On Wed, Jan 23, 2013, Viktor Dukhovni wrote:

> The OpenSSL library includes two very similar functions:
> 
>       int X509_digest(
>               X509 *cert,
>               const EVP_MD *digest,
>               unsigned char *md,
>               int *len);
> 
>       int X509_pubkey_digest(
>               const X509 *cert,
>               const EVP_MD *type,
>               unsigned char *md,
>               int *len)
> 
> The former generates the (raw binary form of) "fingerprint" of an
> X.509 certificate, which is printed in hex for example by 
> 
>       $ openssl x509 -noout -fingerprint -<digest>
> 
> The latter I had assumed for some time produces the corresponding
> public key fingerprint, but this turns out not to be case. Instead
> of producing the digest of the full key (algorithm, parameters and
> key data) as with:
> 
>       $ openssl x509 -noout -pubkey |
>               openssl pkey -pubin -outform DER | 
>               openssl dgst -<dgst> -c
> 
> it produces a digest of just the key data. I believe this matches
> the digest used in constructing subject and authority key identifiers,
> (usually with the digest set to SHA-1). While this digest is thus
> potentially useful its security properties are entirely different
> from the similar X509_digest() function.
> 
> The full certificate digest, with a suitably second-preimage
> resistant hash can be used a compact proxy for the full certificate,
> and some applications (e.g. RFC 6698 DANE TLSA) encourage or at least
> support the use of digests as secure replacements for the underlying
> certificate.
> 
> The same can be said of the digest of the full public key (algorithm,
> parameters and key data), when one wants to trust the holder of
> the private key rather than any particular CA's name binding to
> that key.  And indeed RFC 6698 also supports public-key fingerprint
> security bindings.
> 
> In developing preliminary RFC 6698 support for Postfix, I was
> surprised to find that the X509_pubkey_digest() function was not
> the right tool. Instead I have to use:
> 
>     len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), NULL);
>     buf2 = buf = OPENSSL_malloc(len);
>     i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), (unsigned char **)&buf2);
> 
> and then additional EVP functions to compute the digest of "buf" (can't
> use buf2 as this pointer is set to "buf + len" by i2d_X509_PUBKEY()).
> 
> This is a rather non-obvious interface, and X509_get_X509_PUBKEY() is
> not documented.
> 

I make no claim this is obvious but...

It should be possible to do this in a single call using the ASN1_item_verify
interface like this:

rv = ASN1_item_verify(ASN1_ITEM_rptr(X509_PUBKEY), digest,
                                                (void 
*)X509_get_X509_PUBKEY(cert), &digest_len);


> I'd like to request that the existing X509_pubkey_digest() be
> renamed to something like x509_pubkey_identifier() just for
> internal use by the library.
> 

The problem with renaming or changing existing functions is that it will break
binary compatibility and potentially break applications too.

We could however provide an additional function to hash the whole public key
digest and document the behaviour of both.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to