RFC8292 contains this gem:

The "k" parameter includes an ECDSA public key [FIPS186] in
uncompressed form [X9.62] that is encoded using base64url encoding

There is an example of the use of such a key a bit further down:

Authorization: vapid

The key is the k= field in the example.

This does not appear to be in ASN.1 format:

$ cat vapidkey
-----END PUBLIC KEY-----
$ openssl asn1parse -in vapidkey -i
    0:d=0  hl=2 l=  13 prim: OCTET STRING      [HEX DUMP]:47C73CA2D5150CD5BE708F1B27
Error in encoding
139686682194112:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91:

How do I parse this format?

Unfortunately, the X9.62 standard appears to be behind a paywall. That's fine, I don't need the full standard, I just need to read a key and pass the relevant bits of it to a library that knows how to deal with it. But that appears harder than it seems; this format is not immediately understood by the libraries that I've tried, so I'll have to do some conversion myself. That is pretty difficult if I don't know what format the keys are in, though.


It indeed is not ASN.1.

(AFAIK all) The formats from X9.62 are replicated in SEC1 free from SECG with a curve point (which is the actual public key value, excluding metadata) in 2.3.3 and 2.3.4.

The uncompressed point format, which you have, is just one octet 04 followed by the X and Y coordinates each as an unsigned bigendian integer of size determined by the field underlying the curve, which you need to know already -- usually the public key is embedded in an X.509 SPKI (see below) that identifies the curve and thus provides its field size. The compressed format, which is also common, is one octet 02 or 03 designating whether Y is even or odd (for a prime-characteristic curve, often abbreviated prime and notated Fp) followed by X only.

I've never seen any library that implements ECC at all that doesn't implement (X9.62) uncompressed point format, and durn few that don't implement compressed also. It is much more common to have a disagreement about the format for an ECDSA signature, but that's not your case.

Also note the base64url-unpadded scheme used in 8292 and 7515 is not compatible with the (traditional) PEM/SMIME base64 used by OpenSSL. The two 'extra' characters are different, and OpenSSL requires padding (if not an exact multiple of 3), and in most cases requires linebreaks. Morever the 'PUBLIC KEY' PEM type is supposed to be an X.509 SubjectPublicKeyInfo structure, called PUBKEY in the OpenSSL API (and code), including the SEQUENCE and AlgorithmIdentifier and BIT STRING wrapping, although that doesn't matter here because you didn't try to read it as a key only as arbitrary ASN.1.

  • I was using perl's Crypt::PK::ECC which has a raw import that I assumed would be this format, but it didn't work. It turns out that the problem was not the format, but my use of regular BASE64 rather than the RFC7515 base64url scheme. After switching to the correct base64url decoding mechanism, the pieces fell into place. Thanks for pointing that out ;-) – Wouter Verhelst May 10 '18 at 8:30

Slight addition to the answer provided by @dave_thompson_085. There is a third encoding format specified in X9.62, that is not replicated in SEC1: hybrid.

It's basically the uncompressed encoding but the first byte encodes the evenness of y just like in compressed format. It's designated by 06 and 07 in the first byte, and they have the same meaning as 02 and 03 in compressed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.