在我的应用程序中,我生成一个公钥/私钥对并将它们存储在磁盘上以供以后使用。加载和重新初始化私钥工作正常,但对于私钥,我得到了一个未知的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"。
据此,与其将公钥读取为 PKCS #8,不如将其读取为 X.509。
请考虑将公钥读取代码从以下位置更改为:
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data);
自:
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);