Search code examples
c#gox509asn.1csr

Unmarshal with x509.ParseCertificateRequest fails but openssl is ok?


When I try to load the PEM encoded CSR, Golang does not parse the ASN.1 data inside the CSR correctly. It spits out that the sequence is truncated.

OpenSSL on the other hand is fine with the CSR and prints out the correct CN.

Here is the generation code (in c#):

public string generateCSR(string cn) 
{
    try
    {
        AsymmetricCipherKeyPair pair = this.keyHolder.keypair;

        var subject = new X509Name("CN=" + cn);
        var pkcs10CertificationRequest = new Pkcs10CertificationRequest
            (PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, subject, pair.Public, null, pair.Private);

        string csr = Convert.ToBase64String(pkcs10CertificationRequest.GetDerEncoded());
        Debug.Log(csr);
        return csr;
    } catch(Exception e) 
    {
        Debug.LogError(e);
    }

    return null;
}

That gets send directly via HTTP to the Golang service (without any URL encoding etc.)

Golang server side:

// Try to parse CSR
bytes := make([]byte, base64.StdEncoding.DecodedLen(len(csrData)))
n, err := base64.StdEncoding.Decode(bytes, csrData)
if err != nil {
    fmt.Printf("Error whilst parsing PEM: %v\n", err)
    resp.WriteHeader(http.StatusBadRequest)
    return
}

_, err = x509.ParseCertificateRequest(bytes[:n])
if err != nil {
    fmt.Printf("Error whilst parsing ASN.1/REQ CSR: %v\n", err)
    resp.WriteHeader(http.StatusBadRequest)
    return
}

Test CSR (in PEM):

MIIEWTCCAkECAQAwFjEUMBIGA1UEAwwLdGVzdEFjY291bnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCHu2/2GXBGlEuIWAjhBHXRnT17Pod9aPbTnLwfVSD+1xjchsu2rB83LtSWlfRXoIs4geUTvr2io0iP/kU+IzVZwL/CMzPWoWwq4VH5nQ5QMqCCMEF2g90BmIlLgaopNuQPfAEO64d+3dSFnha3QLbmv2xXe3WwYJ+RTvf+Kij0jgeB3MGzEmlVDiVWlaH4TO5LzY5/CbQgtfDHmhp4LDGe+9vbSkX/m4TXMEg4//21oe7YKO4spM1z9pIUsk8vBb0jDwRFnYRhRjHY5JTzOOM6lewjciOIlOKiBBPb4xSGJeRexZZvl111L/chhLQR701XvSyEn8MQRC6U3/BAhdvvwROPfJoEkbpf5vPYGfmsRr4iwci7XBFlw7q1iJZ6Jk4T4iYaPXl2HF0x9kpbA6eDDKkdJvM0Z6X61Eir6hI8xsyAoTEh4pBRyypl+tTLl1vK1BNEZhaPatTj5N0glCxa/MxODDDri6aobU5mjbYfp1FMdpSYiJub0l7tZvgSCv82ANxjPvT4HLge658C7VOfAQj+kdeGzNgJRSA8/FwJGsbl0RyB0Yn82HrYKB+YQy/e79+i/BIm9yAmBsEjTgrjkNF1izl5PrwQBc/lU9gVbONNvryODV4pG7NrNERSsiwN5YXFWDElDZjO3TaFwbz67raRgX7aBIHlCeINzBVuzwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBFZmrjbbqxerp5oLbmW91fBzinXKLmP8E1bsIyh4GSsWxnN13a9Srbq/VEaNJm+vucAFrptleMCz8GAO5Gm8XobhnMzr6uotn8b2rEDZvo9UHuyqu2H8wI2Te5sqjBjnbH/KOTN83uYLQVODkVve/9VW7e0xxjG8i/OCmyVjVY0sc4U06LRJw4LVqeeOFWJcv0yjxEucwLNodlzm0S3t9Cx0Vkd3cVzq/lwcBTEDHzcfgleOUcOCgbOZF6NDvyuB5VLsS+HwJeIm8tiBF9yqT+RYFKYQjvDy1XT9a1sNqn7jmiV3zwb4vcy16vgAakjyBeWnK87UJQI4XiCyGP61Xchlo5p5yyIu09iJeAN5pHuKCQAYmvEjTF630O5i/e0UHWhIZA0PnG1xAksVv9FpoQh8LjfnG7+XkAYWFxAbiIG/x8rQsyZie9SSvW2hbRykGpNdQYy4wiwt/dx/UaZI3/n24/dE50NWckP8fLeGWqqej0mYWCLjzxult0xELRiVvjNfuHwcfTPBrqmQqG16PII7tjhv0bhszRrIAkcVMpTM0RV/jcSVc4aMLpDRVLElDtaG2qCaJWq5a8MBk1BiYLjI8i8f0cMBXJ2dq9sjzEwl0vGObBui5my9jHgwzY7aPqIO0mgZm5sEpisBZMgCJ9AmK36u7wjqZZC6jnuxYoWg==

Is there any option i miss in the ASN parser in go? Why is OpenSSL fine with that input?


Solution

  • I found the answer to this problem.

    Bouncycastle does not add a0:00 to the attributes when no attribute instance is given (null). This leads to incomplete encoded data.

    "If you just see: Attributes: then the SET OF is missing and the encoding is technically invalid (but it is tolerated)." - https://www.openssl.org/docs/man1.0.2/man1/openssl-req.html

    The solution is to provide a empty DerSet to the CSR which leads to the a0:00 generation indicating there are no attributes present.