Search code examples
command-lineopensslsignatureverificationecdsa

Openssl command line: how to get PEM for a hex public key, 224 bit curve?


I'm lost in a twisty maze of openssl command line options, seemingly all alike...

A public datasheet from a chip company shows this public key for use in chip authentication with secp224r1: 048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68 422B81EC20B65A66B5102A61596AF3379200599316A00A1410

I have saved it do disk as ascii-hex and as binary. I cannot find the openssl magic spell to make it into a PEM public key for signature verification. These are my best failed attempts:

$ openssl ec -in key57.hex -pubin -inform der -pubout -outform pem
read EC key
unable to load Key
34359738384:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:crypto/asn1/asn1_lib.c:91:
34359738384:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:crypto/asn1/tasn_dec.c:1118:
34359738384:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto/asn1/tasn_dec.c:290:Type=X509_ALGOR
34359738384:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:crypto/asn1/tasn_dec.c:627:Field=algor, Type=X509_PUBKEY
$ openssl ec -in key57.bin -pubin -inform der -pubout -outform pem
read EC key
unable to load Key
34359738384:error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long:crypto/asn1/asn1_lib.c:101:

The key is 114 hex digits representing 56 bytes with a prefix of 04. What is this key format properly called, and what is the right way to get it into a format usable to something like: openssl dgst -sha1 -verify public.pem -signature signature.bin test.bin


Solution

  • Your key is just a plain ECPoint (see section 2 of RFC5480). To be useful you need it in SubjectPublicKeyInfo format. Unfortunately the OpenSSL command line cannot read an ECPoint directly. You need to do some manipulation to get it into something readable.

    First convert your hex key into binary:

    $ xxd -r -p key.hex key.bin
    

    Next we'll generate another public key for the same curve to use as a template:

    $ openssl ecparam -name secp224r1 -genkey -noout -out tempkey.pem
    $ openssl ec -in tempkey.pem -pubout -outform der -out temppub.der
    read EC key
    writing EC key
    

    Take a look at the generated output like this:

    $ hexdump -C temppub.der 
    00000000  30 4e 30 10 06 07 2a 86  48 ce 3d 02 01 06 05 2b  |0N0...*.H.=....+|
    00000010  81 04 00 21 03 3a 00 04  93 6c be bb be d9 45 23  |...!.:...l....E#|
    00000020  96 f6 0c 93 d5 72 ab 33  b5 ea c6 df c4 ac 68 1b  |.....r.3......h.|
    00000030  2c e8 10 8d 5f b1 b8 80  7d 54 70 5e 21 cd e6 c6  |,..._...}Tp^!...|
    00000040  21 a4 a5 f0 7e 1a 32 9d  75 de 3d fa c3 be 58 b6  |!...~.2.u.=...X.|
    00000050
    

    This public key consists of 23 bytes of header, followed by the ECPoint data.

    To construct the key you want we can take the same first 23 bytes of header and append your key to the end:

    $ head -c 23 temppub.der >public-header.der
    $ cat public-header.der key.bin >publickey.der
    

    This gives us the key encoded as DER. To get it as PEM we do it like this:

    $ openssl ec -in publickey.der -pubin -inform der -out publickey.pem -pubout
    read EC key
    writing EC key
    

    You can inspect it like this:

    $ cat publickey.pem
    -----BEGIN PUBLIC KEY-----
    ME4wEAYHKoZIzj0CAQYFK4EEACEDOgAEips4CvLuG5jcQX/swmP4RJx2Jc7Ogtm5
    FsmS2iCdaEIrgewgtlpmtRAqYVlq8zeSAFmTFqAKFBA=
    -----END PUBLIC KEY-----
    $ openssl ec -pubin -in publickey.pem -noout -text
    read EC key
    Public-Key: (224 bit)
    pub:
        04:8a:9b:38:0a:f2:ee:1b:98:dc:41:7f:ec:c2:63:
        f8:44:9c:76:25:ce:ce:82:d9:b9:16:c9:92:da:20:
        9d:68:42:2b:81:ec:20:b6:5a:66:b5:10:2a:61:59:
        6a:f3:37:92:00:59:93:16:a0:0a:14:10
    ASN1 OID: secp224r1
    NIST CURVE: P-224