使用 Java 将 ASN1 序列解码为 RSA public 密钥
Decode ASN1 sequence to RSA public key using Java
我有以下 RSA public 密钥作为 ASN1 序列:
SEQUENCE(2 elem)
INTEGER (1024 bit) 14832…
INTEGER 65537
如何将此序列导入为 Java 中的 RSA public 密钥?实施的 KeySpec
s(例如 PKCS8EncodedKeySpec
)不起作用(显然)。
此外,我尝试使用 BouncyCastle 并手动解码序列并自己初始化 java.security.spec.RSAPublicKeySpec
。不过这种做法显得比较笨拙。
有没有更简单的方法?
您可以按照以下代码片段使用 Bouncycastle 库:
import java.io.IOException;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DLSequence;
public class RsaAsn1Example {
// ...
public static BigInteger [] parseASN1RsaPublicKey(byte [] encoded) throws IOException {
ASN1InputStream asn1_is = new ASN1InputStream(encoded);
DLSequence dlSeq = (DLSequence) asn1_is.readObject();
ASN1Integer asn1_n = (ASN1Integer) dlSeq.getObjectAt(0);
ASN1Integer asn1_e = (ASN1Integer) dlSeq.getObjectAt(1);
asn1_is.close();
return new BigInteger[]{ asn1_n.getPositiveValue(), asn1_e.getPositiveValue()};
}
// ....
}
或者,作为一种不太吸引人的选择,您可以像 this example 我的一个回答中那样推出自己的 ASN.1 解码器。但请注意,ASN.1 解码可能非常棘手——这个非常简单的两个元素序列是我尝试用自己的代码解析的最复杂的 ASN.1 结构。
使用 BouncyCastle 解析 ASN.1 并不那么笨拙。
String key =
"30818902818100cc61f9ef5ad0bc21de5b3ca69ee725d2c504edf99a6e97a0279d9" +
"59f2364ed21aaef8c704552d5d1a3deb2ee1a0be1558e3ca182b11a8c14392b6de5" +
"2346bc7c88bf75e3fb2b9f27fab21f5cf19934e3110ea4ad72a6f073f8ab38b9939" +
"bb639e78ad7f434119d8cc2b1bde4eaf9513b056508c908ed43c99b0ceb222cbbe1" +
"ef0203010001";
byte[] keyBytes = DatatypeConverter.parseHexBinary(key);
// These will throw exception in case of type mismatch
ASN1Sequence sequence = ASN1Sequence.getInstance(keyBytes);
ASN1Integer modulus = ASN1Integer.getInstance(sequence.getObjectAt(0));
ASN1Integer exponent = ASN1Integer.getInstance(sequence.getObjectAt(1));
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus.getPositiveValue(),
exponent.getPositiveValue());
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(keySpec);
System.out.println(publicKey.toString());
另一种选择是建立 X509 public 密钥格式的序列,然后使用 X509EncodedKeySpec
。您需要将编码密钥作为位序列与算法标识符一起放入 ASN.1 序列中。但是,这将产生大致相同数量的代码,并且速度较慢,因为要解析的内容更多。 This answer 格式解释得很好。
我有以下 RSA public 密钥作为 ASN1 序列:
SEQUENCE(2 elem)
INTEGER (1024 bit) 14832…
INTEGER 65537
如何将此序列导入为 Java 中的 RSA public 密钥?实施的 KeySpec
s(例如 PKCS8EncodedKeySpec
)不起作用(显然)。
此外,我尝试使用 BouncyCastle 并手动解码序列并自己初始化 java.security.spec.RSAPublicKeySpec
。不过这种做法显得比较笨拙。
有没有更简单的方法?
您可以按照以下代码片段使用 Bouncycastle 库:
import java.io.IOException;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DLSequence;
public class RsaAsn1Example {
// ...
public static BigInteger [] parseASN1RsaPublicKey(byte [] encoded) throws IOException {
ASN1InputStream asn1_is = new ASN1InputStream(encoded);
DLSequence dlSeq = (DLSequence) asn1_is.readObject();
ASN1Integer asn1_n = (ASN1Integer) dlSeq.getObjectAt(0);
ASN1Integer asn1_e = (ASN1Integer) dlSeq.getObjectAt(1);
asn1_is.close();
return new BigInteger[]{ asn1_n.getPositiveValue(), asn1_e.getPositiveValue()};
}
// ....
}
或者,作为一种不太吸引人的选择,您可以像 this example 我的一个回答中那样推出自己的 ASN.1 解码器。但请注意,ASN.1 解码可能非常棘手——这个非常简单的两个元素序列是我尝试用自己的代码解析的最复杂的 ASN.1 结构。
使用 BouncyCastle 解析 ASN.1 并不那么笨拙。
String key =
"30818902818100cc61f9ef5ad0bc21de5b3ca69ee725d2c504edf99a6e97a0279d9" +
"59f2364ed21aaef8c704552d5d1a3deb2ee1a0be1558e3ca182b11a8c14392b6de5" +
"2346bc7c88bf75e3fb2b9f27fab21f5cf19934e3110ea4ad72a6f073f8ab38b9939" +
"bb639e78ad7f434119d8cc2b1bde4eaf9513b056508c908ed43c99b0ceb222cbbe1" +
"ef0203010001";
byte[] keyBytes = DatatypeConverter.parseHexBinary(key);
// These will throw exception in case of type mismatch
ASN1Sequence sequence = ASN1Sequence.getInstance(keyBytes);
ASN1Integer modulus = ASN1Integer.getInstance(sequence.getObjectAt(0));
ASN1Integer exponent = ASN1Integer.getInstance(sequence.getObjectAt(1));
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus.getPositiveValue(),
exponent.getPositiveValue());
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(keySpec);
System.out.println(publicKey.toString());
另一种选择是建立 X509 public 密钥格式的序列,然后使用 X509EncodedKeySpec
。您需要将编码密钥作为位序列与算法标识符一起放入 ASN.1 序列中。但是,这将产生大致相同数量的代码,并且速度较慢,因为要解析的内容更多。 This answer 格式解释得很好。