Skip to content

Adding an attribute in CSR generated using CertificateRequest class. #27417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
NitinKMathur opened this issue Sep 18, 2018 · 11 comments
Closed
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Security
Milestone

Comments

@NitinKMathur
Copy link

Hi,

I am using CertificateRequest class to generate CSR for an SCEP server. The CSR requires challengePassword attribute. I understand the attribute has to be added using CertificateExtensions property. Below is my code for the same.

public byte[] GeneratePkcs10(string challenge, string serial)
        { 
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
            {
                string subject = "serialNumber=" + serial + ", OU=ABC Inc.";
                var req = new System.Security.Cryptography.X509Certificates.CertificateRequest(subject,rsa,HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);

                req.CertificateExtensions.Add(new System.Security.Cryptography.X509Certificates.X509Extension(new Oid("1.2.840.113549.1.9.7"), System.Text.Encoding.UTF8.GetBytes("password"), false)); //add challengePassword attribute

                return req.CreateSigningRequest();
            }
        }

I ran openssl asn1parse to see if attribute is added properly in CSR, below is the output of the command.

openssl asn1parse -in cert1.pem
    0:d=0  hl=4 l= 663 cons: SEQUENCE
    4:d=1  hl=4 l= 383 cons: SEQUENCE
    8:d=2  hl=2 l=   1 prim: INTEGER           :00
   11:d=2  hl=2 l=  42 cons: SEQUENCE
   13:d=3  hl=2 l=  22 cons: SET
   15:d=4  hl=2 l=  20 cons: SEQUENCE
   17:d=5  hl=2 l=   3 prim: OBJECT            :organizationalUnitName
   22:d=5  hl=2 l=  13 prim: PRINTABLESTRING   :ABC Inc.
   37:d=3  hl=2 l=  16 cons: SET
   39:d=4  hl=2 l=  14 cons: SEQUENCE
   41:d=5  hl=2 l=   3 prim: OBJECT            :serialNumber
   46:d=5  hl=2 l=   7 prim: PRINTABLESTRING   :1234567
   55:d=2  hl=4 l= 290 cons: SEQUENCE
   59:d=3  hl=2 l=  13 cons: SEQUENCE
   61:d=4  hl=2 l=   9 prim: OBJECT            :rsaEncryption
   72:d=4  hl=2 l=   0 prim: NULL
   74:d=3  hl=4 l= 271 prim: BIT STRING
  349:d=2  hl=2 l=  40 cons: cont [ 0 ]
  351:d=3  hl=2 l=  38 cons: SEQUENCE
  **353:d=4  hl=2 l=   9 prim: OBJECT            :Extension Request**
  364:d=4  hl=2 l=  25 cons: SET
  366:d=5  hl=2 l=  23 cons: SEQUENCE
  368:d=6  hl=2 l=  21 cons: SEQUENCE
  370:d=7  hl=2 l=   9 prim: OBJECT            :challengePassword
  381:d=7  hl=2 l=   8 prim: OCTET STRING      :password
  391:d=1  hl=2 l=  13 cons: SEQUENCE
  393:d=2  hl=2 l=   9 prim: OBJECT            :sha256WithRSAEncryption
  404:d=2  hl=2 l=   0 prim: NULL
  406:d=1  hl=4 l= 257 prim: BIT STRING

Everything looks fine, except the highlighted object. The expected output should be as below:

 0:d=0  hl=4 l= 667 cons: SEQUENCE
   4:d=1  hl=4 l= 387 cons: SEQUENCE
   8:d=2  hl=2 l=   1 prim: INTEGER           :00
  11:d=2  hl=2 l=  51 cons: SEQUENCE
  13:d=3  hl=2 l=  25 cons: SET
  15:d=4  hl=2 l=  23 cons: SEQUENCE
  17:d=5  hl=2 l=   3 prim: OBJECT            :serialNumber
  22:d=5  hl=2 l=  16 prim: PRINTABLESTRING   :1234567
  40:d=3  hl=2 l=  22 cons: SET
  42:d=4  hl=2 l=  20 cons: SEQUENCE
  44:d=5  hl=2 l=   3 prim: OBJECT            :organizationalUnitName
  49:d=5  hl=2 l=  13 prim: UTF8STRING        :ABC Inc.
  64:d=2  hl=4 l= 290 cons: SEQUENCE
  68:d=3  hl=2 l=  13 cons: SEQUENCE
  70:d=4  hl=2 l=   9 prim: OBJECT            :rsaEncryption
  81:d=4  hl=2 l=   0 prim: NULL
  83:d=3  hl=4 l= 271 prim: BIT STRING
 358:d=2  hl=2 l=  35 cons: cont [ 0 ]
 360:d=3  hl=2 l=  33 cons: SEQUENCE
 362:d=4  hl=2 l=   9 prim: OBJECT            :challengePassword
 373:d=4  hl=2 l=  20 cons: SET
 375:d=5  hl=2 l=  18 prim: PRINTABLESTRING   :password
 395:d=1  hl=2 l=  13 cons: SEQUENCE
 397:d=2  hl=2 l=   9 prim: OBJECT            :sha256WithRSAEncryption
 408:d=2  hl=2 l=   0 prim: NULL
 410:d=1  hl=4 l= 257 prim: BIT STRING

