Java 我们如何将字符串从 PEM 转换为 DER 格式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4032985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do we convert a String from PEM to DER format
提问by MSSV
Have a String being sent from in the below format:
以以下格式发送一个字符串:
-----BEGIN RSA PUBLIC KEY-----
MIGHAoGBANAahj75ZIz9nXqW2H83nGcUao4wNyYZ9Z1kiNTUYQl7ob/RBmDzs5rY
mUahXAg0qyS7+a55eU/csShf5ATGzAXv+DDPcz8HrSTcHMEFpuyYooX6PrIZ07Ma
XtsJ2J4mhlySI5uOZVRDoaFY53MPQx5gud2quDz759IN/0gnDEEVAgED
-----END RSA PUBLIC KEY-----
How do i construct a PublicKey Object from this string ? Have tried the below Remove the header and footer and base64 decode the buffer
我如何从这个字符串构造一个 PublicKey 对象?已尝试以下删除页眉和页脚并base64解码缓冲区
public static PublicKey getFromString(String keystr) throws Exception
{
//String S1= asciiToHex(keystr);
byte[] keyBytes = new sun.misc.BASE64Decoder().decodeBuffer(keystr);
X509EncodedKeySpec spec =
new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
This fails either as an invalid key format or will get below error
这要么作为无效的密钥格式失败,要么将出现以下错误
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188)
at java.security.KeyFactory.generatePublic(KeyFactory.java:304)
at PublicKeyReader.getFromString(PublicKeyReader.java:30)
at Tst.main(Tst.java:36)
The Key is being generated thro the API of openSSL PEM_write_bio_RSAPublicKey(bio, rsa);
密钥是通过 openSSL 的 API 生成的 PEM_write_bio_RSAPublicKey(bio, rsa);
回答by Jcs
by calling PEM_write_bio_RSAPublicKey
only the key modulus and public exponent are encoded into the output PEM data. However the X509EncodedKeySpec
is expected this ASN.1 key format:
通过PEM_write_bio_RSAPublicKey
仅调用密钥模数和公共指数被编码到输出 PEM 数据中。但是,X509EncodedKeySpec
预期此 ASN.1 密钥格式:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
You should use the PEM_write_bio_PUBKEY
function which encodes the public key using the SubjectPublicKeyInfo structure which as expected by X509EncodedKeySpec
您应该使用PEM_write_bio_PUBKEY
使用 SubjectPublicKeyInfo 结构对公钥进行编码的函数,正如预期的那样X509EncodedKeySpec
An other possible solution to decode the key. Unfortunately I don't think it is possible to do only with the standard JDK API but it can be done with the Bouncycastlelibrary
解码密钥的另一种可能的解决方案。不幸的是,我认为仅使用标准 JDK API 是不可能的,但可以使用Bouncycastle库来完成
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
public static PublicKey getFromString(String keystr) throws Exception
{
//String S1= asciiToHex(keystr);
byte[] keyBytes = new sun.misc.BASE64Decoder().decodeBuffer(keystr);
ASN1InputStream in = new ASN1InputStream(keyBytes);
DERObject obj = in.readObject();
RSAPublicKeyStructure pStruct = RSAPublicKeyStructure.getInstance(obj);
RSAPublicKeySpec spec = new RSAPublicKeySpec(pStrcut.getModulus(), pStruct.getPublicExponent());
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
回答by Bruno
BouncyCastle's PEMReader will do this for you:
BouncyCastle 的 PEMReader 将为您执行此操作:
String pemKey = "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGHAoGBANAahj75ZIz9nXqW2H83nGcUao4wNyYZ9Z1kiNTUYQl7ob/RBmDzs5rY\n"
+ "mUahXAg0qyS7+a55eU/csShf5ATGzAXv+DDPcz8HrSTcHMEFpuyYooX6PrIZ07Ma\n"
+ "XtsJ2J4mhlySI5uOZVRDoaFY53MPQx5gud2quDz759IN/0gnDEEVAgED\n"
+ "-----END RSA PUBLIC KEY-----\n";
PEMReader pemReader = new PEMReader(new StringReader(pemKey));
RSAPublicKey rsaPubKey = (RSAPublicKey) pemReader.readObject();
System.out.println("Public key: "+rsaPubKey);
(Note that you may need Security.addProvider(new BouncyCastleProvider());
somewhere before.)
(请注意,您Security.addProvider(new BouncyCastleProvider());
之前可能需要某个地方。)
回答by Alain O'Dea
UPDATE: greatlysimplified process and code thanks to @dave_thompson_085
更新:由于@dave_thompson_085,大大简化了流程和代码
You can construct a PublicKey Object from the string you provided as follows:
您可以从您提供的字符串构造一个 PublicKey 对象,如下所示:
- Reading the Subject Public Key Information (SPKI) from binary DER (using Bouncy Castle's PEMParser)
- Feeding the SPKI into a converter to get the PublicKey (Bouncy's Castle's JcaPEMKeyConverter works)
- 从二进制 DER 中读取主题公钥信息 (SPKI)(使用 Bouncy Castle 的 PEMParser)
- 将 SPKI 送入转换器以获取公钥(Bouncy's Castle 的 JcaPEMKeyConverter 工作)
Pre-reqs for my solution:
我的解决方案的先决条件:
- Java 7+ (or you'll need to manually unroll the try-with-resources)
- Bouncy Castle bcprov-jdk15on 1.51 or later (does NOT run on 1.50 or earlier, does not compile on 1.47 or earlier)
- Java 7+(或者您需要手动展开 try-with-resources)
- Bouncy Castle bcprov-jdk15on 1.51 或更高版本(不在 1.50 或更早版本上运行,不在 1.47 或更早版本上编译)
Full working Java 7+ example:
完整的 Java 7+ 示例:
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import java.io.IOException;
import java.io.StringReader;
import java.security.PublicKey;
public interface PemToDer
{
static void main(String[] args) throws IOException {
createRsaPublicKey(
"-----BEGIN RSA PUBLIC KEY-----\n" +
"MIGHAoGBANAahj75ZIz9nXqW2H83nGcUao4wNyYZ9Z1kiNTUYQl7ob/RBmDzs5rY\n" +
"mUahXAg0qyS7+a55eU/csShf5ATGzAXv+DDPcz8HrSTcHMEFpuyYooX6PrIZ07Ma\n" +
"XtsJ2J4mhlySI5uOZVRDoaFY53MPQx5gud2quDz759IN/0gnDEEVAgED\n" +
"-----END RSA PUBLIC KEY-----"
);
}
static PublicKey createRsaPublicKey(String keystr) throws IOException {
try (StringReader reader = new StringReader(keystr);
PEMParser pemParser = new PEMParser(reader)) {
SubjectPublicKeyInfo subjectPublicKeyInfo = (SubjectPublicKeyInfo) pemParser.readObject();
JcaPEMKeyConverter pemKeyConverter = new JcaPEMKeyConverter();
return pemKeyConverter.getPublicKey(subjectPublicKeyInfo);
}
}
}