将X509公钥转换为RSA公钥 [英] Convert a X509 Public key to RSA public key

查看:142
本文介绍了将X509公钥转换为RSA公钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下格式的公钥

<代码>----- BEGIN公钥-----xxxxxxxx-----结束公钥-----

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

I need to convert this into the following format

<代码>----- BEGIN RSA公钥-----xxxxxxxxx-----结束RSA公钥-----

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

Basically, the issue is that I am working with a third party library which is written in Java.

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

  1. The third party library uses Java class "RSAPublicKeySpec" to generate an instance of type RSAPublicKey from a String.

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

The String that I am supplying to this third party library is taken from a file which is in the following format:

<代码>----- BEGIN公钥-----xxxxxxxx-----结束公钥-----

  1. 仔细检查一下代码后,我可以看到,如果我使用Java类"X509EncodedKeySpec"来加载此公钥,则代码的签名验证部分可以完美地工作.但是,由于代码是第三方库,因此我无法更改其代码中的类类型.我需要以某种方式确保我要提供给库的输入与"RSAPublicKeySpec"类兼容,以便正确加载公钥.

推荐答案

"RSA PUBLIC KEY"格式在很早的SSLeay中就使用了,它演变为OpenSSL,但在2000年之前已经过时了,我认为这对于Java来说还很早.并且我认为在Java拥有任何加密货币之前,甚至是受限制的加密货币,然后允许从美国出口.简而言之,"RSA PUBLIC KEY"格式是来自PKCS#1的RSA特定格式,而"PUBLIC KEY"是X.509通用结构,可处理多种(且可扩展)算法.因此,了解您的Java库的开发人员如何陷入这种奇怪的局限将是很有趣的.但是无论如何...

The "RSA PUBLIC KEY" format was used in very early SSLeay, which evolved into OpenSSL, but obsoleted before 2000 I believe, which was very early days for Java and I think before Java had any crypto even the restricted kind then allowed for export from the US. In short, the "RSA PUBLIC KEY" format is the RSA-specific format from PKCS#1, whereas "PUBLIC KEY" is the X.509 generic structure that handles numerous (and extensible) algorithm. So it would be interesting to know how the developers of your Java library got themselves into this bizarre limitation. But anyway ...

尽管此格式已过时,但 OpenSSL仍支持.如果您有可用的openssl命令行(可能在另一个将文件/数据复制到该文件的系统上,请执行以下操作:

Although this format is long obsolete, OpenSSL still supports it. If you have the openssl commandline available (could be on another system which you copy the file/data to and back) just do:

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

Argh!写了下面的内容,现在我在(

Argh! having written the below, now I notice the (more general) dupe at Generating RSA keys in PKCS#1 format in Java (plus several links onward from there) if you use BouncyCastle in Java (or OpenSSL library in C, but you already have the OpenSSL commandline option above).

无论如何,如果您愿意,以下是使用普通Java 进行编码的两种方法的概述:

Anyway, here is an outline of two ways to code in plain Java if you prefer that:

0)两者首先将输入的PEM转换为字节.阅读"---- BEGIN"行,最好检查一下它是否正确;读取(base64的)以下所有行,直到但不包括"----- END"行;将base64连接并解码为字节.Java8提供了 java.util.Base64 ;在此之前,您必须摆弄内部"类,或者添加诸如commons编解码器之类的几种常见(但不是内置)库之一,或者自己编写(这并不难).现在选择第1步或第2步.

0) Both of them start by converting the input PEM to bytes. Read the "----BEGIN" line and preferably check it's correct; read all following lines (of base64) up to but not including the "-----END" line; concatenate and decode the base64 to bytes. Java8 provides java.util.Base64; before that you had to fiddle with "internal" classes or add one of several common (but not builtin) libraries like commons-codecs or write it yourself (which isn't that hard). Now choose either step 1 or step 2.

1)解析这些字节,作为 ASN.1 DER X.509 SubjectPublicKeyInfo的编码,如RFC 5280所示,其中包括算法标识符.确切地说:跳过外部序列的标签和长度;跳过AlgorithmIdentifier的标签,长度和内容-或者更好地提取内容,并检查它是否为rsaEncryption和NULL(或可能省略)参数的OID的SEQUENCE;然后跳过 BIT STRING 的标签,长度和第一个字节(未使用的位),并将(剩余的)内容作为已编码的密钥-已经是PKCS所需的#1 RSAPublicKey结构.继续执行步骤3.

1) Parse those bytes as the ASN.1 DER encoding of an X.509 SubjectPublicKeyInfo as shown in RFC 5280 including the AlgorithmIdentifier. To be exact: skip the tag and length of the outer sequence; skip the tag, length and contents of the AlgorithmIdentifier -- or better extract the contents and check it is a SEQUENCE of an OID for rsaEncryption and NULL (or possibly omitted) params; then skip the tag and length and first byte (unused-bits) for the BIT STRING and take the (remaining) contents as the encoded key -- which is already the PKCS#1 RSAPublicKey structure you want. Proceed to step 3.

2)或使用标准JCE来读取X.509格式密钥:将字节包装在 X509EncodedKeySpec 中,将其提供给 KeyFactory 的code> .generatePublic(),并将结果转换为 RSAPublicKey .然后调用 .getModulus() .getPublicExponent()获取数学值并将其编码在ASN.1 DER中,其结构为在PKCS#1 rfc3447 中定义的RSAPublicKey(用于rfc3279中的PKIX/X.5092.2.1). BigInteger.toByteArray()给出了ASN.1想要的大尾数带符号的二进制补码形式,所以它包括:获取两个 .toByteArray()值,分别为每个添加tag = INTEGER(0x02)和长度前缀,然后为它们的串联添加一个tag = SEQUENCE-composite(0x30)和长度前缀.然后继续执行步骤3.

2) Or use standard JCE to read the X.509 format key: wrap the bytes in an X509EncodedKeySpec, give it to .generatePublic() of a KeyFactory for RSA, and cast the result to RSAPublicKey. Then call .getModulus() and .getPublicExponent() to get the mathematical values and encode them in ASN.1 DER with the structure RSAPublicKey defined in PKCS#1 rfc3447 (used for PKIX/X.509 in rfc3279 2.2.1). BigInteger.toByteArray() gives exactly the big-endian signed two's-complement form that ASN.1 wants, so this consists of: get both .toByteArray() values, add tag=INTEGER (0x02) and length prefixes to each one, then add a tag=SEQUENCE-composite (0x30) and length prefix to their concatenation. Then proceed to step 3.

3)现在,您具有构成PKCS#1 RSAPublicKey的字节,转换为PEM :编码为base64;如有必要,请分成几行(以64个字符为单位),或者为了确保安全起见;并添加"BEGIN"和"END"行,除非不需要.

3) Now you have the bytes constituting a PKCS#1 RSAPublicKey, convert to PEM: encode to base64; break into lines (at 64 chars) if needed, or always to be safe; and add "BEGIN" and "END" lines, unless not needed.

这篇关于将X509公钥转换为RSA公钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