java - 在 Java 中加载 RSA 私钥(algid 解析错误,不是序列)

标签 java encryption openssl rsa

我正在尝试将使用 ssl 生成的私有(private) RSA key 加载到 java 中,我的代码是:

生成 key :

openssl genrsa -out mykey.pem 1024

结果:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCUibP4fY2PA/sGMKMbU6usuIGcOAqgQjD6c2ylVo05Oz7pgjnE
+O0l2MFRUYUGT5KKk/W+0cAXkxaQHE3n8A8X1mHT8eMDmWnzz0PeYjDE8LQmAw8R
Y2FnVKFAB36BIjdb5FsZmCk5QYKU5+nWLMqH/j/IR5AyX5wR2SMoslUg2QIDAQAB
AoGAeJ1s7638IhLIZtldyRXjRKi6ToFPV50IKodJxOSIXt3WE0V05ZaA84eUSxUY
IOzCgRbuqVmnUz1USAdD18AecC8qc7tXTRALLy7q8fxklPwmGPUOvTFmI7gRMUnv
cWrq1gySk3SKpj0YmWnuY9Xmd2+xoWLzUeFD1CROY5OTjIECQQDDlp1+Al7+duR0
XyMlkWLIk0nIbkQ5zlTAEipzmaeTSOJi6YG3EMMz3AGuZb7tw6HFxWqeg1hyKJ+T
cTM3WTdJAkEAwmrCDKE29n3wFOBKsZZFQbDgVOUXCBs2ubEI+ALe1DJU5BlfnrhJ
OINRCNgnwSFNbwxDTkDpR6J6Av2ElAvNEQJAV0dVvk5Wj50Ecz2lFHWdLD41taAn
B9igDxnMIcvWcK4cf+ENhmCPiwvJIEa8/aLIBNYErvmTtVWVaBkirrc8KQJABr+z
+sJB6S6X/fGHRkDkKJKeRvQo54QiUzHdENbwq0cQAVcMJbNZ/1c3oen2/1JLoNY5
I+dG8dCnEaGBT65VMQJBAIDqH1Kqs5tb51cpt6h9ot31SUVud5pSML/babwp3pRs
1s6poreym4PkAyRug0Dgcj1zVLt25TlOHvrL9r3Swq8=
-----END RSA PRIVATE KEY-----

加载:

String privKeyPEM=readFile("mykey.pem");
privKeyPEM= privKeyPEM.replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("\n", "");
// Remove the first and last lines
privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
System.out.println(privKeyPEM);

// Base64 decode the data
byte [] encoded = Base64.decode(privKeyPEM);

// PKCS8 decode the encoded RSA private key
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);

// Display the results
System.out.println(privKey);

它会抛出 IOException : algid parse error, not a sequence。哪里出错了?

Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)
at java.security.KeyFactory.generatePrivate(Unknown Source)
at base54.encrypt.RSAToy.main(RSAToy.java:36)
Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source)
at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source)

最佳答案

根据 Julien Kronegg 的回答,如果您因为文件具有 PKCS#1 格式而收到此错误,则可以使用以下步骤将其转换为 PKCS#8 文件。

首先,将您的 PKCS#1 key 文件保存到名为 priv1.pem 的文件中:

-----BEGIN RSA PRIVATE KEY-----
[...]
-----END RSA PRIVATE KEY-----

然后,执行以下命令:

openssl pkcs8 -topk8 -inform PEM -outform PEM -in priv1.pem -out priv8.pem -nocrypt

这会生成一个名为 priv8.pem 的文件,这是您的 PKCS#8 格式的 key 文件:

-----BEGIN PRIVATE KEY-----
[...]
-----END PRIVATE KEY-----

我在 Java 中使用如下:

String PRIVATE_RSA_KEY_PKCS8 = 
    "-----BEGIN PRIVATE KEY-----\n" +
    "MDSTofml23d....\n" +
    [...] +
    "-----END PRIVATE KEY-----\n";
String key = PRIVATE_RSA_KEY_PKCS8
    .replace("-----BEGIN PRIVATE KEY-----\n", "")
    .replace("\n-----END PRIVATE KEY-----\n", "");
PKCS8EncodedKeySpec keySpec =
    new PKCS8EncodedKeySpec(DatatypeConverter.parseBase64Binary(key));
try {
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] bytes = parseBase64Binary(encryptedNodeIdentifier);
    byte[] decryptedData = cipher.doFinal(bytes);
    return new String(decryptedData);
} catch (GeneralSecurityException e) {
    return "";
}

关于java - 在 Java 中加载 RSA 私钥(algid 解析错误,不是序列),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15344125/

相关文章:

java - 自定义 ListView 未按应有的方式更新

java - 通过套接字接收 Diffie-Hellman key 错误

java - Android 中的 Diffie Hellman key 交换

java - 从PFX文件中读取私钥,用该私钥解密密文

delphi - 使用 DCrypt 在 Delphi (10 Seattle) 中使用 AES 加密字符串,使用 PHP/OpenSSL 解密

java - 使用自定义字体 [java.io.IOException : Error reading font data.]

java - 将多行日志文件分解为事件流或迭代器

java - 输入输出异常处理

c++ - vs2015 cuda9.0 链接 SHA1_Init 与 CUDA 实现而不是 openssl cpu 库

windows - 如何检查 openssl 库是否使用经过 FIPS 验证的密码术