Search code examples
cryptographycertificatex509certificatepkipkcs

Meaning of algorithm properties in a certificate


I am not able to find a reliable definition for the different algorithm properties in a certificate. In windows UI, I have this CA certificate and a CRL it generated (with certutil/ADCS):

enter image description here

My interpretation of this is that:

'Signature algorithm' -> only relates to how the signature of the CA certificate was computed by the parent CA (so it relates to the parent of the certificate of the example) 'Signature hash algorithm' -> I think it's the same? But I am not sure since SHA384 seems to be used also for the 'child' CRL generated with the certificate in the example 'Public key parameters' -> It seems to be the algorithm that is actually used for the 'children' of the CA certificate of the example, because it is the 'Signature algorithm' property of the CRL file on the right

Now, I figured, maybe this is just Windows UI being confusing, so I took a look at openssl:

openssl x509 -in 'somecert.crt' -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            17:00:00:00:0d:2a:7f:28:7b:10:75:11:5d:00:00:00:00:00:0d
        Signature Algorithm: sha384WithRSAEncryption
        Issuer: -----
        Validity
            Not Before: Mar 14 21:07:30 2019 GMT
            Not After : Mar 14 21:17:30 2024 GMT
        Subject: -----
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:cc:db:61:51:3a:bc:7b:35:e8:c6:28:2a:82:1b:
                    6c:fd:f2:db:2f:ec:27:7a:2f:e9:60:85:ad:9f:e6:
                    bb:25:cf:a7:a0:97:ab:c6:fe:82:30:6d:ce:f0:ff:
                    23:9a:8a:c3:a9:68:4f:17:39:82:0c:22:f9:10:93:
                    4f:54:6b:ff:2f:8a:99:4a:31:e0:a6:c2:d6:4e:26:
                    23:78:55:a0:e1:55:4f:c1:8f:28:c9:82:38:0e:cf:
                    12:e6:c2:ce:b9:92:ff
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
[irrelevant parts]
    Signature Algorithm: sha384WithRSAEncryption
    Signature Value:
        5d:4f:db:84:9b:34:e3:9e:0b:e7:e2:35:0c:69:5a:58:2f:70:
        b9:97:47:f0:9a:5a:19:fd:3f:5c:7a:a6:87:a9:d9:8a:1c:20:
        7a:a4:9c:b3:a4:60:f5:18:5b:29:17:42:11:69:77:71:e9:c6:
        77:ea:f2:f1:d0:96:d1:70:2f:70:58:42:b3:08:55:42:ed:24:
        3e:ff:4b:98:2c:af:0a:f6:d7:53:30:9d:43:1d:83:39:b9:75:
        77:90:c6:31:35:b0:e5:b6:4f:cc:9d:fc:7f:06:97:d4:72:79:
        8a:71:5a:cf:ec:3a:a3:2d:f8:65:eb:3f:01:91:2f:e7:0b:51:
        ff:75:a9:65:59:6b:2f:a4:0a:2d:1a:a0:73:5a:c4:99:9f:37:
        7b:ea:f4:ff:b9:47:f7:d8:bc:61:d9:c2:ab:ef:dc:2b:7a:3e:
        41:5d:79:5e:21:27:e8:66:37:0f:b7:03:7e:0d:79:40:13:a0:
        4f:2a:89:48:00:b7:86:81:ed:e2:bc:c0:70:3b:91:1c:47:f1:
        ad:72:19:d5:63:46:78:d6:67:5d:c0:58:96:11:67:73:36:6c:
        fb:7e:b2:e7:8b:2f:a7:e0:37:41:37:bd:3d:c9:92:10:c4:95:
        b6:e3:4b:09:57:d7:d6:6e:e2:64:a2:b2:d1:3d:c8:e7:26:ba:
        b5:ba:46:8c:5c:1d:d4:d1:a8:53:47:88:26:8d:65:2e:85:ac:
        cb:69:25:47:ea:d5:44:cb:99:12:07:1d:bb:01:77:87:47:5e:
        8d:92:7f:1d:23:27:ae:3f:9e:e1:c8:51:c7:df:6d:ad:b6:02:
        72:1f:28:f7:1c:3a:7e:70:f2:46:4b:b7:4b:90:de:c3:69:8c:
        75:bd:d5:4b:04:98:7d:6e:00:92:92:f5:f5:57:29:a7:66:0f:
        35:09:f5:58:be:23:a1:95:b1:10:2c:11:ea:9a:fe:65:82:94:
        48:ff:45:f2:37:58:96:55:d3:ca:97:f7:c3:a7:30:a2:07:6a:
        92:9d:a3:fc:4e:1f:bc:f4:5f:5f:c6:14:59:18:ff:df:66:65:
        21:ad:4a:bc:5e:a2:b6:a2:11:d7:40:13:30:ec:fb:df:c4:ef:
        36:3a:33:dd:c1:64:0b:7f:de:41:0b:72:0d:c6:66:03:55:be:
        38:ae:89:d2:37:41:c7:88:2b:ac:2c:25:96:ac:2b:82:f1:15:
        57:8b:47:1f:5f:2d:33:ce:ba:e9:78:30:55:ec:43:aa:f7:49:
        6e:34:3c:60:51:86:9a:39:ea:e3:fd:ba:80:87:a4:ae:bc:7d:
        83:75:7e:94:85:62:e1:89:47:3a:8d:44:13:bd:30:62:81:a0:
        d6:73:23:d0:8a:ed:08:76

