java - 如何从 Java 中的 *pem 字符串生成 RSA 私钥

标签 java rsa private-key pem der

我想从 Java 中的字符串(.pem 文件)生成私钥。

private static final String test = "-----BEGIN RSA PRIVATE KEY-----\n" +
         "MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" +
// and so on
         "-----END RSA PRIVATE KEY-----";

try {
    String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");

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

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey privKey = kf.generatePrivate(keySpec);
}
catch (Exception e) {
    e.printStackTrace();
}

最后一行(generatePrivate 函数)抛出了这个异常:

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 Test.main(Test.java:52)
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)
    ... 3 more

如果我将私钥更改为 .der 文件中的值,它可以正常工作,但我需要从 .pem 文件生成私钥文件。

我附上了打印为字符串的字节的屏幕截图(一次使用\n 进行硬编码,一次不使用\n 进行硬编码),一次来自文件。

Bigger Image

Output

奇怪的是文件的输出与字符串的输出不同。

如果我尝试使用 Base64 对 .der 文件进行编码,结果与 .pem 文件中的字符串不同。为什么会这样?

最佳答案

你说最后一行抛出异常,即

PrivateKey privKey = kf.generatePrivate(keySpec);

上一行适用于设置正确的关键规范,即

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);

所以实际问题是编码字节数组。您是否在 byte [] encoded = Base64.decode(privKeyPEM); 之后完成了 System.out 并查看输出是什么。

我知道如果邮件是 MIME 格式,那么在某些字符之后它会附加回车符和换行符的组合,这样字符串对于电子邮件系统或您使用它的任何地方都不会太长。

最后的 String 测试在您使用的原始文本中有一些 '\n'。您确实删除了下一行中的其他文本,

String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");

但是,看看字符串,

"MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" +
// and so on
         "-----END RSA PRIVATE KEY-----";

它可能还剩下一些 '\n',这可能会在您生成 keyspec 时导致一些不需要的字符。尝试更多 System.out 并查看编码的字节数组是什么样的,然后再检查 String privKeyPEM 并查看其中是否没有留下任何额外的字符。

希望这会有所帮助。

关于java - 如何从 Java 中的 *pem 字符串生成 RSA 私钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18369330/

相关文章:

java - jar 没有复制到 Tomcat 的 lib 文件夹

ssh - 使用 openssl libcrypto 解析新的 openssh-key-v1 格式

java - 根据用户定义的结果和条件在包含多个相关或不相关表的数据库中动态构建 SQL

Java 泛型难题 - 获取泛型类型的对象的类/类型,以便稍后确定类型

java - 为什么 Java 中的 BigInteger.isProbablePrime() 函数对负数返回 true?

ssl - OpenSSL:openssl s_client 验证返回:1 但验证返回码:0(确定)

encryption - 为什么 WebCryptoAPI RSA-OAEP 加密函数无法使用给定 key 大小的预期最大块大小?

c++ - RSA解密C++的私钥

linux - 在 python 中等效的 openssl 命令?

java - 文档获取添加/更新/删除时 Lucene 索引文件的更改?