我有以下格式的公钥
-----BEGIN PUBLIC KEY-----
xxxxxxxx
-----END PUBLIC KEY-----
我需要将其转换为以下格式
-----BEGIN RSA PUBLIC KEY-----
xxxxxxxxx
-----END RSA PUBLIC KEY-----
基本上,问题是我正在使用用Java编写的第三方库。
第三方库使用Java类“RSAPublicKeySpec”从String生成RSAPublicKey类型的实例。
我提供给第三方库的字符串取自以下格式的文件:
-----BEGIN PUBLIC KEY-----
xxxxxxxx
-----END PUBLIC KEY-----
答案 0 :(得分:5)
“RSA PUBLIC KEY”格式在早期的SSLeay中使用,后来演变为OpenSSL,但在2000年之前已经过时了,我相信,这是Java的早期阶段,我认为在Java之前 < em>任何加密即使是受限制的那样也允许从美国出口。简而言之,“RSA PUBLIC KEY”格式是来自PKCS#1的RSA特定格式,而“PUBLIC KEY”是处理大量(和可扩展)算法的X.509通用结构。因此,了解Java库的开发人员如何将自己置于这种奇怪的限制中会很有趣。但无论如何......
虽然这种格式已经过时,但 OpenSSL仍支持。如果你有openssl命令行可用(可以在你将文件/数据复制到另一个系统的另一个系统上),那就做:
openssl rsa -in publickey.pem -out rsapublickey.pem -pubin -RSAPublicKey_out
唉!写了下面的内容,现在我注意到Generating RSA keys in PKCS#1 format in Java处的(更一般的)欺骗 (如果你在Java中使用BouncyCastle(或者在C中使用OpenSSL库,但你已经在上面使用了OpenSSL命令行选项),那么(以及那里的几个链接)。
无论如何,如果您愿意,可以使用以下两种方式概述普通Java :
0)它们都是通过将输入PEM转换为字节开始。阅读“---- BEGIN”行,最好检查一下是否正确;读取所有以下行(base64),但不包括“----- END”行;将base64连接并解码为字节。 Java8提供java.util.Base64
;在此之前,你必须摆弄“内部”类或添加几个常见(但不是内置)库之一,如commons-codecs或自己编写(这并不难)。现在选择第1步或第2步。
1)解析这些字节作为ASN.1 DER的X.509 SubjectPublicKeyInfo as shown in RFC 5280编码,包括AlgorithmIdentifier。确切地说:跳过外部序列的标签和长度;跳过AlgorithmIdentifier的标签,长度和内容 - 或者更好地提取内容并检查它是否为rsaEncryption和NULL(或可能省略)参数的OID的SEQUENCE;然后跳过 BIT STRING 的标记和长度以及第一个字节(未使用的位),并将(剩余的)内容作为编码密钥 - 这已经是PKCS #1你需要的RSAPublicKey结构。继续第3步。
2)或使用标准JCE来读取X.509格式键:将字节包装在X509EncodedKeySpec
中,将其提供给{{1}用于RSA的.generatePublic()
,并将结果转换为KeyFactory
。然后调用RSAPublicKey
和.getModulus()
以获取数学值并在ASN.1 DER中对其进行编码,结构为RSAPublicKey defined in PKCS#1 rfc3447(用于PKIX / X.509 in rfc3279 2.2.1)。 .getPublicExponent()
完全给出了ASN.1想要的big-endian签名的二进制补码形式,因此它包括:
获取两个BigInteger.toByteArray()
值,为每个值添加tag = INTEGER(0x02)和长度前缀,然后在其串联中添加tag = SEQUENCE-composite(0x30)和长度前缀。然后继续执行第3步。
3)现在你有了构成PKCS#1 RSAPublicKey的字节,转换为PEM :编码为base64;如果需要,可以分成几行(64个字符),或者总是安全;并添加“BEGIN”和“END”行,除非不需要。