Why does the Symantec CSR checker think my CSR is missing a NULL value in AlgorithmIdentifier? RFC3279

774 Views Asked by At

For a number of unpleasant reasons, I have been attempting to build my own Certificate Signing Request manually using the bouncycastle API.

Ostensibly I chose to do this because I needed the pre-signed version of the CSR in order to generate the sha256withRSA signature using a key that is stored in an HSM, encrypted under an LMK, and therefore not immediately available at the point of CSR creation.

Anyway, that's sort of incidental at this point.

I have managed to create a CSR structure by comparing with other CSRs generated using openSSL, add the required information to it, send it off to the HSM to generate a signature using the private key, get that signature back and then append it to the CSR.

I've then stuck my generated certificate into a few CSR checkers, notably the Symantec one as this is, I believe, our CA who will have to sign this.

The symantec CSR checker confidently informs me that:

The CSR is missing a NULL value in its AlgorithmIdentifier parameter

Hmm. Ok.

It then gives an example of what a good one would look like:

An example of a good AlgorithmIdentifier parameter in a CSR

Here's the bit of code where I added this particular NULL value to the AlgorithmIdentifier object:

    ASN1EncodableVector topLevelPublicKeySequenceVector = new ASN1EncodableVector();
    ASN1EncodableVector publicKeySequenceVector = new ASN1EncodableVector();
    AlgorithmIdentifier rsaEncryptionOid = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);      

    ASN1Integer pkModulus = new ASN1Integer(publicKey.getModulus());
    ASN1Integer pkExponent = new ASN1Integer(publicKey.getPublicExponent());
    publicKeySequenceVector.add(pkModulus);
    publicKeySequenceVector.add(pkExponent);
    DERSequence publicKeySequence = new DERSequence(publicKeySequenceVector);
    DERBitString publicKeyBitString = null;
    try {
        publicKeyBitString = new DERBitString(publicKeySequence);
    } catch (IOException e1) {
        e1.printStackTrace();
    }

    topLevelPublicKeySequenceVector.add(rsaEncryptionOid);
    topLevelPublicKeySequenceVector.add(publicKeyBitString);

    DERSequence topLevelPublicKeySequence = new DERSequence(topLevelPublicKeySequenceVector);

So, if I take my CSR and pop it into an ASN.1 decoder, to take a look at this AlgorithmIdentifier parameter and verify that it is indeed missing this NULL value, I get the following output (complete with spurious values for the benefit of StackOverflow), which shows that my NULL value appears to be right there, where I'd expect it to be:

