RSA-Java';在bouncycastle';s的PEM解析器成功

RSA-Java';在bouncycastle';s的PEM解析器成功,java,rsa,bouncycastle,Java,Rsa,Bouncycastle,我有一个PEM格式的公钥(从iOS设备接收): 如果我尝试使用KeyFactory将其解析为公钥,如下所示: KeyFactory kf = KeyFactory.getInstance("RSA"); Pattern parse = Pattern.compile("(?m)(?s)^---*BEGIN.*---*$(.*)^---*END.*---*$.*"); String encoded = parse.matcher(pemPubKey).replaceFirst("$1"); byt

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

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

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));
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
}
我得到:
java.security.InvalidKeyException:IOException:algid解析错误,不是序列

但是当我使用像这样的
bouncycastle
时:

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));
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
}
我得到了一个有效的
公钥
,并且正确识别了算法

为什么java的解析器在这里失败?我是否正确地从
SubjectPublicKeyInfo
迁移到
PublicKey

更新

我已尝试使用
openssl
验证密钥:

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

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

$openssl rsa-通知PEM-pubin-in-pub.PEM-text-noout无法 加载公钥140735659656136:错误:0D0680A8:asn1编码 例行程序:ASN1\u检查\u t错误 标签:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c:1164: 140735659656136:错误:0D07803A:asn1编码 例程:ASN1\U项目\U EX\U D2I:嵌套ASN1 错误:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c:314:Type=X509_ALGOR 140735659656136:错误:0D08303A:asn1编码 例程:ASN1\U模板\U NOEXP\U D2I:嵌套ASN1 错误:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c:653:Field=algor, 类型=X509_PUBKEY 140735659656136:错误:0906700D:PEM 例行程序:PEM\U ASN1\U read\U bio:ASN1 lib:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pem/pem_oth.c:84:


Java的解析器没有失败,您的公钥不是Java的
X509EncodedKeySpec
所期望的已编码SubjectPublicKeyInfo结构的实例。我还没有通过Bouncycastle例程了解它成功的原因,但是PEMParser设计用于解析许多不同类型的所谓“PEM”文件

SubjectPublicKeyInfo在中定义为:

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


关于“PEM”文件的最后一句话。在将某些内容描述为“PEM”格式时需要小心,因为PEM实际上不是一种特定的格式。“PEM”只不过是在base64中编码一个真正的格式,然后将base64包装在“----开始------”和“----结束------”行中,希望在这两行中唯一地描述base64编码的数据是什么

谢谢你的回答。那么你实际上是说BC“组成”了算法id还是使用了默认id?有没有一个好的工具可以用来可视化/解析asn1结构?或者我应该手动操作?我最喜欢的工具是。它希望看到base64编码的数据,然后对其进行解码、解析、缩进、显示alg标识符。请使用公钥尝试,但必须删除“开始”和“结束”行,以及所有引号和“\n”“等等,这样你就有了base64部分。谢谢,我会试试看。你是对的,没有算法id。这个工具真的很有用!我现在可以深入研究苹果设备提供的奇怪结构,理解为什么Java/openssl不能处理它们。。。
RSAPublicKey ::= SEQUENCE {
             modulus           INTEGER,  -- n
             publicExponent    INTEGER   -- e
         }