OpenSSL doesn't show all the requested extensions for a CSR

23 views
Skip to first unread message

Thomas Anderson

unread,
Aug 5, 2025, 8:48:09 PMAug 5
to openss...@openssl.org
Here's a CSR I kinda hacked together:

-----BEGIN NEW CERTIFICATE REQUEST-----
MIIBADCBqAIBADATMREwDwYDVQQKDAh3aGF0ZXZlcjBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABInX+1ey1zZ9zM4z4rxTJVxdtMpBNlrwK9mae1DaPkGqvtXCr/ER
AJpPDgWJcT2j9W5EjvrMtUxe5yujJw210DSgMzAxBgkqhkiG9w0BCQ4xJDANMAsG
A1UdDwQEAwIBhjATMBEGA1UdDgQKBAhkZWFkYmVlZjAKBggqhkjOPQQDAgNHADBE
AiAORfemho2gtZudBD8BGUvKBeQOVeg4fzkJTYTkqk4cKwIgGhdlouh2dVGbCa4t
Iq3EaI+b4OMe2uEb3mmftiefvok=
-----END NEW CERTIFICATE REQUEST-----

Here's the output of openssl asn1parse -in test.pem :

    0:d=0  hl=4 l= 256 cons: SEQUENCE
    4:d=1  hl=3 l= 168 cons: SEQUENCE
    7:d=2  hl=2 l=   1 prim: INTEGER           :00
   10:d=2  hl=2 l=  19 cons: SEQUENCE
   12:d=3  hl=2 l=  17 cons: SET
   14:d=4  hl=2 l=  15 cons: SEQUENCE
   16:d=5  hl=2 l=   3 prim: OBJECT            :organizationName
   21:d=5  hl=2 l=   8 prim: UTF8STRING        :whatever
   31:d=2  hl=2 l=  89 cons: SEQUENCE
   33:d=3  hl=2 l=  19 cons: SEQUENCE
   35:d=4  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   44:d=4  hl=2 l=   8 prim: OBJECT            :prime256v1
   54:d=3  hl=2 l=  66 prim: BIT STRING
  122:d=2  hl=2 l=  51 cons: cont [ 0 ]
  124:d=3  hl=2 l=  49 cons: SEQUENCE
  126:d=4  hl=2 l=   9 prim: OBJECT            :Extension Request
  137:d=4  hl=2 l=  36 cons: SET
  139:d=5  hl=2 l=  13 cons: SEQUENCE
  141:d=6  hl=2 l=  11 cons: SEQUENCE
  143:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Key Usage
  148:d=7  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:03020186
  154:d=5  hl=2 l=  19 cons: SEQUENCE
  156:d=6  hl=2 l=  17 cons: SEQUENCE
  158:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Identifier
  163:d=7  hl=2 l=  10 prim: OCTET STRING      [HEX DUMP]:04086465616462656566
  175:d=1  hl=2 l=  10 cons: SEQUENCE
  177:d=2  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
  187:d=1  hl=2 l=  71 prim: BIT STRING

So it's showing "X509v3 Subject Key Identifier" and "X509v3 Key Usage".

Now here's the output of openssl req -in test.pem -inform PEM -text -noout -verify :

Certificate request self-signature verify OK
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: O = whatever
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:89:d7:fb:57:b2:d7:36:7d:cc:ce:33:e2:bc:53:
                    25:5c:5d:b4:ca:41:36:5a:f0:2b:d9:9a:7b:50:da:
                    3e:41:aa:be:d5:c2:af:f1:11:00:9a:4f:0e:05:89:
                    71:3d:a3:f5:6e:44:8e:fa:cc:b5:4c:5e:e7:2b:a3:
                    27:0d:b5:d0:34
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        Attributes:
            Requested Extensions:
                X509v3 Key Usage:
                    Digital Signature, Certificate Sign, CRL Sign
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:44:02:20:0e:45:f7:a6:86:8d:a0:b5:9b:9d:04:3f:01:19:
        4b:ca:05:e4:0e:55:e8:38:7f:39:09:4d:84:e4:aa:4e:1c:2b:
        02:20:1a:17:65:a2:e8:76:75:51:9b:09:ae:2d:22:ad:c4:68:
        8f:9b:e0:e3:1e:da:e1:1b:de:69:9f:b6:27:9f:be:89

That is only showing "X509v3 Key Usage". So where is "X509v3 Subject Key Identifier"? To understand this let's consider this CSR:

