Reputation: 906
OpenSsl
generates a private key in DER
format with 118 bytes length. (openssl ecparam -genkey -name secp256k1 and so on
).
In android KeyPairGenerator
initialized like:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "SC");
ECGenParameterSpec spec = new ECGenParameterSpec("secp256k1");
keyPairGenerator.initialize(spec, new SecureRandom());
return keyPairGenerator.generateKeyPair();
returns a private key with a 144 length. But i need 118. Where is a difference? Is smh added in android implementation? How could i get 118 key length? Cannot find implementation to figure out.
Upvotes: 0
Views: 2190
Reputation: 906
Found a way to do this. Generate key pair:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "SC");
ECGenParameterSpec spec = new ECGenParameterSpec("secp256k1");
keyPairGenerator.initialize(spec, new SecureRandom());
KeyPair kp = keyPairGenerator.generateKeyPair();
Get private key bytes array:
byte[] privateK = kp.getPrivate();
Then convert private key to PKCS1:
byte[] privBytes = privateKey.getEncoded();
PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
ASN1Encodable encodable = pkInfo.parsePrivateKey();
ASN1Primitive primitive = encodable.toASN1Primitive();
byte[] privBytesEncoded = primitive.getEncoded();
Upvotes: 2
Reputation: 41958
It's a little bit of good news/bad news. The good news is that the bytes you want are a subsequence of the bytes returned by PrivateKey.getEncoded()
. The bad news is that there's no good way that I'm aware of to get at them. Well, there is one easy way: the bytes you want are always at the end of PrivateKey.getEncoded()
, so if you know the length of the byte sequence is n (e.g. 118 in your example) then just take the last n bytes of PrivateKey.getEncoded()
.
A slightly harder way is to parse through the encoding using the Spongycastle/Bouncycastle ASN1 routines, as in the following snippet:
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();
}
I offer this as an example but I have to warn you that this is brittle: I haven't made any real effort to follow the PKCS#8 specification, I just eyeballed the ASN.1 structure to grab the bytes I knew were needed.
Upvotes: 0