java - 从文件加载公钥数据

标签 java android rsa public-key

在我的应用程序中,我生成了一个公钥/私钥对并将它们存储在磁盘上供以后使用。加载和重新初始化私钥工作正常,但对于私钥,我得到一个未知的 KeySpec 类型:java.security.spec.PKCS8EncodedKeySpec - 我不知道为什么。

这就是我创建和保存 key 的方式(代码稍微简化以便于阅读):

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() 方法的说明:

Returns the name of the primary encoding format of this key, or null if this key does not support encoding. The primary encoding format is named in terms of the appropriate ASN.1 data format, if an ASN.1 specification for this key exists. For example, the name of the ASN.1 data format for public keys is SubjectPublicKeyInfo, as defined by the X.509 standard; in this case, the returned format is "X.509". Similarly, the name of the ASN.1 data format for private keys is PrivateKeyInfo, as defined by the PKCS #8 standard; in this case, the returned format is "PKCS#8".

据此,您不应将公钥读取为 PKCS #8,而应将其读取为 X.509。

考虑更改您的公钥读取代码:

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data);

到:

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);

关于java - 从文件加载公钥数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19640735/

相关文章:

cryptography - 使用 openssl.exe 使用 256 位 RSA key 签名 20 字节消息,但不在代码中

android - 如何在 Android 上用 Java 发送 ICMP 数据包(带有关联的 TTL 值)?没有第 3 方库是否可能?如果没有,你用什么?

java - 如何在 javadoc 中显示构造函数注释?

java - 根据条件将字符串替换为新字符串

java - 如何在 Struts 2 操作名称中允许使用斜杠?

android - 知道 Firebase 何时完成 API 调用?

android - 哪个第三方库用于在 android 中创建 3d View 条形图?

java - 编码 RSA 算法 Java

java - 使 MessageDigest 和 Cipher 等同于 java.security.Signature

java - Map 和 orElse 返回不同的子类型