如果我想将私钥和公钥都存储在一个文件中,那么最简单的格式是什么?特别是如果我打算将BouncyCastle库用于Java?
答案 0 :(得分:3)
从理论的角度来看,可以从私钥重新计算公钥(计算成本略低于生成单个ECDSA签名的成本,或者执行ECDH的一半,因此速度很快)。因此,从概念上讲,您只需存储私钥,其标准格式为PKCS#8,Java支持java.security.spec.PKCS8EncodedKeySpec
。此外,PKCS#8格式包括可选地在同一个blob中沿私钥编码公钥的规定,所以这看起来就像你正在寻找的那样。
PKCS8EncodedKeySpec
,该私钥也包含公钥,BouncyCastle将足够内部保留编码公钥的副本并在您决定时将其写回以PKCS#8格式重新编码私钥。但是,它没有任何其他功能;它将其作为不透明的blob处理。
因此,您必须重新计算公钥。浏览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
类,但是在BouncyCastle中似乎尚未实现clean方法。
答案 1 :(得分:0)
试试这个(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();
其中rawPrivKey
和rawPubKey
是字节类型的数组
我建议你使用分组密码(即AES)加密编码的私钥,否则文件会被盗,然后你无限期暴露。