# Can I shorten the large ECDSA public key output file from OpenSSL?

I am working in a very bandwidth restricted environment where I from time to time have the need to distribute public keys. The distribution happens in bit format, so there is no need for encoding, at best I would like all my data "raw".

It is my understanding that the public key, in compressed form, takes up the space of the curve size+1, e.g. 160 bit curve gives 161 bit public key. However, the output from OpenSSL gives me a much larger key size, e.g. 904 bits for the secp160r1 curve. I reckon there must be a lot of metadata involved.

Edit: I removed the "--- Public key starts here ---" etc and that almost cut the file in half ahem. But still there are 60 bytes/480 bits, a lot more than what I would think of as necessary.

Can I somehow reduce this size, getting rid of metadata? For example extract the key components of the signature and reassemble it in a compatible format on the receiver side? I assume DER encoding also adds overhead, but hardly this much?

Here arethe commands I use, in Cygwin:

$openssl ecparam -out private.pem -name secp160k1 -genkey$ openssl ec -in private.pem -pubout -conv_form compressed -out public.pem

• (These 2 comments don't help answer your question, but may be useful in your environment.) ​ This paper shows how to get short key encapsulation. ​ It may be possible to modify that and/or the signature algorithm to let you ​ ​ ​ (continued ...) ​ ​ ​ ​ ​ ​ ​ – user991 Jan 12 '16 at 9:02
• (... continued) ​ ​ ​ use the same key-pairs for encryption and signing, although there are separate reasons why you might want to avoid that anyway. ​ It should be possible to reduce the key size by 1 more bit by dropping the y coordinate. ​ ​ ​ ​ – user991 Jan 12 '16 at 9:02

Asn1parse to the rescue.

Most of the overhead is from the base64 encoding and the PEM header and footer.

The raw size of the compressed form ASN1 encoding is just 44 bytes for my dummy key.

And 22 of those bytes are for the 161 bits of the actual public key.

$openssl asn1parse -in compressed_public.pem -i -dump 0:d=0 hl=2 l= 42 cons: SEQUENCE 2:d=1 hl=2 l= 16 cons: SEQUENCE 4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey 13:d=2 hl=2 l= 5 prim: OBJECT :secp160k1 20:d=1 hl=2 l= 22 prim: BIT STRING 0000 - 00 03 ca f2 7b b8 4c 3c-99 b2 7a 6f fb f3 cf 8f ....{.L<..zo.... 0010 - 95 b8 77 61 76 dc ..wav.  And if you turn the PEM encoding into raw DER encoding like so... $ openssl ec -pubin -in compressed_public.pem -outform der -out compressed_public.der
writing EC key


...then 44 bytes is the size of your file.

$stat compressed_public.pem | grep Size Size: 113 Blocks: 1 IO Block: 65536 regular file$ stat compressed_public.der | grep Size
Size: 44              Blocks: 1          IO Block: 65536  regular file


And just for another look at this: using "dumpas1n", you can see exactly where those 22 non-pubkey bytes went:
(Note: dumpasn1 skips the "00" byte at the beginning of the 22 byte "BIT STRING" object and does not display it. And openssl asn1parse does not.)

$dumpasn1 | head -n2 DumpASN1 - ASN.1 object dump/syntax check program. Copyright Peter Gutmann 1997, 1998. Last updated 27 July 1998.$ dumpasn1 compressed_public.der
0 30   42: SEQUENCE {
2 30   16:   SEQUENCE {
4 06    7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
13 06    5:     OBJECT IDENTIFIER '1 3 132 0 9'
:     }
20 03   22:   BIT STRING 0 unused bits
:     03 CA F2 7B B8 4C 3C 99 B2 7A 6F FB F3 CF 8F 95
:     B8 77 61 76 DC
:   }

0 warnings, 0 errors.


• @BendikM, an ECDSA public key is just a point on the curve. The most compressed version of such a point is just the x-coordinate along with a hint which y-coordinate (because there are two square roots) to use. The additional byte encodes a) whether you encode the point at infinity, b) a compressed point (x-coordinate only) and which y-coordinate to use or c) whether you encode an uncompressed point (i.e. x- and y-coordinate). As for the 131-bit curve, it probably rounds up to the nearest multiple of 8 (136) to encode the x and then adds the type byte. – SEJPM Jan 12 '16 at 14:52