[openssl-dev] Retrieving DSA public key (Y) in ASN.1 format
Dave Thompson
dthompson at prinpay.com
Tue Dec 16 22:34:07 UTC 2014
> From: openssl-dev On Behalf Of Douglas E Engert
> Sent: Tuesday, December 16, 2014 11:40
> On 12/16/2014 12:18 AM, Philip Prindeville wrote:
> > Is there an easy way to get at the parameter 'y' (DSA->pub_key, which is
a
> BIGNUM *) in ASN.1 format? (See (2) below.)
> > Better yet, how to take that and pass it to ASN_item_digest()?
> >
> > Also, there's some confusion (at least for me) about what constitutes
> DSAPublicKey. According to RFC-5912 you have: <snip>
> > DSA-Params ::= <snip: p,q,g>
> > DSAPublicKey ::= INTEGER -- public key, y
> > so I'd assume that i2d_DSAPublicKey() would generate a DER string
> containing the serialization of a single ASN.1 object, i.e. the INTEGER
> containing 'y' or dsa->pub_key as the serialized ASN representation of
that
> BIGNUM.
> >
> > Alas, it doesn't.
>
> I would assume it would do what you say. People confuse what is in a
> SubjectPublicKeyInfo
> which includes an algorithm oid, parameters and the public key.
>
> The same type of confusion can occur with ECC.
>
The OpenSSL implementation of DSAPublicKey has some arcana in it
that I haven't seen elsewhere. I suspect this may be because DSA was
the first parameterized (PK?) cipher and broke new territory. See below.
> PKCS#15 has ASN.1 definitions that might help, and it referes to ANSI X9
> documents. <snip>
> > If I run test/dsatest for instance and I write out the generated DSA
key,
> then parse it, I get <snip>
Note dsatest's main function is to test that the *parameter* generation
algorithm, specified by FIPS 186 to be reproducible and thus (provably?)
nothing-up-my-sleeve, works. For testing keys it would be simpler to just
use
some fixed (but valid) params. But anyway:
> > $ openssl asn1parse -in dsa.der -inform DER -i
> > 0:d=0 hl=3 l= 222 cons: SEQUENCE
> > 3:d=1 hl=2 l= 64 prim: INTEGER
> :18CF7F66E23221AEA14DB900DA06BE46A91DF113D490C3C6A0C57EEAEE56
> DF1E9059A541445CFCBE1B63E8197199C0C9FD25A7CCE3354CC1077D577C3
> 112A6CA
> > 69:d=1 hl=2 l= 65 prim: INTEGER
> :8DF2A494492276AA3D25759BB06869CBEAC0D83AFB8D0CF7CBB8324F0D7
> 882E5D0762FC5B7210EAFC2E9ADAC32AB7AAC49693DFBF83724C2EC0736E
> E31C80291
> > 136:d=1 hl=2 l= 21 prim: INTEGER
> :C773218C737EC8EE993B4F2DED30F48EDACE915F
> > 159:d=1 hl=2 l= 64 prim: INTEGER
> :626D027839EA0A13413163A55B4CB500299D5522956CEFCB3BFF10F399CE
> 2C2E71CB9DE5FA24BABF58E5B79521925C9CC42E9F6F464B088CC572AF53E
> 6D78802
> > $
>
> It is not clear to me where the above is defined.
>
> > is the result of calling i2d_DSAPublicKey() and writing that to a file.
HERE'S THE TRICKY BIT:
It's defined where you would expect, in dsa/dsa_asn1.c .
But it's defined as a "choice" that does either the standard INTEGER
(from internal BIGNUM) *OR* the above SEQUENCE which is named
'dsa_pub_internal' suggesting that it should be internal to OpenSSL
i.e. not interoperable or standard, but not explained that I can find.
Anyway, to get the standard form apparently you need to set
dsa->write_params to 0 (false) which is done *for the SPKI form*
in dsa_ameth.c dsa_pub_encode.
> > Calling i2d_DSA_PUBKEY_fp() results in something else: <snip>
> That appears to be a SubjectPublicKeyInfo (SPKI) , with algorithm ID,
> parameters, and the public key in the bit string.
Yes. PUBKEY is effectively the OpenSSL name for SPKI. There are also
RSA_PUBKEY,
EC_PUBKEY, and generic PUBKEY routines.
> But as you say below, the bit string looks like a SPKI!
No he doesn't and it doesn't.
> > Using dumpasn1 I find out that the BIT STRING at the end is actually:
> >
> > $ dumpasn1 -a -d -z -h -l dsa5.der
> > <30 81 F0>
> > 0 240: SEQUENCE {
> > <30 81 A8>
> > 3 168: . SEQUENCE {
> > <06 07>
> > 6 7: . . OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
> > : . . . (ANSI X9.57 algorithm)
> > <30 81 9C>
> > 15 156: . . SEQUENCE {
> > <02 41>
> > 18 65: . . . INTEGER
> > : . . . . 00 8D F2 A4 94 49 22 76 AA 3D 25 75 9B B0 68 69
> > : . . . . CB EA C0 D8 3A FB 8D 0C F7 CB B8 32 4F 0D 78 82
> > : . . . . E5 D0 76 2F C5 B7 21 0E AF C2 E9 AD AC 32 AB 7A
> > : . . . . AC 49 69 3D FB F8 37 24 C2 EC 07 36 EE 31 C8 02
> > : . . . . 91
> > <02 15>
> > 85 21: . . . INTEGER
> > : . . . . 00 C7 73 21 8C 73 7E C8 EE 99 3B 4F 2D ED 30 F4
> > : . . . . 8E DA CE 91 5F
> > <02 40>
> > 108 64: . . . INTEGER
> > : . . . . 62 6D 02 78 39 EA 0A 13 41 31 63 A5 5B 4C B5 00
> > : . . . . 29 9D 55 22 95 6C EF CB 3B FF 10 F3 99 CE 2C 2E
> > : . . . . 71 CB 9D E5 FA 24 BA BF 58 E5 B7 95 21 92 5C 9C
> > : . . . . C4 2E 9F 6F 46 4B 08 8C C5 72 AF 53 E6 D7 88 02
> > : . . . }
> > : . . }
> > <03 43>
> > 174 67: . BIT STRING, encapsulates {
> > <02 40>
> > 177 64: . . INTEGER
> > : . . . 18 CF 7F 66 E2 32 21 AE A1 4D B9 00 DA 06 BE 46
> > : . . . A9 1D F1 13 D4 90 C3 C6 A0 C5 7E EA EE 56 DF 1E
> > : . . . 90 59 A5 41 44 5C FC BE 1B 63 E8 19 71 99 C0 C9
> > : . . . FD 25 A7 CC E3 35 4C C1 07 7D 57 7C 31 12 A6 CA
> > : . . }
> > : . }
See? Starting at 174 BITSTRING containing DER/BER for INTEGER.
> > Oddly, though, if I define:
> >
> > int i2d_DSAPublicKey_fp(FILE *fp, DSA *dsa)
> > {
> > return ASN1_i2d_fp_of_const(DSA,i2d_DSAPublicKey,fp,dsa);
> > }
> >
> > and call that, it correctly writes out 'y' (dsa->pub_key) as: <snip
INTEGER>
> > which I'm happy about, but don't quite understand.
> >
For me that code writes the 'internal' SEQUENCE, consistent with others,
UNLESS I previously within the same program call i2d_DSA_PUBKEY
(perhaps indirectly such as PEM_write_PUBKEY) or clear write_params.
Did you maybe do the former of these?
> > So, a few questions:
> >
> > (1) what's the quick way to, given a DSA *, compute a hash (given an
> EVP_MD *) over dsa->pub_key as an ASN.1 primitive? I tried:
> >
> > ASN1_item_digest(ASN1_ITEM_ref(BIGNUM), mdtype, dsa->pub_key, md,
> mdlen);
> >
> > but it's giving me highly dubious results.
> >
I wouldn't poke around in internals like that, I would just i2d to a buffer
and hash the buffer. 32 bytes of memory costs about $.000001 .
I'm not sure even bitcoin divides small enough to make that detectable.
(Alternatively one could get a cert for the key from a CA that uses SKId
which is conventionally the hash of the "raw" pubkey. <G><G><G>)
> > (2) where is the ASN.1 module definition which corresponds to the format
> used by i2d_DSA_PUBKEY_fp()?
> >
If you mean the ASN.1 source, RFC 5280 augmented by IIRC 3279,
which got them from (CCITT) X.509 and (ANSI) X9.something,
in addition to Douglas's answer of PKCS#15.
If you mean the data the OpenSSL code uses to do ASN.1,
generic PUBKEY=X509_PUBKEY=SPKI is in asn1/x_pubkey.c,
and the DSA-specific part is in dsa/dsa_asn1.c .
> > (3) is there a way to generate a pk-dsa serialization in the library or
do I
> have to muster this by hand?
> >
> > (4) why does i2d_DSAPublicKey() give you its current results and not the
> DER representation of 'y' (dsa->pub_key)?
> >
See above.
More information about the openssl-dev
mailing list