# OpenSSL EC PRIVATE KEY content structure details

Background I am trying to understand how PEM contents are formatted for "EC Private Key" so e.g. following is private key

-----BEGIN EC PARAMETERS-----
BgUrgQQAIw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEIAavpiUck1lQc01A6FH1SE1XSwW4C+i354tOQyPjioSnq5lzc9YQXX
yAIiC6hiMhARzBxe2vmYBeCEENlmCG0jNymgBwYFK4EEACOhgYkDgYYABAEyMQ/2
NkU0LHTBhpsbeaFklNSXUeG2znLuFvcb0hvc29R5ydz8/dpDOhhEtT3+SRiYOmBS
f5wQRRWyf872XFtxhgGp6MFrfHL0c2ofvYIfxLJPXSnq+GCqOKi83GwKITfkkd9N
iwfW7YlKbAQPSoPcCoPG+cNCMLs3FLN/6fD6K99R/w==
-----END EC PRIVATE KEY-----


which was created with following openssl command just in case anyone like to see

openssl ecparam -out ecc_private_key.key -name secp521r1 -genkey

Recently I realized that contents in between -----XXX EC PRIVATE KEY----- contains more than just private key and cannot be used a Parameter "D" in elliptic curve equation. So using following command I was able to find individual elements also given below;

$openssl ec -in ecc_private_key.key -noout -text read EC key Private-Key: (521 bit) priv: 00:6a:fa:62:51:c9:35:95:07:34:d4:0e:85:1f:54: 84:d5:74:b0:5b:80:be:8b:7e:78:b4:e4:32:3e:38: a8:4a:7a:b9:97:37:3d:61:05:d7:c8:02:22:0b:a8: 62:32:10:11:cc:1c:5e:da:f9:98:05:e0:84:10:d9: 66:08:6d:23:37:29 pub: 04:01:32:31:0f:f6:36:45:34:2c:74:c1:86:9b:1b: 79:a1:64:94:d4:97:51:e1:b6:ce:72:ee:16:f7:1b: d2:1b:dc:db:d4:79:c9:dc:fc:fd:da:43:3a:18:44: b5:3d:fe:49:18:98:3a:60:52:7f:9c:10:45:15:b2: 7f:ce:f6:5c:5b:71:86:01:a9:e8:c1:6b:7c:72:f4: 73:6a:1f:bd:82:1f:c4:b2:4f:5d:29:ea:f8:60:aa: 38:a8:bc:dc:6c:0a:21:37:e4:91:df:4d:8b:07:d6: ed:89:4a:6c:04:0f:4a:83:dc:0a:83:c6:f9:c3:42: 30:bb:37:14:b3:7f:e9:f0:fa:2b:df:51:ff ASN1 OID: secp521r1 NIST CURVE: P-521  Question: I would like know that how openssl able to decode Base64 contents and extracted private and public key out of it. I am currently dealing with an app which does not have any PemReader abilities built in so I would like to write my own implementation of PemReader so I can decode this information in my application (only EC keys for now) PS: I already have gone through RFC5915 according to that Private-Key should start with 1 (version) but all key I generate with openssl always start with 0x30. So I am missing something of course • 5915 #3 says it's ASN.1 type ECPrivateKey which is a SEQUENCE containing INTEGER with value 1 etc. The DER (or BER) encoding of a SEQUENCE begins with the tag for SEQUENCE which is 0x30. Sep 30 at 23:35 ## 2 Answers The private key data is encoded in ASN.1, so you need to decode that to get the various fields out. openssl asn1parse can do this, but by default it'll parse the "EC PARAMETERS" section of the file (since that comes before the "EC PRIVATE KEY" section), so you need to strip that off first. You can do that with sed, and then pipe the result to openssl asn1parse: $ sed '1,/-----BEGIN EC PRIVATE KEY-----/ d' ecc_private_key.key | openssl asn1parse --dump
0:d=0  hl=3 l= 220 cons: SEQUENCE
3:d=1  hl=2 l=   1 prim: INTEGER           :01
6:d=1  hl=2 l=  66 prim: OCTET STRING
0000 - 00 6a fa 62 51 c9 35 95-07 34 d4 0e 85 1f 54 84   .j.bQ.5..4....T.
0010 - d5 74 b0 5b 80 be 8b 7e-78 b4 e4 32 3e 38 a8 4a   .t.[...~x..2>8.J
0020 - 7a b9 97 37 3d 61 05 d7-c8 02 22 0b a8 62 32 10   z..7=a...."..b2.
0030 - 11 cc 1c 5e da f9 98 05-e0 84 10 d9 66 08 6d 23   ...^........f.m#
0040 - 37 29                                             7)
74:d=1  hl=2 l=   7 cons: cont [ 0 ]
76:d=2  hl=2 l=   5 prim: OBJECT            :secp521r1
83:d=1  hl=3 l= 137 cons: cont [ 1 ]
86:d=2  hl=3 l= 134 prim: BIT STRING
0000 - 00 04 01 32 31 0f f6 36-45 34 2c 74 c1 86 9b 1b   ...21..6E4,t....
0010 - 79 a1 64 94 d4 97 51 e1-b6 ce 72 ee 16 f7 1b d2   y.d...Q...r.....
0020 - 1b dc db d4 79 c9 dc fc-fd da 43 3a 18 44 b5 3d   ....y.....C:.D.=
0030 - fe 49 18 98 3a 60 52 7f-9c 10 45 15 b2 7f ce f6   .I..:R...E.....
0040 - 5c 5b 71 86 01 a9 e8 c1-6b 7c 72 f4 73 6a 1f bd   \[q.....k|r.sj..
0050 - 82 1f c4 b2 4f 5d 29 ea-f8 60 aa 38 a8 bc dc 6c   ....O])...8...l
0060 - 0a 21 37 e4 91 df 4d 8b-07 d6 ed 89 4a 6c 04 0f   .!7...M.....Jl..
0070 - 4a 83 dc 0a 83 c6 f9 c3-42 30 bb 37 14 b3 7f e9   J.......B0.7....
0080 - f0 fa 2b df 51 ff                                 ..+.Q.


BTW, you've now published this private key to the Internet... so please don't ever use it for anything you want to actually be secure.

• thanks for answer I am going through that. Of course this is just a sample key and not intended to be used in production. Sep 30 at 2:13

Before looking into PEM/ASN.1: EC private key is a prime field element, almost a bignumber. EC public key is a point on the curve, (most likely) encoded as two field elements, either prime-field (that is, modulo another prime) or binary extension field. So you look into curve description for background. Just pick two prime numbers for secp521r1 (from your trusted source) to understand both fields. Also pick "a" and "b" coefficients and group generator.

To summarize: decode your private key down to a bignumber modulo group order, and two bignumbers ("x" and "y" coordinates of the point on elliptic curve) modulo base-field-prime as the public key.

Follow Gordon Davisson' answer for details, remember BITSTRING at the public key is another SEQUENCE to decode.