RSA - Java 的 KeyFactory 失败,而 bouncycastle 的 PEM 解析器成功



我有一个PEM格式的公钥(从iOS设备接收(:

String pemPubKey = ""+
"-----BEGIN RSA PUBLIC KEY-----n"+
"MIIBCgKCAQEA07ACQHTTrgX7ddNtyamh58xwD+S+pSrJz/Rah4zj0HIg4V/Ok5vkn"+
"Wx6y4UyuKLCtefeiB2ipg/n1ZZ0eRac1B4UwPhAtILGQzgIUgOp0cQ3Cb94ugq92n"+
"wxkxeEdWmIFIlXgWOf6I8yWp9DZaigrRhA2kPbY01zKxCsX1ZxKMVu2sU/HM1hJyn"+
"aebLLND002yLzuRDLXbacmCt5U6vDQDjBmm3uZ26fEMF+GTCnn6fJBq5RDfRKjpSn"+
"fVM0mCePO9RHiwu3oHfqoyLA2QGlCexXcIYq7KbJjC9vcamAWRqQdHlsSj5ezDTRn"+
"GofA6HtQ+zNdGHOvqsYtbN8MJSlUXXy39wIDAQABn"+
"-----END RSA PUBLIC KEY-----";

如果我尝试使用KeyFactory将其解析为PublicKey,如下所示:

KeyFactory kf = KeyFactory.getInstance("RSA");
Pattern parse = Pattern.compile("(?m)(?s)^---*BEGIN.*---*$(.*)^---*END.*---*$.*");
String encoded = parse.matcher(pemPubKey).replaceFirst("$1");
byte[] pem = Base64.getMimeDecoder().decode(encoded);
PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(pem));

我得到:java.security.InvalidKeyException: IOException: algid parse error, not a sequence

但当我像那样使用bouncycastle时:

SubjectPublicKeyInfo subjectPublicKeyInfo =
    (SubjectPublicKeyInfo) new PEMParser(new StringReader(pemPubKey)).readObject();
PublicKey pubKey;
if (PKCSObjectIdentifiers.rsaEncryption == subjectPublicKeyInfo.getAlgorithm().getAlgorithm()) {
    DLSequence der = (DLSequence) subjectPublicKeyInfo.parsePublicKey().toASN1Primitive();
    ASN1Object modulus, exponent;
    modulus = (ASN1Object) der.getObjectAt(0);
    exponent = (ASN1Object) der.getObjectAt(1);
    RSAPublicKeySpec spec =
            new RSAPublicKeySpec(new BigInteger(modulus.toString()), new BigInteger(exponent.toString()));
    KeyFactory factory = KeyFactory.getInstance("RSA");
    pubKey = factory.generatePublic(spec);
} else {
    // Throw some exception
}

我得到了一个有效的PublicKey,并且算法被正确识别。

为什么java的解析器在这里失败了?我是否正确地执行了从SubjectPublicKeyInfoPublicKey的迁移?

更新

我试着用openssl:验证密钥

$openssl-rsa-通知PEM-pubin-in pub.PEM-text-noout无法加载公钥140735659656136:错误:0906D06C:PEM例程:PEM_read_bio:无启动line:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-2.50.2/libressl/crypto/pem/pem_lib.c:704:预期:公钥

从页眉/页脚中删除RSA后:

$openssl-rsa-通知PEM-pubin-in pub.PEM-text-noout无法加载公钥140735659656136:错误:0D0680A8:asn1编码例程:ASN1_CHECK_TLEN:错误标签:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-2.50.2/libressl/crypto/asn1/tasn_dec.c:1164:140735659656136:错误:0D07803A:asn1编码例程:ASN1_ITEM_EX_DII:嵌套ASN1错误:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-2.50.2/libressl/crypto/asn1/tasn_dec.c:314:类型=X509_ALGOR140735659656136:错误:0D0803A:asn1编码例程:ASN1_EMPLATE_NOEXP_D2I:嵌套ASN1错误:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-2.50.2/libressl/crypto/asn1/tasn_dec.c:653:Field=algor,类型=X509_PUBKEY 140735659656136:错误:0906700D:PEM例程:PEM_ASN1_read_bio:ASN1lib:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-2.50.2/libressl/crypto/pem/pem_oth.c:84:

Java的解析器没有失败,您的公钥是而不是Java的X509EncodedKeySpec所期望的编码SubjectPublicKeyInfo结构的实例。我还没有通过Bouncycastle例程来了解它为什么成功,但PEMParser被设计为解析许多不同类型的所谓";PEM";文件。

SubjectPublicKeyInfo在RFC 5280中定义为:

SubjectPublicKeyInfo  ::=  SEQUENCE  {
     algorithm            AlgorithmIdentifier,
     subjectPublicKey     BIT STRING
}

您的公钥是一个简单的PKCS#1RSAPublicKey,在RFC 8017中定义为:

RSAPublicKey ::= SEQUENCE {
             modulus           INTEGER,  -- n
             publicExponent    INTEGER   -- e
         }

关于";PEM";文件。当你把某事描述为";PEM";格式,因为PEM实际上并不是一种特定的格式"PEM";只不过是用base64编码一个真正的格式-----开始-----";以及"-----结束-----";行,其中希望唯一地描述base64编码数据是什么。

最新更新