Java 将X509公钥转换为RSA公钥

Java 将X509公钥转换为RSA公钥,java,rsa,x509,public-key,Java,Rsa,X509,Public Key,我有一个公钥,格式如下 -----开始公钥----- xxxxxxxx -----结束公钥----- 我需要将其转换为以下格式 -----开始RSA公钥----- xxxxxxxxx -----结束RSA公钥----- 基本上,问题是我正在使用一个用Java编写的第三方库 第三方库使用Java类“RSAPublicKeySpec”从字符串生成RSAPublicKey类型的实例 我提供给此第三方库的字符串取自以下格式的文件: -----开始公钥----- xxxxxxxx -----结束

我有一个公钥,格式如下


-----开始公钥-----
xxxxxxxx
-----结束公钥-----

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


-----开始RSA公钥-----
xxxxxxxxx
-----结束RSA公钥-----

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

  • 第三方库使用Java类“RSAPublicKeySpec”从字符串生成RSAPublicKey类型的实例

  • 我提供给此第三方库的字符串取自以下格式的文件:

  • 
    -----开始公钥-----
    xxxxxxxx
    -----结束公钥-----
    

  • 在仔细研究代码之后,我发现如果使用java类“X509EncodedKeySpec”加载此公钥,代码的签名验证部分就可以完美地工作。但是,由于代码是第三方库,因此我无法在代码中更改类类型。我需要以某种方式确保提供给库的输入与“RSAPublicKeySpec”类兼容,以便正确加载公钥
  • “RSA公钥”格式在非常早期的SSLeay中使用,后来演变为OpenSSL,但在2000年之前就被淘汰了,我相信这对于Java来说是非常早期的,我认为在Java拥有任何密码之前,甚至是当时允许从美国出口的受限密码。简言之,“RSA公钥”格式是PKCS#1中的特定于RSA的格式,而“公钥”是处理大量(可扩展)算法的X.509通用结构。因此,了解Java库的开发人员是如何陷入这种奇怪的限制的将是一件有趣的事情。但无论如何

    尽管这种格式早已过时,OpenSSL仍然支持它。如果您有可用的openssl命令行(可能在您复制文件/数据的另一个系统上),只需执行以下操作:

    写了下面的内容后,现在我注意到在 如果您使用Java中的BouncyCastle(或C中的OpenSSL库,但您已经拥有上面的OpenSSL命令行选项),则(再加上从此处开始的几个链接)

    无论如何,如果您愿意,这里概述了在纯Java中编写代码的两种方法:

    0)它们都首先将输入PEM转换为字节。阅读“----开始”行,最好检查它是否正确;阅读以下所有行(base64),直到但不包括“----结束”行;将base64连接并解码为字节。Java8提供了
    java.util.Base64
    ;在此之前,您必须处理“内部”类,或者添加几个常见(但不是内置)库中的一个,比如commons codecs,或者自己编写(这并不难)。现在选择步骤1或步骤2

    1) 将这些字节解析为包含。确切地说:跳过标签和外部序列的长度;跳过AlgorithmIdentifier的标记、长度和内容——或者更好地提取内容并检查它是一个OID序列,用于RSA加密和NULL(或可能省略)参数;然后跳过位字符串的标记、长度和第一个字节(未使用的位),并将(剩余的)内容作为编码密钥——这已经是您想要的PKCS#1 RSACPublicKey结构。继续执行步骤3

    2) 使用标准JCE来读取X.509格式的密钥:将字节包装在
    X509EncodedKeySpec
    中,将其交给RSA的
    密钥工厂的
    generatePublic()
    ,并将结果强制转换为
    RSPublicKey
    。然后调用
    .getmodule()
    .getPublicExponent()
    获取数学值,并用结构(用于rfc3279 2.2.1中的PKIX/X.509)在ASN.1中对其进行编码
    BigInteger.toByteArray()
    提供了ASN.1所需的大端有符号二补形式,因此它包括: 获取
    .toByteArray()
    两个值,为每个值添加tag=INTEGER(0x02)和length前缀,然后为它们的串联添加tag=SEQUENCE composite(0x30)和length前缀。然后继续执行步骤3

    3) 现在您有了构成PKCS#1 RSAPublicKey的字节,转换为PEM:编码为base64;如果需要,或者为了安全起见,可以分成几行(64个字符);并添加“开始”和“结束”行,除非不需要

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