Server is failing to extract challengePassword because it's not finding it at expected position. My doubt is, is it right way to add an attribute in CSR request, or I am doing something wrong?

@NitinKMathur
Copy link
Author

Hi, I debugged it further and figured out that sending a set of extension request to CA is fine. The issue is in the encoding of password. MDM server is expecting password to be a PRINTABLESTRING, but the CSR had it as OCTET STRING.

I found X509Extension has another way to create set using AsnEncodedData as below.

req.CertificateExtensions.Add(new System.Security.Cryptography.X509Certificates.X509Extension(new AsnEncodedData("1.2.840.113549.1.9.7", DerEncoding.EncodePrintableString(challenge)), false));

Here I do see there is option to set attribute as PrintableString, but when CSR is generated I still see value as OCTET STRING. How can I set value as PRINTABLE STRING?

@NitinKMathur
Copy link
Author

NitinKMathur commented Sep 18, 2018

Went through the library code and found that extensions are always added as octet string. This is the method called to encode the extension. So there is no way to encode it to printable or UTF8 string?

internal static byte[][] SegmentedEncodedX509Extension(this X509Extension extension)
   {
     if (extension.Critical)
       return DerEncoder.ConstructSegmentedSequence(DerEncoder.SegmentedEncodeOid(extension.Oid), DerEncoder.SegmentedEncodeBoolean(extension.Critical), DerEncoder.**SegmentedEncodeOctetString**(extension.RawData));
     return DerEncoder.ConstructSegmentedSequence(DerEncoder.SegmentedEncodeOid(extension.Oid), DerEncoder.**SegmentedEncodeOctetString**(extension.RawData));
   }

@bartonjs
Copy link
Member

The CSR requires challengePassword attribute. I understand the attribute has to be added using CertificateExtensions property.

The CertificateExtensions property is for extensions for the certificate. The challenge password attribute is an attribute on the CSR (not the certificate). The current API doesn't support custom attributes on the CSR itself, only the automatically generated extension request attribute.

@NitinKMathur
Copy link
Author

Thanks for clarifying @bartonjs. Is this going to be supported for CSR anytime soon?

@bartonjs
Copy link
Member

You're the first person to bring it up; so it's not planned work at this time, no.

@NitinKMathur
Copy link
Author

ok thanks @bartonjs

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 5.0 milestone Jan 31, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 23, 2020
@bartonjs bartonjs modified the milestones: 5.0.0, Future Jul 7, 2020
@bartonjs bartonjs removed the untriaged New issue has not been triaged by the area owner label Jul 7, 2020
@mohankumar6
Copy link

ok thanks @bartonjs

Hey @NitinKMathur ,Got any update on this how to add ChallengePassword Attribute with CertificateRequest?
I Stuck here for SCEP CA.

@mohankumar6
Copy link

You're the first person to bring it up; so it's not planned work at this time, no.

Hi @bartonjs ,
Kindly suggest, how do we use ChallengePassword attribute with CertificateRequest.

@bartonjs
Copy link
Member

How do we use ChallengePassword attribute with CertificateRequest.

It's not currently possible. There's other planned work in this area for .NET 7 so this might end up being done in the next couple of months... but that doesn't help you today.

@bartonjs
Copy link
Member

bartonjs commented Aug 3, 2022

This will be possible in .NET 7 (as of #73023). It's not super convenient, but it is possible now.

CertificateRequest req = ...;

AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
writer.WriteUtf8String(challengePassword);

req.OtherRequestAttributes.Add(
    new AsnEncodedData(
        new Oid("1.2.840.113549.1.9.7", null),
        writer.Encode()));

...

string reqPem = req.CreateSigningRequestPem();

@bartonjs bartonjs closed this as completed Aug 3, 2022
@NitinKMathur
Copy link
Author

NitinKMathur commented Aug 3, 2022 via email

@ghost ghost locked as resolved and limited conversation to collaborators Sep 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Security
Projects
None yet
Development

No branches or pull requests

5 participants