ring icon indicating copy to clipboard operation
ring copied to clipboard

How to use der (pem) encoded ECDSA public key?

Open micromaomao opened this issue 5 years ago • 4 comments

I'm trying to use ECDSA_P256_SHA256_ASN1 to verify signatures, and the documentation says the provided public key should be in Octet-String-to-Elliptic-Curve-Point format. However I only have a public key that look something like this:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEI3MQm+HzXvaYa2mVlhB4zknbtAT8cSxakmBoJcBK
GqGwYS0bhxSpuvABM1kdBTDpQhXnVdcq+LSiukXJRpGHVg==
-----END PUBLIC KEY-----

I don't know much about EC crypto, and I can't seem to find any doc on how to convert this (pem) format to the format accepted by ring.

ring's documentation showed how one can convert a pem RSA public key to the desired format with openssl. Can you perhaps add an example of doing the same thing with a EC key?


I don't need to convert it with ring on the go, I just need any way (e.g. with openssl) that I can prepare a public key to be passed to ring's verify.


What I tried:

$ openssl ec -pubin -in key.pem -text                                                                                                                                                                                                03:43:28
read EC key
Public-Key: (256 bit)
pub:
    04:23:73:10:9b:e1:f3:5e:f6:98:6b:69:95:96:10:
    78:ce:49:db:b4:04:fc:71:2c:5a:92:60:68:25:c0:
    4a:1a:a1:b0:61:2d:1b:87:14:a9:ba:f0:01:33:59:
    1d:05:30:e9:42:15:e7:55:d7:2a:f8:b4:a2:ba:45:
    c9:46:91:87:56                 <--- Feeding this to ring doesn't work
ASN1 OID: prime256v1
NIST CURVE: P-256

micromaomao avatar Jul 27 '19 04:07 micromaomao

https://lapo.it/asn1js/#MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEI3MQm-HzXvaYa2mVlhB4zknbtAT8cSxakmBoJcBKGqGwYS0bhxSpuvABM1kdBTDpQhXnVdcq-LSiukXJRpGHVg shows that your key is PEM (base64) encoded SubjectPublicKeyInfo format.

Given that, the premise of this bug is a duplicate of #476.

However:

04:23:73:10:9b:e1:f3:5e:f6:98:6b:69:95:96:10: 78:ce:49:db:b4:04:fc:71:2c:5a:92:60:68:25:c0: 4a:1a:a1:b0:61:2d:1b:87:14:a9:ba:f0:01:33:59: 1d:05:30:e9:42:15:e7:55:d7:2a:f8:b4:a2:ba:45: c9:46:91:87:56 <--- Feeding this to ring doesn't work

That sounds like it might be a real bug. But, it might also be user error. Please provide a minimal working program.

briansmith avatar Aug 18 '19 08:08 briansmith

You can actually use a DER-encoded prime256r1 key by just stripping the first 26 bytes, which will always be:

unsigned char a_dat[] = {
  0x59, 0x30, 0x13, 0x30, 0x07, 0x06, 0x86, 0x2a, 0xce, 0x48, 0x02, 0x3d,
  0x06, 0x01, 0x2a, 0x08, 0x48, 0x86, 0x3d, 0xce, 0x01, 0x03, 0x03, 0x07,
  0x00, 0x42
};
unsigned int a_dat_len = 26;

Demi-Marie avatar Feb 28 '20 21:02 Demi-Marie

  • For P-384, the header is 24 bytes.
  • For P-521, the header is again 26 bytes.
  • For ed25519, the header is 12 bytes.
  • For ed488, the header is also 12 bytes.

Demi-Marie avatar Feb 28 '20 22:02 Demi-Marie

https://github.com/RustCrypto/formats/blob/master/spki/README.md

I found the crate above can solve the issue:

let pub_key = fs::read(pub_key_path).unwrap();
let pub_key = SubjectPublicKeyInfo::try_from(pub_key.as_slice()).unwrap();
let pub_key = UnparsedPublicKey::<Vec<u8>>::new(
    &signature::ECDSA_P256_SHA256_ASN1,
    pub_key.subject_public_key.to_owned(),
);

kaiwk avatar Mar 08 '22 12:03 kaiwk

Closing this as a duplicate of #370.

briansmith avatar Oct 14 '23 16:10 briansmith