# OpenSSL ECC key - Additional byte in DER encoding for one curve

In the below, I use OpenSSL to create a private key for the secp224k1 curve. Note the length of the private key in the DER - 0x1d. That's 29 bytes, or 232 bits, not 224. It appears that a leading zero byte has been prepended.

$openssl version OpenSSL 1.1.1a 20 Nov 2018$ openssl ecparam -name secp224k1 -genkey -noout -outform DER -out ~/secp224k1.der

\$ certutil -asn ~/secp224k1.der
0000: 30 69                                     ; SEQUENCE (69 Bytes)
0002:    02 01                                  ; INTEGER (1 Bytes)
0004:    |  01
0005:    04 1d                                  ; OCTET_STRING (1d Bytes)
0007:    |  00 9b 69 d2 25 22 85 cc  58 c5 57 29 7e 59 02 6f  ; ..i.%"..X.W)~Y.o
0017:    |  ee 90 b1 f7 7e 78 c3 10  5c 20 52 22 78           ; ....~x..\ R"x
0024:    a0 07                                  ; OPTIONAL[0] (7 Bytes)
0026:    |  06 05                               ; OBJECT_ID (5 Bytes)
0028:    |     2b 81 04 00 20
|        ; 1.3.132.0.32 secP224k1
002d:    a1 3c                                  ; OPTIONAL[1] (3c Bytes)
002f:       03 3a 00 04 47 21 06 a1  dc ea 7d 12 e9 0f 00 29  ; .:..G!....}....)
003f:       ca 5d db 67 3f 51 e3 b3  a7 5a b6 8c d3 23 f6 93  ; .].g?Q...Z...#..
004f:       7f 8a a2 fe ce cb d9 22  f1 92 95 69 4f 25 08 3a  ; ......."...iO%.:
005f:       0d 28 1a 27 a8 99 0e 5f  0b e0 17 b5              ; .(.'..._....


Now, since this is OCTET_STRING, not INTEGER, the number having MSB 1 should not have led automatically to the prepended zero byte. Indeed, for secp224r1, it does not:

0005:    04 1c                                  ; OCTET_STRING (1c Bytes)
0007:    |  e5 5f 38 18 d8 7b ca 84  85 f3 c0 1a c7 83 21 bf  ; ._8..{........!.
0017:    |  b9 f9 ed 9c 83 2b b5 b0  ce 15 6c 0b              ; .....+....l.


This behaviour does not occur for either of the secp256r1 and secp256k1 curves. Does any one know why it would have happened for this one?

Thanks.

Although for secp224k1 the size of the underlying field, and thus point coordinates including a public key, is (slightly) smaller than 2224, the order of the curve group, and thus the size of a private key, is slightly larger than 2224 and nominally requires 29 octets to represent -- even though the probability of d chosen uniformly at random per spec actually needing 29 octets is so small it probably won't happen during the Earth's lifetime. Quoting SEC2 from http://www.secg.org (since it's free and X9.62 isn't) minus formatting I can't reproduce without MathJax:

2.3.1 Recommended Parameters secp224k1
The elliptic curve domain parameters over Fp associated with a Koblitz curve secp224k1 are specified by the sextuple T = (p, a, b, G, n, h) where the finite field Fp is defined by:
p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFE56D
= 2224 − 232 − 212 − 211 − 29 − 27 − 24 − 2 − 1
The curve E: y2 = x3 + ax + b over Fp is defined by:
a = 00000000 00000000 00000000 00000000 00000000 00000000 00000000
b = 00000000 00000000 00000000 00000000 00000000 00000000 00000005
The base point G in compressed form is:
G = 03 A1455B33 4DF099DF 30FC28A1 69A467E9 E47075A9 0F7E650E B6B7A45C
and in uncompressed form is:
G = 04 A1455B33 4DF099DF 30FC28A1 69A467E9 E47075A9 0F7E650E B6B7A45C 7E089FED 7FBA3442 82CAFBD6 F7E319F7 C0B0BD59 E2CA4BDB 556D61A5
Finally the order n of G and the cofactor are:
n = 01 00000000 00000000 00000000 0001DCE8 D2EC6184 CAF0A971 769FB1F7
h = 01

See https://github.com/openssl/openssl/commit/30cd4ff294252c4b6a4b69cbef6a5b4117705d22#diff-a51596fb2f3b3650972f0f650cdcf115 -- although this was initially implemented wrongly, using the field size ('degree'), and subsequently fixed to use group order (not directly in ec_asn1.c but by calling to EC_KEY_priv2{buf,oct} in ec_key.c) AFAICS only in 1.1.0 up.

• That site gives a 502 error for me, but I edited this to add formatting. Is this how it appeared? – forest Apr 12 at 6:41
• Thanks to @dave_thompson_085 - not least because, if you hadn't posted this, I'd probably be filing an OpenSSL bug report right now! Also, there's an X9.62 working draft dated September 1998 at "citeseerx.ist.psu.edu/viewdoc/…" – AJM Apr 12 at 8:46
• @forest: close. They used the F with two vertical strokes and serifs that means 'finite field', a combination of serif and 'typewriter' fonts, and indentation, but I think in context here those aren't needed for meaning. I was (and am) actually working from a copy I downloaded years ago, and slapped in the URL without rechecking -- my bad; I also get 502 now, but https does get a valid certificate (issued Jan 10) which for several years at least it didn't. I'll try to figure out if there's any way to notify them and get this fixed. – dave_thompson_085 Apr 13 at 17:50
• Yeah that's what I guessed (you can do that in MathJax with \mathbb(F), but sadly this site lacks MathJax support), but since there's no unicode character for that, I just made it bold instead. – forest Apr 14 at 3:03