-----BEGIN NEW CERTIFICATE REQUEST-----
MIH/MIGmAgEAMBMxETAPBgNVBAoMCHdoYXRldmVyMFkwEwYHKoZIzj0CAQYIKoZI
zj0DAQcDQgAEXj0aPYgbLFMlCwD89DQCjIBG+axx6uiq6t4ZgUOK+9piM3+3aScq
CKEDRDY8dmFYetIxS8xW3t513N+1BTwWSqAxMC8GCSqGSIb3DQEJDjEiMCAwCwYD
VR0PBAQDAgGGMBEGA1UdDgQKBAhkZWFkYmVlZjAKBggqhkjOPQQDAgNIADBFAiEA
uutZz9KNjvXw0fqa3NOIZRHQP4rS+tLrLxfmb8lgKi4CIA/m3oLwSxNDom0q406p
FUp0Wt/MkYMrHiKG2InRK9V+
-----END NEW CERTIFICATE REQUEST-----

Here's the openssl req output for this new CSR:

Certificate request self-signature verify OK
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: O = whatever
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:5e:3d:1a:3d:88:1b:2c:53:25:0b:00:fc:f4:34:
                    02:8c:80:46:f9:ac:71:ea:e8:aa:ea:de:19:81:43:
                    8a:fb:da:62:33:7f:b7:69:27:2a:08:a1:03:44:36:
                    3c:76:61:58:7a:d2:31:4b:cc:56:de:de:75:dc:df:
                    b5:05:3c:16:4a
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        Attributes:
            Requested Extensions:
                X509v3 Key Usage:
                    Digital Signature, Certificate Sign, CRL Sign
                X509v3 Subject Key Identifier:
                    64:65:61:64:62:65:65:66
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:45:02:21:00:ba:eb:59:cf:d2:8d:8e:f5:f0:d1:fa:9a:dc:
        d3:88:65:11:d0:3f:8a:d2:fa:d2:eb:2f:17:e6:6f:c9:60:2a:
        2e:02:20:0f:e6:de:82:f0:4b:13:43:a2:6d:2a:e3:4e:a9:15:
        4a:74:5a:df:cc:91:83:2b:1e:22:86:d8:89:d1:2b:d5:7e

So this new CSR has both but the first CSR doesn't.

Here's the openssl asn1parse for this new CSR:

    0:d=0  hl=3 l= 255 cons: SEQUENCE
    3:d=1  hl=3 l= 166 cons: SEQUENCE
    6:d=2  hl=2 l=   1 prim: INTEGER           :00
    9:d=2  hl=2 l=  19 cons: SEQUENCE
   11:d=3  hl=2 l=  17 cons: SET
   13:d=4  hl=2 l=  15 cons: SEQUENCE
   15:d=5  hl=2 l=   3 prim: OBJECT            :organizationName
   20:d=5  hl=2 l=   8 prim: UTF8STRING        :whatever
   30:d=2  hl=2 l=  89 cons: SEQUENCE
   32:d=3  hl=2 l=  19 cons: SEQUENCE
   34:d=4  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   43:d=4  hl=2 l=   8 prim: OBJECT            :prime256v1
   53:d=3  hl=2 l=  66 prim: BIT STRING
  121:d=2  hl=2 l=  49 cons: cont [ 0 ]
  123:d=3  hl=2 l=  47 cons: SEQUENCE
  125:d=4  hl=2 l=   9 prim: OBJECT            :Extension Request
  136:d=4  hl=2 l=  34 cons: SET
  138:d=5  hl=2 l=  32 cons: SEQUENCE
  140:d=6  hl=2 l=  11 cons: SEQUENCE
  142:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Key Usage
  147:d=7  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:03020186
  153:d=6  hl=2 l=  17 cons: SEQUENCE
  155:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Identifier
  160:d=7  hl=2 l=  10 prim: OCTET STRING      [HEX DUMP]:04086465616462656566
  172:d=1  hl=2 l=  10 cons: SEQUENCE
  174:d=2  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
  184:d=1  hl=2 l=  72 prim: BIT STRING

Here's the difference:
(second CSR)

  138:d=5  hl=2 l=  32 cons: SEQUENCE
  140:d=6  hl=2 l=  11 cons: SEQUENCE
  142:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Key Usage
  147:d=7  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:03020186
  153:d=6  hl=2 l=  17 cons: SEQUENCE
  155:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Identifier
  160:d=7  hl=2 l=  10 prim: OCTET STRING      [HEX DUMP]:04086465616462656566

