2011-03-03 139 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)加密編碼後的私鑰,否則文件將被盜取,然後你無限期暴露。