从文件加载公钥数据

Elm*_*lmi 7 java android rsa public-key

在我的应用程序中,我生成一个公钥/私钥对并存储它们以供以后在磁盘上使用.加载和重新初始化私钥工作正常,但对于私钥,我得到一个未知的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();
Run Code Online (Sandbox Code Playgroud)

下一次加载私钥工作正常:

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);
Run Code Online (Sandbox Code Playgroud)

类似的公钥代码惨遭失败:

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);             
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

ini*_*mfs 14

公钥和私钥的编码方式不同.虽然私钥是在PKCS#8中编码的,但公钥却不是.它们根据ASN.1规范在X.509中编码.

Key.getFormat()方法的描述:

返回此键的主要编码格式的名称,如果此键不支持编码,则返回null.如果存在此密钥的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);
Run Code Online (Sandbox Code Playgroud)

至:

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);
Run Code Online (Sandbox Code Playgroud)