vs.
(first CSR)

  139:d=5  hl=2 l=  13 cons: SEQUENCE
  141:d=6  hl=2 l=  11 cons: SEQUENCE
  143:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Key Usage
  148:d=7  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:03020186
  154:d=5  hl=2 l=  19 cons: SEQUENCE
  156:d=6  hl=2 l=  17 cons: SEQUENCE
  158:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Identifier
  163:d=7  hl=2 l=  10 prim: OCTET STRING      [HEX DUMP]:04086465616462656566

Structurally I see the difference. The first CSR has two SEQUENCES at depth level 5 whereas the second CSR only has one.

My question is...  should the first CSR be showing both extension requests or shouldn't it be? I mean, right now it isn't, but how ought a CSR like the first one behave? I mean, OpenSSL seems to think that the first CSR is perfectly valid - it's just not showing all of the data that's embedded within it.

Viktor Dukhovni

unread,
Aug 6, 2025, 2:59:06 AMAug 6
to openss...@openssl.org
On Tue, Aug 05, 2025 at 07:47:50PM -0500, Thomas Anderson wrote:
> Here's a CSR I kinda hacked together:
>
> -----BEGIN NEW CERTIFICATE REQUEST-----
> MIIBADCBqAIBADATMREwDwYDVQQKDAh3aGF0ZXZlcjBZMBMGByqGSM49AgEGCCqG
> SM49AwEHA0IABInX+1ey1zZ9zM4z4rxTJVxdtMpBNlrwK9mae1DaPkGqvtXCr/ER
> AJpPDgWJcT2j9W5EjvrMtUxe5yujJw210DSgMzAxBgkqhkiG9w0BCQ4xJDANMAsG
> A1UdDwQEAwIBhjATMBEGA1UdDgQKBAhkZWFkYmVlZjAKBggqhkjOPQQDAgNHADBE
> AiAORfemho2gtZudBD8BGUvKBeQOVeg4fzkJTYTkqk4cKwIgGhdlouh2dVGbCa4t
> Iq3EaI+b4OMe2uEb3mmftiefvok=
> -----END NEW CERTIFICATE REQUEST-----

The above CSR is not consistent with section 5.4.2 of RFC2985 (PKCS#9).

https://datatracker.ietf.org/doc/html/rfc2985#page-17

which defines the "extensionRequest" attribute to consist (as a set of
values) of a single element which is a sequence of extensions.

> Here's the output of openssl asn1parse -i -in test.pem :
While what you have above is a set of two 1-element sequences. Sadly, a
set of two 1-element sequences is not the same as a set containing a
single 2-element sequence.

{ [a], [b] } != { [[a], [b]] }

> So it's showing "X509v3 Subject Key Identifier" and "X509v3 Key Usage".

Yes, but not in the format specified in PKCS#9.

> To understand this let's consider this CSR:
>
> -----BEGIN NEW CERTIFICATE REQUEST-----
> MIH/MIGmAgEAMBMxETAPBgNVBAoMCHdoYXRldmVyMFkwEwYHKoZIzj0CAQYIKoZI
> zj0DAQcDQgAEXj0aPYgbLFMlCwD89DQCjIBG+axx6uiq6t4ZgUOK+9piM3+3aScq
> CKEDRDY8dmFYetIxS8xW3t513N+1BTwWSqAxMC8GCSqGSIb3DQEJDjEiMCAwCwYD
> VR0PBAQDAgGGMBEGA1UdDgQKBAhkZWFkYmVlZjAKBggqhkjOPQQDAgNIADBFAiEA
> uutZz9KNjvXw0fqa3NOIZRHQP4rS+tLrLxfmb8lgKi4CIA/m3oLwSxNDom0q406p
> FUp0Wt/MkYMrHiKG2InRK9V+
> -----END NEW CERTIFICATE REQUEST-----

This CSR is consistent with the specification.
This has a set with a single element which is a 2-element sequence
in conformance with PKCS#9.

> My question is... *should* the first CSR be showing both extension
> requests or shouldn't it be?

It is not a well-formed CSR. It would ideally be rejected by the CSR
parser, because the multiplicitly of the requested extensions set is
incorrect. Unfortunately, it excess requested extensions elements
appear to be silently ignored. If there isn't yet an open issue on
Github covering this, please open one.

> I mean, right now it isn't, but how *ought* a CSR like the first one
> behave?

It isn't a valid CSR, so its behaviour is undefined, but rejection is
likely the right outcome.

--
Viktor. 🇺🇦 Слава Україні!
Reply all
Reply to author
Forward
0 new messages