在我的应用程序中,我生成一个公钥/私钥对,并将其存储以供以后在磁盘上使用。加载并重新初始化私钥可以正常工作,但是对于私钥,我得到了一个未知的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);
那我在做什么错?从磁盘加载公共密钥数据的正确方法是什么?
谢谢!
公钥和私钥的编码方式不同。私钥在PKCS#8中编码,而公钥则没有。相反,它们根据ASN.1规范在X.509中编码。
Key.getFormat()方法的描述:
返回此密钥的主要编码格式的名称;如果此密钥不支持编码,则返回null。如果存在针对此密钥的ASN.1规范,则根据适当的ASN.1数据格式来命名主要编码格式。例如,公共密钥的ASN.1数据格式的名称是X.509标准定义的SubjectPublicKeyInfo。在这种情况下,返回的格式为“ X.509”。同样,私钥的ASN.1数据格式的名称是PrivateKeyInfo,如PKCS#8标准所定义;在这种情况下,返回的格式为“ PKCS#8”。
据此,您应该将其读取为X.509,而不是将其作为PKCS#8读取。
考虑从以下位置更改您的公共密钥读取代码:
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data);
至:
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);