I work on OkHttp, an Android HTTP client that implements HPKP-like certificate pinning. We recently saw a problem where different versions of Android returned different bytes for the ASN.1 encoding of the same certificate. This is bad: the pins don’t match!
The certificate of interest uses a named curve (secp521r1) with ECC. I used der2ascii <https://github.com/google/der-ascii> to view the SPKI ASN.1 bytes. Older versions of Android (which use BouncyCastle) embed the curve: SEQUENCE { SEQUENCE { # ecPublicKey OBJECT_IDENTIFIER { 1.2.840.10045.2.1 } SEQUENCE { INTEGER { 1 } SEQUENCE { # prime-field OBJECT_IDENTIFIER { 1.2.840.10045.1.1 } INTEGER { `01ffffffffffffff...` } } SEQUENCE { OCTET_STRING { `01ffffffffffffff...` } OCTET_STRING { `0051953eb9618e1c...` } } OCTET_STRING { `0400c6858e06b704...` } INTEGER { `01ffffffffffffff...` } INTEGER { 1 } } } BIT_STRING { `0004019519de800d...` } } But new versions of Android (which use Conscrypt/OpenSSL) reference the curve by name: SEQUENCE { SEQUENCE { # ecPublicKey OBJECT_IDENTIFIER { 1.2.840.10045.2.1 } # secp521r1 OBJECT_IDENTIFIER { 1.3.132.0.35 } } BIT_STRING { `0004019519de800d...` } } The original certificate embeds the curve. I believe my problem is that the Java APIs I’m using don’t return raw bytes from the certificate. Instead Java decodes the certificate into a model and re-encodes that when the bytes are requested. The original and roundtripped SPKI bytes are not identical. Does anyone else do ASN.1 encoding in order to compute a certificate’s pin? Or is it a uniquely Java problem?! The spec should warn that a single SPKI may have multiple conflicting encodings. I suggest that only encoding in the certificate should be pinned. TLS server administrators should also be careful to not inadvertently re-encode their SPKIs when doing maintenance. Thanks!
_______________________________________________ websec mailing list [email protected] https://www.ietf.org/mailman/listinfo/websec
