将X509公钥转换为RSA公钥



我有一个如下格式的公钥

-----BEGIN PUBLIC KEY----- xxxxxxxx -----END PUBLIC KEY-----

我需要将其转换为以下格式

-----BEGIN RSA PUBLIC KEY----- xxxxxxxxx -----END RSA PUBLIC KEY-----

基本上,问题是我正在使用一个用Java编写的第三方库。

  1. 第三方库使用Java类"RSAPublicKeySpec"从字符串生成RSAPublicKey类型的实例。

  2. 我提供给这个第三方库的字符串取自以下格式的文件:

-----BEGIN PUBLIC KEY----- xxxxxxxx -----END PUBLIC KEY-----

在对代码进行了一些研究之后,我可以看到,如果我使用java类"X509EncodedKeySpec"来加载这个公钥,那么我的代码的签名验证部分就可以完美地工作。但是,由于代码是第三方库,因此我无法更改其代码中的类类型。我需要以某种方式确保我提供给库的输入与"rsappublickeyspec"类兼容,以便正确加载公钥。

RSA PUBLIC key;格式在早期的SSLeay中使用,后来演变成OpenSSL,但我相信在2000年之前就过时了,这是Java的早期阶段,我认为在Java有任何加密之前,甚至是允许从美国出口的受限类型。简而言之,RSA公钥格式是来自pkcs# 1的rsa特定格式,而"公钥";是处理多种(和可扩展)算法的X.509通用结构。因此,了解Java库的开发人员是如何陷入这种奇怪的限制是很有趣的。但无论如何…

虽然这种格式早就过时了,但是OpenSSL仍然支持它。如果您有可用的openssl命令行(可能是在另一个系统上,您可以将文件/数据复制到和返回),只需执行:

openssl rsa -in publickey.pem -out rsapublickey.pem -pubin -RSAPublicKey_out 

啊!写完下面的代码后,现在我注意到在Java中以pkcs# 1格式生成RSA密钥的(更普遍的)欺骗如果你在Java中使用BouncyCastle(或在C中使用OpenSSL库,但你已经有上面的OpenSSL命令行选项)。

无论如何,这里是在中编写纯Java代码的两种方法的大纲如果你喜欢的话:
  • 它们都以将输入的PEM转换为字节开始。阅读"----BEGIN"线和最好检查它是正确的;读取以下所有行(base64),但不包括"-----END"行;将base64串接并解码为字节。Java8提供java.util.Base64;在此之前,你必须摆弄"内部"。类,或者添加一个通用的(但不是内置的)库,比如common -codecs,或者自己编写(这并不难)。现在选择步骤1或步骤2。

  • 解析这些字节作为RFC 5280中所示的X.509 SubjectPublicKeyInfo的ASN.1 DER编码,包括AlgorithmIdentifier。确切地说:跳过外序列的标签和长度;跳过标签,长度和AlgorithmIdentifier的内容——或者更好地提取内容,并检查它是rsaEncryption和NULL(或可能省略)参数的OID的SEQUENCE;然后跳过位字符串的标记、长度和第一个字节(未使用的位),并将(剩余的)内容作为编码的密钥——这已经是您想要的pkcs# 1 RSAPublicKey结构。3.

  • 使用标准JCE 读取X.509格式密钥:将字节包装在X509EncodedKeySpec中,将其交给KeyFactory中的.generatePublic()用于RSA,并将结果强制转换为RSAPublicKey。然后调用.getModulus().getPublicExponent()来获取数学值,并在asn . 1der中使用pkcs# 1 rfc3447中定义的RSAPublicKey结构对进行编码(用于PKIX/X)。rfc3279 2.2.1 . 509)。BigInteger.toByteArray()给出了ASN.1想要的大端双s补码形式,所以它包括:获取两个.toByteArray()值,为每个值添加tag=INTEGER (0x02)和长度前缀,然后为它们的连接添加tag=SEQUENCE-composite (0x30)和长度前缀。然后进行步骤3。

  • 现在你有了组成pkcs# 1 RSAPublicKey的字节,转换为PEM:编码为base64;如果需要,分行(64个字符),或者总是为了安全;并加上"BEGIN"one_answers";以何种;行,除非不需要

  • 最新更新