从 Bouncy Castle 中的文本创建 RSA 公钥的问题

Posted

技术标签:

【中文标题】从 Bouncy Castle 中的文本创建 RSA 公钥的问题【英文标题】:Problem creating RSA public key from text in Bouncy Castle 【发布时间】:2019-08-30 06:08:06 【问题描述】:

我在从公钥文本创建公钥时遇到问题。我从这个链接Creating RSA Public Key From String 找到了解决方案。他们提到将 Bouncy Castle(轻量级 API)作为一个库来解决将公钥字符串转换为 RSA 公钥时出现的 InvalidKeySpecException 错误。但是这个解决方案在我的情况下失败了。程序在这里抛出异常

线程“main”java.lang.IllegalArgumentException 中的异常:错误的序列大小:9

Creating RSA Public Key From String

   String publicKeyB64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3AQKDhhtcM5A1a8R9/VX" +
            "mrocKGaQlat2/MRFy/Y1fTabYyKkfgaRXyrHiRn+imq3ljEgx/vLRTTPtLt8H79a" +
            "iMU6WJkQwG504NCnDRVB9DZBoAYDtBkjtje7I2Xs3tzvlNwM0bcCmmj/6QE9rHEv" +
            "xhvvXO8M332hINORLNiCF6NvYHrIVSa8EU4F0bnlWpoNi0YhP45uyOOuPpVmsaxp" +
            "MWOycf3nTICKK5BDylnVO7kMcL1utJxOOb1fsotaLuge4fF84DG4cPpLZko3ksB/" +
            "voOLTDv5QRsn++8qRciK4sptlnOs8g2TrXjE/rZlP9QmpUV4a3iQ1WmsqWQVizmw" +
            "PwIDAQAB";

    byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
    org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(decoded);
    BigInteger modulus = pkcs1PublicKey.getModulus();
    BigInteger publicExponent = pkcs1PublicKey.getPublicExponent();
    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PublicKey generatedPublic = kf.generatePublic(keySpec);
    System.out.printf("Modulus: %X%n", modulus);
    System.out.printf("Public exponent: %d ... 17? Why?%n", publicExponent); // 17? OK.
    System.out.printf("See, Java class result: %s, is RSAPublicKey: %b%n", generatedPublic.getClass().getName(), generatedPublic instanceof RSAPublicKey);

所以我真的很期待处理这个问题的建议。

【问题讨论】:

您的数据不是 RSA 公钥,它是 RSA 私钥,采用 PKCS1 aka CRT 形式,允许提取私钥或公钥字段。使用org.bouncycastle.asn1.pkcs.RSAPrivateKey——并且不要将该密钥用于任何事情,因为它已被泄露。 对此我很抱歉。我更新了公钥,但它抛出 Exception in thread "main" java.lang.IllegalArgumentException: invalid object in getInstance: org.bouncycastle.asn1.DLSequence 【参考方案1】:

如果您的公钥是正确的,那么您应该能够在命令行上读取它以解决问题。尝试使用这些命令:

$ openssl rsa -inform PEM -pubin -in pub.key -text -noout
$ openssl pkey -inform PEM -pubin -in pub.key -text -noout

将“pub.key”替换为您的公钥文件。

【讨论】:

这仅适用于 X.509 SubjectPublicKeyInfo 格式的(公共)密钥,OpenSSL 调用 PUBKEY,Java 调用 X509EncodedKeySpec,并且仅当您添加正确的 PEM BEGIN 和 END 行时。这不是 RSA 公钥的唯一有效表示 - 尽管此 Q 中的密钥不是 RSA 公钥的任何表示。 对此我很抱歉。我在我的代码中更新了公钥,但它抛出 Exception in thread "main" java.lang.IllegalArgumentException: invalid object in getInstance: org.bouncycastle.asn1.DLSequence【参考方案2】:

您现在编辑的数据是公钥,但不是PKCS1格式;它采用更常见(通常更有用)的 X.509 SubjectPublicKeyInfo 格式。 the Q you linked 中解释了这种差异。虽然 BouncyCastle 支持这种格式,但 Java 加密 (JCA) 也使用(技术上不精确的)名称 X509EncodedKeySpec 直接支持这种格式,所以这样做要简单得多:

byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey generatedPublic = kf.generatePublic(new X509EncodedKeySpec(decoded));

【讨论】:

以上是关于从 Bouncy Castle 中的文本创建 RSA 公钥的问题的主要内容,如果未能解决你的问题,请参考以下文章