So openssl also has that weird redundancy of specifying a 'Signature algorithm' property twice, along with the 'Public Key Algorithm'.

In a nutshell, I am trying to know how to determine what is the hashing & signing algorithms used by a CA to sign its children, and what are the algorithms used by its parents (I actually don't understand why those are worth mentioning in a certificate: wouldn't someone verifying the cert look for those properties in the parent?)

BONUS QUESTION: how to get those properties from the X509Certificate2 object of the certificate in C#?

I looked for various documentation and asked chatgpt, but no reliable answer came out so I am basically trying to reverse engineer this from examples I have


Solution

  • The OpenSSL output shows it twice because that data is in the certificate redundantly, as part of a signature protection strategy that (IIRC) the industry has later decided wasn't important.

    https://datatracker.ietf.org/doc/html/rfc5280#section-4.1:

    Certificate  ::=  SEQUENCE  {
        tbsCertificate       TBSCertificate,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }
    
    TBSCertificate  ::=  SEQUENCE  {
        version         [0]  EXPLICIT Version DEFAULT v1,
        serialNumber         CertificateSerialNumber,
        signature            AlgorithmIdentifier,
        issuer               Name,
        validity             Validity,
        subject              Name,
        subjectPublicKeyInfo SubjectPublicKeyInfo,
        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version MUST be v2 or v3
        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version MUST be v2 or v3
        extensions      [3]  EXPLICIT Extensions OPTIONAL
                             -- If present, version MUST be v3
        }
    

    And from 4.1.1.2. signatureAlgorithm:

    The signatureAlgorithm field contains the identifier for the cryptographic algorithm used by the CA to sign this certificate. ... This field MUST contain the same algorithm identifier as the signature field in the sequence tbsCertificate (Section 4.1.2.3).

    The SignatureAlgorithm value from the Windows CertUI is available in .NET as X509Certificate2.SignatureAlgorithm.

    The "Signature Hash Algorithm" property is made up by Windows CertUI, it's not really in the certificate, they just have mapped all the signature algorithms they know into what the underlying hash algorithm is. .NET doesn't have a way for getting this data without building the mapping table yourself based on SignatureAlgorithm. While your example uses SHA-2-384 for both creating the intermediate CA cert and signing the CRLs from that intermediate CA, there's no requirement that they match. SHA-2-384 is generally the recommended hash algorithm to use with secp384r1 aka NIST P-384, aka "ECDSA_P384".

    The public key algorithm (Windows CertUI says "ECC" here, and OpenSSL says "id-ecPublicKey") is cert.PublicKey.Oid. For RSA that OID is all that you need. For DSA and ECC (ECDSA/ECDH) you also need to interpret the public key parameters, which .NET only exposes as the raw bytes. For DSA you shouldn't care, it's a dead algorithm. For ECC, your best bet if you want it is to do something like

    using (ECDsa key = cert.GetECDsaPublicKey())
    {
        if (key != null)
        {
            Oid curveId = key.ExportParameters(false).Curve.Oid;
            ...
        }
    }
    

    Basically, you just want to poke around at the methods and properties on X509Certificate2 (and the X509Certificate base class).