SEQUENCE(3 elem)
   SEQUENCE(3 elem)
   INTEGER 0
   SEQUENCE(7 elem)
      SET(1 elem)
         SEQUENCE(2 elem)
            OBJECT IDENTIFIER 2.5.4.6 countryName (X.520 DN component)
            PrintableString GB
      SET(1 elem)
         SEQUENCE(2 elem)
            OBJECT IDENTIFIER 2.5.4.8 stateOrProvinceName (X.520 DN component)
            UTF8String Sol
      SET(1 elem)
         SEQUENCE(2 elem)
            OBJECT IDENTIFIER 2.5.4.7 localityName (X.520 DN component)
            UTF8String Earth
      SET(1 elem)
         SEQUENCE(2 elem)
            OBJECT IDENTIFIER 2.5.4.10 organizationName (X.520 DN component)
            UTF8String Stackoverflow
      SET(1 elem)
         SEQUENCE(2 elem)
            OBJECT IDENTIFIER 2.5.4.11 organizationalUnitName (X.520 DN component)
            UTF8String Stackoverflow
      SET(1 elem)
         SEQUENCE(2 elem)
            OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
            UTF8String common.name.for.stackoverflow
      SET(1 elem)
         SEQUENCE(2 elem)
         OBJECT IDENTIFIER 1.2.840.113549.1.9.1 emailAddress (PKCS #9)
         IA5String [email protected]
   SEQUENCE(2 elem)
      SEQUENCE(2 elem)
         OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
         NULL
      BIT STRING(1 elem)
         SEQUENCE(2 elem)
            INTEGER(2048 bit) 231457529965blahblahetc
            INTEGER65537
   SEQUENCE(2 elem)
      OBJECT IDENTIFIER 1.2.840.113549.1.1.11 sha256WithRSAEncryption (PKCS #1)
      NULL
   BIT STRING(2048 bit) 1011010etc etc...

So, with apologies for the slightly circuitous way I've described this, does anyone have even the foggiest idea why my CSR would fail validation for a missing field that is, it would appear, not actually missing?

EDIT: Here is the actual request (or at least, one I've generated with nonsense values that shares the same symptom, for the purposes of this question)

-----BEGIN CERTIFICATE REQUEST-----
MIIC6zCCAdMCAQAwgaUxCzAJBgNVBAYTAkdCMQwwCgYDVQQIDANTb2wxDjAMBgNV
BAcMBUVhcnRoMRYwFAYDVQQKDA1TdGFja292ZXJmbG93MRYwFAYDVQQLDA1TdGFj
a292ZXJmbG93MRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20xLjAsBgkqhkiG9w0B
CQEWH2R1ZmYudmFsdWVAZm9yc3RhY2tvdmVyZmxvdy5jb20wggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDrH2qNz5wtTc9jFQPoTfdk1Mf9N1LGXrqyV5sA
1w9Y4BGGJNm3yW0KUPLxyHhSJLWzHqdKzcLwlocSJvYVrMmBG9agOnHhX1aQLrnr
ruEAP7aN/gHW9isQLk6/MJPt8TkIby6azR0qq4VYR/+6dRCv7PhVvGBMxWjdQbEa
UxJAyq3eVMNBMdDdrOIMLrvxF3xcido4O9qWtdXFQwUgXoUGJG0sY3tXpwE5jB7A
1MWayfbSXj2NATU9fqHhwEoPwBm4yw65Hg+VDHWABCR/qYmLQKrVThF9UE4RUy5I
+DMRoTOUX3YRqZkg3aaCfe/LtuoHhfsCSZwxak2GZ1TI8vWBAgMBAAGgADANBgkq
hkiG9w0BAQsFAAOCAQEAoqTYzypOlLKSrF4+5jKqbRgC+9JBUhYKmQcAIaDzmDNf
0ZHwxG4iGeCS5pj60MKpv6gxUZcLhwgcm717XZrMMR4dD9yILyJsFp7C8MnOgYpB
C/VzSBwH8FvmnVsSmOcAR8IcvXLW2BpTgH6tSiFsU+xlpUWUUceFL97xZAiM93cZ
tdsH6KbKo/YvCbKhGkX311S+oTPk1oSvu5znRXBl2iyk3wbFiC9blARIcfYlhGPH
gL/ic+7+Mn5qmOY8w39Y42aP/G4ISG8h52Q1pbxH7B/I++sK73yTwRZCf1tprMP6
27j3Bpr72VY1Egge97rrb8KcL+K+A84/74Ad7NNywQ==
-----END CERTIFICATE REQUEST-----
2

There are 2 best solutions below

2
On BEST ANSWER

The error message is completely wrong. It should say that PKCS#10 request signature validation failed :)

Details of your PKCS#10 request in xca

Try to generate PKCS#10 request using openssl/xca/certreq and change the value of signature algorithm oid to something else.

2
On

The relevant structures are defined in PKCS#10.

CertificationRequest ::= SEQUENCE {
        certificationRequestInfo CertificationRequestInfo,
        signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
        signature          BIT STRING
   }

   AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE {
        algorithm          ALGORITHM.&id({IOSet}),
        parameters         ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
   }

CertificationRequestInfo ::= SEQUENCE {
        version       INTEGER { v1(0) } (v1,...),
        subject       Name,
        subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
        attributes    [0] Attributes{{ CRIAttributes }}
   }

   SubjectPublicKeyInfo { ALGORITHM : IOSet} ::= SEQUENCE {
        algorithm        AlgorithmIdentifier {{IOSet}},
        subjectPublicKey BIT STRING
   }

In particular, notice the last element in the CertificationRequestInfo sequence: attributes [0] Attributes{{ CRIAttributes }}.

It is not optional, it must be there even if there are no attributes, but it is missing in your CSR. The error message from the CSR checker seems to be wrong, but there is an error in your CSR.