一尘不染

从文件加载公钥数据

java

在我的应用程序中,我生成一个公钥/私钥对,并将其存储以供以后在磁盘上使用。加载并重新初始化私钥可以正常工作,但是对于私钥,我得到了一个未知的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);

那我在做什么错?从磁盘加载公共密钥数据的正确方法是什么?

谢谢!


阅读 246

收藏
2020-12-03

共1个答案

一尘不染

公钥和私钥的编码方式不同。私钥在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);
2020-12-03