2011-03-03 117 views

回答

3

从理论的角度来看,公钥可以通过私钥重新计算(计算成本稍低于生成单个ECDSA签名的成本,或者执行ECDH的一半,因此速度很快) 。因此,从概念上讲,您只需存储私钥,其标准格式为PKCS#8,这是由Java支持的java.security.spec.PKCS8EncodedKeySpec。此外,PKCS#8格式还包含了可选项,用于在同一个blob中沿着私钥对公钥进行编码,因此这看起来就像您正在寻找的内容。

然而,棘手的事情是说服加密提供者(例如BouncyCastle)提取公共密钥和/或重新计算它。显然,如果您从包含公钥的PKCS#8编码的EC私钥创建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中实现。

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(); 

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