从 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 公钥的问题的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Bouncy Castle 创建与 OpenSSH 兼容的 ED25519 密钥?
Bouncy Castle 从公钥加密会话数据包中提取 PGP 会话密钥
在没有 Bouncy Castle 的情况下,如何在 java 中从私有(ecdsa)生成公钥?