Android密钥对生成

时间:2018-03-06 16:04:37

标签: java android openssl bouncycastle

OpenSsl生成DER格式的私钥,长度为118字节。 (openssl ecparam -genkey -name secp256k1 and so on)。

在android KeyPairGenerator中初始化为:

 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "SC");
            ECGenParameterSpec spec = new ECGenParameterSpec("secp256k1");
            keyPairGenerator.initialize(spec, new SecureRandom());
            return keyPairGenerator.generateKeyPair();

返回长度为144的私钥。但我需要118.差异在哪里? smh是否在Android实现中添加?我怎么能得到118键长?无法找到实现来搞清楚。

2 个答案:

答案 0 :(得分:2)

找到了一种方法。 生成密钥对:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "SC");
            ECGenParameterSpec spec = new ECGenParameterSpec("secp256k1");
            keyPairGenerator.initialize(spec, new SecureRandom());
           KeyPair kp =  keyPairGenerator.generateKeyPair();

获取私钥字节数组:

byte[] privateK = kp.getPrivate();

然后将私钥转换为 PKCS1

 byte[] privBytes = privateKey.getEncoded();
            PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
            ASN1Encodable encodable = pkInfo.parsePrivateKey();
            ASN1Primitive primitive = encodable.toASN1Primitive();
            byte[] privBytesEncoded =  primitive.getEncoded();

答案 1 :(得分:0)

这是一个好消息/坏消息。好消息是你想要的字节是PrivateKey.getEncoded()返回的字节的子序列。坏消息是我没有意识到要抓住他们的好方法。好吧,有一种简单的方法:你想要的字节总是在PrivateKey.getEncoded()的末尾,所以如果你知道字节序列的长度是 n (例如在你的例子中为118)然后只取PrivateKey.getEncoded()的最后 n 个字节。

稍微困难的方法是使用Spongycastle / Bouncycastle ASN1例程解析编码,如下面的代码段所示:

private static byte[] encodePrivateKey(PrivateKey privateKey) throws Exception{
    ASN1InputStream asn1InputStream = new ASN1InputStream(privateKey.getEncoded());
    ASN1Primitive asn1Primitive = asn1InputStream.readObject();
    DLSequence seq = (DLSequence) asn1Primitive;
    ASN1OctetString octetString = (ASN1OctetString) seq.getObjectAt(2);
    return octetString.getOctets();
}

我提供这个作为一个例子,但我必须警告你这很脆弱:我没有做任何真正的努力来遵循PKCS#8规范,我只是用ASN.1结构来抓住我知道的字节需要。