2013-10-28 98 views
7

在我的應用程序中,我生成一個公鑰/私鑰對並將它們存儲起來,以便以後在磁盤上使用。加載和重新初始化私鑰工作正常,但對於私鑰我得到一個未知的KeySpec類型:java.security.spec.PKCS8EncodedKeySpec - 我不知道爲什麼。從文件加載公鑰數據

這就是我如何創建並保存鍵(代碼有點簡化爲更易於閱讀):

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
kpg.initialize(4096); 
KeyPair keyPair = kpg.generateKeyPair(); 
privKey =keyPair.getPrivate(); 
pubKey =keyPair.getPublic();   

DataOutputStream out=new DataOutputStream(ctx.openFileOutput(PRIVKEY_FILE,Context.MODE_PRIVATE)); 
byte[] data=privKey.getEncoded(); 
out.write(data); 
out.close(); 

DataOutputStream out=new DataOutputStream(ctx.openFileOutput(PUBKEY_FILE,Context.MODE_PRIVATE)); 
byte[] data=pubKey.getEncoded(); 
out.write(data); 
out.close(); 

私鑰的下一步裝載工作正常:

DataInputStream in=new DataInputStream(ctx.openFileInput(PRIVKEY_FILE)); 
byte[] data=new byte[in.available()]; 
in.readFully(data); 

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data); 
KeyFactory kf = KeyFactory.getInstance("RSA"); 
privKey = kf.generatePrivate(keySpec); 

decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
decryptCipher.init(Cipher.DECRYPT_MODE, privKey); 

類似的代碼公鑰失敗:

DataInputStream in=new DataInputStream(ctx.openFileInput(PUBKEY_FILE)); 
byte[] data=new byte[in.available()]; 
in.readFully(data); 

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data); 
KeyFactory kf = KeyFactory.getInstance("RSA"); 
pubKey = kf.generatePublic(keySpec); --> here the exception is thrown 

encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
encryptCipher.init(Cipher.ENCRYPT_MODE, pubKey);    

那麼我做錯了什麼?從磁盤加載公鑰數據的正確方法是什麼?

謝謝!

回答

14

公鑰和私鑰的編碼方式不同。私鑰在PKCS#8中編碼,而公鑰則不是。根據ASN.1規範,它們被編碼在X.509中。從Key.getFormat()方法

描述:

返回此密鑰的基本編碼格式,或空如果此鍵不支持編碼的名稱。如果存在此密鑰的ASN.1規範,則主要編碼格式將根據相應的ASN.1數據格式命名。例如,公共密鑰的ASN.1數據格式的名稱是SubjectPublicKeyInfo,由X.509標準定義;在這種情況下,返回的格式是「X.509」。同樣,私鑰的ASN.1數據格式的名稱是PrivateKeyInfo,由PKCS#8標準定義;在這種情況下,返回的格式是「PKCS#8」。

據此,不要將公鑰作爲PKCS#8讀取,您應該將其讀爲X.509。

考慮從改變你的公鑰閱讀代碼:

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data); 

到:

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);