Android 密钥对生成

Android keypair generation

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();

returns 长度为 144 的私钥。但我需要118。有什么区别? android实现中是否添加了smh?我怎么能得到 118 键长度?找不到要弄清楚的实现。

这是个好消息 news/bad。好消息是您想要的字节是 PrivateKey.getEncoded() 返回的字节的子序列。坏消息是,据我所知,没有找到它们的好方法。好吧,有一个简单的方法:你想要的字节总是在 PrivateKey.getEncoded() 的末尾,所以如果你知道字节序列的长度是 n(例如 118 in你的例子)然后只取 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 结构来获取字节我知道需要。

找到了一种方法来做到这一点。 生成密钥对:

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();