Dear all, -----Facts----- The private EC key is always encoded as an OCTET STRING in ASN.1 cf. RFC 5915 http://tools.ietf.org/html/rfc5915#page-3: o privateKey is the private key. It is an octet string of length ceiling (log2(n)/8) (where n is the order of the curve) obtained from the unsigned integer via the Integer-to-Octet-String- Primitive (I2OSP) defined in [RFC3447].
Therefore the length of this OCTECT STRING is fixed by the curve parameters. The EC private key encoding is wrong in OpenSSL from the very beginning: If the byte length of the private key is shorter than the byte length of the order then OpenSSL generates a shorter OCTET STRING than required. Keep in mind that the private key is not a DER encoded integer but an (unsigned) integer encoded in a fixed length byte string. Check that out with, e.g. the attached script and a log that shows up by the script. If you compare in the script the hexdata string length against 64 you will get more broken key encodings: openssl asn1parse gives: 0:d=0 hl=2 l= 117 cons: SEQUENCE 2:d=1 hl=2 l= 1 prim: INTEGER :01 5:d=1 hl=2 l= 30 prim: OCTET STRING [HEX DUMP]:0672D2.... 37:d=1 hl=2 l= 10 cons: cont [ 0 ] 39:d=2 hl=2 l= 8 prim: OBJECT :prime256v1 49:d=1 hl=2 l= 68 cons: cont [ 1 ] 51:d=2 hl=2 l= 66 prim: BIT STRING openssl ec -text shows: read EC key Private-Key: (256 bit) priv: 06:72:d2:f7:54:2a:1f:f8:35:06:12:81:94:9d:68: 84:bb:8f:f2:4d:f5:88:62:ad:a7:42:16:1f:15:30 pub: 04:3f:ff:4b:5d:5b:4c:b5:ae:b2:1a:2e:8e:52:14: 7d:fc:1a:56:45:76:cd:ba:45:2e:ef:ea:d1:36:59: 9b:85:f3:c5:d5:09:bd:6c:d8:e3:f0:88:1a:37:2c: 20:1c:21:85:54:f3:53:6c:2e:51:66:67:c1:95:58: a0:64:f8:fa:97 ASN1 OID: prime256v1 -----Remark----- Note that is not required to output the encoded OCTET STRING by the text option, which displays an integer. Look instead at the output of the asn1parse command. As a side effect, if the upper bit of a shorter key is set, the text option shows an additional leading zero byte, which is in fact not in the encoding. -----How to proceed----- The encoding is broken and does not conform with the Specification. Full stop. Because OpenSSL gently handles leading zero bytes in a private key, I'm quite sure that a correction of the EC key encoding has no impact. Try out as examples the following conformaing private EC keys: -----BEGIN EC PRIVATE KEY----- MHcCAQEEIADurCM9Znleeiyft0Ll5fK9HLZiMsEa1prIsF/rj5ZmoAoGCCqGSM49 AwEHoUQDQgAEbf8lX1VO8rfkHQao+D3PTIq9Mtg2Z54DNlTv2Fa4SnyKyjxbm/V9 PmluypK/YofHS+Qsd4JkExbSZ0xC+G78dg== -----END EC PRIVATE KEY----- or -----BEGIN EC PRIVATE KEY----- MHcCAQEEIAAMVeMs6sJ6iKyn+3whuEo9KuAStgwyRo+KxaOCbnfKoAoGCCqGSM49 AwEHoUQDQgAERYtBxIKY6Glq7sRHpYhrJ01KKAvH9LfD4L+B7GeMDht3Sw2IbK+e 82cUTBOXXBRHCL7xfk+DamHAcl9GtoO8XQ== -----END EC PRIVATE KEY----- OpenSSL converts this encoding into the internal structure, where the private key is stored as a BIGNUM, and leading zeros disappear. Any comments on the attached diff for 1.0.2.beta3 are welcome. It works, but I didn't check it carefully. It is applicable to the 1.0.1 branch as well. Regards, Ann.
$ ./script.txt 500 1000 1500 2000 2500 3000 3500 4000 4500 5000 5500 6000 6500 0672D2F7542A1FF835061281949D6884BB8FF24DF58862ADA742161F1530 -----BEGIN EC PRIVATE KEY----- MHUCAQEEHgZy0vdUKh/4NQYSgZSdaIS7j/JN9YhiradCFh8VMKAKBggqhkjOPQMB B6FEA0IABD//S11bTLWushoujlIUffwaVkV2zbpFLu/q0TZZm4XzxdUJvWzY4/CI GjcsIBwhhVTzU2wuUWZnwZVYoGT4+pc= -----END EC PRIVATE KEY----- 0:d=0 hl=2 l= 117 cons: SEQUENCE 2:d=1 hl=2 l= 1 prim: INTEGER :01 5:d=1 hl=2 l= 30 prim: OCTET STRING [HEX DUMP]:0672D2F7542A1FF835061281949D6884BB8FF24DF58862ADA742161F1530 37:d=1 hl=2 l= 10 cons: cont [ 0 ] 39:d=2 hl=2 l= 8 prim: OBJECT :prime256v1 49:d=1 hl=2 l= 68 cons: cont [ 1 ] 51:d=2 hl=2 l= 66 prim: BIT STRING read EC key Private-Key: (256 bit) priv: 06:72:d2:f7:54:2a:1f:f8:35:06:12:81:94:9d:68: 84:bb:8f:f2:4d:f5:88:62:ad:a7:42:16:1f:15:30 pub: 04:3f:ff:4b:5d:5b:4c:b5:ae:b2:1a:2e:8e:52:14: 7d:fc:1a:56:45:76:cd:ba:45:2e:ef:ea:d1:36:59: 9b:85:f3:c5:d5:09:bd:6c:d8:e3:f0:88:1a:37:2c: 20:1c:21:85:54:f3:53:6c:2e:51:66:67:c1:95:58: a0:64:f8:fa:97 ASN1 OID: prime256v1 7000 7500 8000 8500 9000 9500 10000
ec_asn1.diff
Description: Binary data
#!/bin/bash let counter=0 while [ $counter -lt 10000 ] do openssl ecparam -genkey -name prime256v1 -out key.pem -noout hexdata=`openssl asn1parse -i -in key.pem | sed '/HEX DUMP/!d;s/.*://'` if [ ${#hexdata} -lt 62 ]; then echo $hexdata cat key.pem openssl asn1parse -i -in key.pem openssl ec -in key.pem -text -noout fi let counter=(1+$counter) if [ $(($counter % 500)) == 0 ]; then echo $counter fi done
_______________________________________________ openssl-dev mailing list openssl-dev@openssl.org https://mta.opensslfoundation.net/mailman/listinfo/openssl-dev