EC 公钥/私钥的文件格式?

发布于 2024-10-20 11:47:30 字数 71 浏览 6 评论 0原文

如果我想将私钥和公钥存储在一个文件中,最容易使用的格式是什么?特别是如果我打算使用 Java 的 BouncyCastle 库?

If I wanted to store both a private and a public key in a single file, what would be the easiest format to use? Especially if I'm planning to use the BouncyCastle library for Java?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冰雪梦之恋 2024-10-27 11:47:30

从理论上来看,公钥可以从私钥重新计算出来(计算成本略低于生成单个 ECDSA 签名的成本,或者做 ECDH 的一半,所以速度很快)。因此,从概念上讲,您只需存储私钥,其标准格式为 PKCS#8,Java 通过 java.security.spec.PKCS8EncodedKeySpec 支持它。此外,PKCS#8 格式包括在同一 blob 中选择性地对公钥和私钥进行编码的规定,因此这看起来确实像您正在寻找的内容。

然而,棘手的事情是说服密码提供者(例如 BouncyCastle)提取公钥和/或重新计算它。显然,如果您从 PKCS#8 编码的 EC 私钥(也包含公钥)创建 PKCS8EncodedKeySpec,BouncyCastle 将很友好地在内部保留编码公钥的副本并将其写回如果您决定以 PKCS#8 格式重新编码私钥。然而,它并没有做任何其他事情。它将它作为一个不透明的斑点来处理。

因此您必须重新计算公钥。通过 JCE 和 BouncyCastle API 以及未实现的位,我发现了以下内容,它似乎可以工作(JDK 1.6.0_24,BouncyCastle 1.46):

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Provider;
import java.security.spec.PKCS8EncodedKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JCEECPrivateKey;
import org.bouncycastle.jce.provider.JCEECPublicKey;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;

// Create the provider and an appropriate key factory.
Provider pp = new BouncyCastleProvider();
KeyFactory kf = KeyFactory.getInstance("EC", pp);

// Decode the private key (read as a byte[] called 'buf').
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(buf);
PrivateKey sk = kf.generatePrivate(ks);

// Recompute public key.
JCEECPrivateKey priv = (JCEECPrivateKey)sk;
ECParameterSpec params = priv.getParameters();
ECPublicKeySpec pubKS = new ECPublicKeySpec(
    params.getG().multiply(priv.getD()), params);
PublicKey pk = kf.generatePublic(pubKS);

// To reencode the private key.
buf = kf.getKeySpec(sk, PKCS8EncodedKeySpec.class).getEncoded();

从概念上讲,我应该将 kf.getkeySpec()org.bouncycastle.jce.spec.ECPrivateKeySpec 而不是无情地将私钥强制转换为 JCEECPrivateKey 类,但 clean 方法似乎尚未在 BouncyCastle 中实现。

On a theoretical point of view, the public key can be recomputed from the private key (computational cost for that is slightly lower than the cost for producing a single ECDSA signature, or doing half of ECDH, so it is fast). Therefore, conceptually, you only have to store the private key, and the standard format for that is PKCS#8, which is supported by Java with java.security.spec.PKCS8EncodedKeySpec. Moreover, the PKCS#8 format includes provisions for optionally encoding the public key along the private key in the same blob, so this really looks like what you are looking for.

The tricky thing, however, is to convince the cryptographic provider (e.g. BouncyCastle) to extract the public key as such and/or recompute it. Apparently, if you create a PKCS8EncodedKeySpec from a PKCS#8-encoded EC private key which also contains the public key, BouncyCastle will be kind enough to internally keep a copy of the encoded public key and write it back if you decide to reencode the private key in PKCS#8 format. However, it does nothing else with it; it handles it as an opaque blob.

Hence you must recompute the public key. Wading through the JCE and BouncyCastle API and unimplemented bits, I found the following, which appears to work (JDK 1.6.0_24, BouncyCastle 1.46):

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Provider;
import java.security.spec.PKCS8EncodedKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JCEECPrivateKey;
import org.bouncycastle.jce.provider.JCEECPublicKey;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;

// Create the provider and an appropriate key factory.
Provider pp = new BouncyCastleProvider();
KeyFactory kf = KeyFactory.getInstance("EC", pp);

// Decode the private key (read as a byte[] called 'buf').
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(buf);
PrivateKey sk = kf.generatePrivate(ks);

// Recompute public key.
JCEECPrivateKey priv = (JCEECPrivateKey)sk;
ECParameterSpec params = priv.getParameters();
ECPublicKeySpec pubKS = new ECPublicKeySpec(
    params.getG().multiply(priv.getD()), params);
PublicKey pk = kf.generatePublic(pubKS);

// To reencode the private key.
buf = kf.getKeySpec(sk, PKCS8EncodedKeySpec.class).getEncoded();

Conceptually, I should use kf.getkeySpec() with org.bouncycastle.jce.spec.ECPrivateKeySpec instead of ruthlessly casting the private key to the JCEECPrivateKey class, but the clean method appears not to be implemented yet in BouncyCastle.

风尘浪孓 2024-10-27 11:47:30

试试这个(BouncyCastle v1.47,使用 JDK 1.7.*,但我认为 JDK 1.6.* 也可以):

// Recreate the private key.
final KeyFactory kf = KeyFactory.getInstance("EC", "BC");
final PKCS8EncodedKeySpec encPrivKeySpec = new PKCS8EncodedKeySpec(rawPrivKey);
final PrivateKey privKey = kf.generatePrivate(encPrivKeySpec);
final byte[] rawPrivKey = privKey.getEncoded();

// Recreate the public key.
final X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(rawPubKey);
final PublicKey pubKey = kf.generatePublic(pubKeySpec);
final byte[] rawPubKey = pubKey.getEncoded();

其中 rawPrivKeyrawPubKey 是字节类型的数组。
我建议您使用分组密码(即 AES)加密编码的私钥,否则文件可能会被盗,然后您将无限期暴露。

Try this (BouncyCastle v1.47, using JDK 1.7.* but I assume JDK 1.6.* will be fine too):

// Recreate the private key.
final KeyFactory kf = KeyFactory.getInstance("EC", "BC");
final PKCS8EncodedKeySpec encPrivKeySpec = new PKCS8EncodedKeySpec(rawPrivKey);
final PrivateKey privKey = kf.generatePrivate(encPrivKeySpec);
final byte[] rawPrivKey = privKey.getEncoded();

// Recreate the public key.
final X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(rawPubKey);
final PublicKey pubKey = kf.generatePublic(pubKeySpec);
final byte[] rawPubKey = pubKey.getEncoded();

where rawPrivKey and rawPubKey are arrays of byte type.
I suggest you encrypt the encoded private key with a block cipher (i.e. AES) otherwise the file is subject to be stolen and then you are indefinitely exposed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文