使用Java将ASN1序列解码为RSA公钥

时间:2015-04-10 15:54:59

标签: java rsa bouncycastle

我有以下RSA公钥作为ASN1序列:

SEQUENCE(2 elem)
  INTEGER (1024 bit) 14832…
  INTEGER 65537

如何在Java中将此序列作为RSA公钥导入?实施的KeySpec(例如PKCS8EncodedKeySpec)不起作用(显然)。

此外,我尝试使用BouncyCastle并手动解码序列并自行初始化java.security.spec.RSAPublicKeySpec。然而,这种方法似乎相当笨拙。

有更简单的方法吗?

2 个答案:

答案 0 :(得分:3)

您可以使用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()};
    }
// ....
}

或者,作为一个不太吸引人的选择,你可以从我的一个答案中推出你自己的ASN.1解码器,就像在this example中一样。但要注意,ASN.1解码可能非常棘手 - 这个非常简单的两个元素序列是关于我试图用我自己的代码解析的最复杂的ASN.1结构。

答案 1 :(得分:2)

使用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公钥格式,然后使用X509EncodedKeySpec。您需要将编码密钥作为位序列与算法标识符一起放入ASN.1序列中。但是,这将导致大约相同数量的代码,并且因为需要解析更多代码而变慢。 This answer格式很好地解释了。