Skip to content
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

X509Certificate2 Handling of RSASSA-PSS certificates #102090

Open
asant57 opened this issue May 10, 2024 · 2 comments
Open

X509Certificate2 Handling of RSASSA-PSS certificates #102090

asant57 opened this issue May 10, 2024 · 2 comments

Comments

@asant57
Copy link

asant57 commented May 10, 2024

Description

System.Security.Cryptography.X509Certificates.X509Certificate2 can load an RSASSA-PSS certificate from bytes (i.e. the X509Certificate2(byte[] rawData) constructor) but is unable to create the X509Certificate2 object with the static function CreateFromPem(ReadOnlySpan certPem, ReadOnlySpan keyPem).

Reproduction Steps

class RSASSATester
{
public static string RSASSAPSSPrivateKeyPem => @"-----BEGIN PRIVATE KEY-----
MIIEvAIBADALBgkqhkiG9w0BAQoEggSoMIIEpAIBAAKCAQEA1U8xIp4qXmfOKzvH
3NASP598T0iOPhTgOinAKFTq3yPsaQZBF35Wjwp2zGosjChPnkMNcztlnKDm2tCK
hi5A2M+DmkoL4C6x7dyrnBpa3POk7KKIxFQhRK/8UlunmIreZRhcio77rVZcD6lK
X6BY7ye3D1GoSNlIQGFRe9/DBBZFkYpAsiLaGdjueeQ3uUfTiN1XFrCZW1OixhOL
PEYstOMBRPh+lvYTybSEfy4f28BNiaDNaEtXw69gkYqy2siIzx+d7LhIscUmYBdG
BYPOXM8kt9kOuBKXkYaYEQ1xRiK/DcxUB7Ptu6ANWQ5/XNxq1eTr73zQi8Ur4+7D
BsLGHQIDAQABAoIBAAR6PhN2SHi6KxdjO4XEua1WNrDKBW+uK9Vst5jhIhuppbZq
qDEgY3FrNyUr/Aq7yeK45kO19SMS3uWsR6Fwv8cNTBDlXwHHWSV0uAbLKCnH1NLB
cqd/Be0Vg0a4n82m6euAqxNJfw+bZsv5XL33IAbHyaLrruGglftWpPQ5tTPqY0nk
TrXPYLV7ZVrBen04c9xHoMLVOGoGIdLCaXpJLxUhfCTirRtpn6auY9qLzBOhhcHA
gpa25q9/dO8xcZmLIJyiyBLqkNk209qkMDyhxyoG5ZTqbHqNyxac6xxj1MRaBAOV
vkLntGtkYawyry31DFh0cRLfWeGVcFOV3rm5RQECgYEA57eRqs2RR2MajgEYMlyN
5kaGhrrMhJ3MVMwK23wOfCB1n6vsgKEFV3Hq18F4CG3pRV+V0EoLkfAO+aOAviLe
Cz2g8Y0xEpJP2cqNT0kJznt8WYGl1q0x0YCERPR673AATKuAury8Fq6+4rlb04TM
HP77Mam5Q/LhXCUBAS/PRcECgYEA66nJVI2GADlMZShvvGiF3jxLFSCH+1MLZWHk
Kx+u98tXvlObKO5sOgWm1o+/5ogHh5X9B87CRciPA97FY4HgSeEBvF8JdRASqG0W
TK6UNuAiLDNIm6rtnlpztLC2RQM1i9QqoI3IBCDj8iFWXJLbdbGMVdlBZJmDPyXs
xNSoL10CgYBDcHfi4EWCI2PdJJBoR+u8s5X/rGpNxqdrnp8iVi7ZDZFuUVlZ7oNh
efRBqztGKMcVu8YcgxBu/xE8ssuLixZY6yzmYJOBtjerSXprMvS5tdLxMfyUSIAR
W3gjoYwOF+jeZ6PltXyAlYdU8WG6ZBIL9mIhiCY1koDokpSCRenrgQKBgQDbe1T7
/5bWrIa/C+sM0VgkQ4k2EwcyhgRuFr63fxmoxORiaWFvvKZlX5Aj8tuqK/S/TWzM
kb8T2ReBZj/2TiaDCCFivCyFr0OBQ5/qKQn3FcYd3mF4QbhurBVpKs+G9Ncw9JgC
0il/1tYVUwEo1Mm6EnL+HYou1F6NOJgMNXayLQKBgQCeqPeyA6WXZl2L2II+9lxu
svdEgdepIVwNEOa+Dm1bdiKFlZ6ZH0QVCKWsxivebl4xXfVNjJIaAgA9wBClxM/J
c2xfeAK/xUEbYnHlVtx9X0wSmZomlwiN3w1p9rq2KyYNTv/nLfa+pt7eoZzFE2qi
DJSFRJxCAvUlU2XMOWnLPA==
-----END PRIVATE KEY-----";

    public static string RSARSSAPSSCertPem => @"-----BEGIN CERTIFICATE-----

MIIDpTCCAo2gAwIBAgIJALJ812drJG7kMA0GCSqGSIb3DQEBCwUAMDkxCzAJBgNV
BAYTAlVTMQ0wCwYDVQQKDARUZXN0MRswGQYDVQQDDBJBbGxlbiBUZXN0IFJvb3Qg
Q0EwHhcNMjQwNTEwMTczNTM4WhcNMjUwNTIwMTczNTM4WjBCMQswCQYDVQQGEwJV
UzENMAsGA1UECgwEVGVzdDEkMCIGA1UEAwwbVGVzdCBDZXJ0aWZpY2F0ZSBSU0FT
U0EtUFNTMIIBIDALBgkqhkiG9w0BAQoDggEPADCCAQoCggEBANVPMSKeKl5nzis7
x9zQEj+ffE9Ijj4U4DopwChU6t8j7GkGQRd+Vo8KdsxqLIwoT55DDXM7ZZyg5trQ
ioYuQNjPg5pKC+Ause3cq5waWtzzpOyiiMRUIUSv/FJbp5iK3mUYXIqO+61WXA+p
Sl+gWO8ntw9RqEjZSEBhUXvfwwQWRZGKQLIi2hnY7nnkN7lH04jdVxawmVtTosYT
izxGLLTjAUT4fpb2E8m0hH8uH9vATYmgzWhLV8OvYJGKstrIiM8fney4SLHFJmAX
RgWDzlzPJLfZDrgSl5GGmBENcUYivw3MVAez7bugDVkOf1zcatXk6+980IvFK+Pu
wwbCxh0CAwEAAaOBqDCBpTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVu
U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUT7c/UVNAE0qaBQ/z
sdusHueync8wHwYDVR0jBBgwFoAUf7DEtTNMMo8puQQaQ4pTTD+qJYcwCwYDVR0P
BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B
AQsFAAOCAQEAOYOtyF2jX9CdBf9XkRSRzgaR10+yK0WBnE5NUEStfcrxCKuLlwGh
6lpvF7W6uxF2V4aYQbYzAVmKUperPvWWf8ns+egOOLoyGp3r9xgjmwne4YypDorR
M/t5xnB6t/AMi6j/e5bfaiX6HQLvFVzDNhyeGM8e3nl8b/hR26fcGZwg4clDHSH2
FW0NDBb+N+sf15qgGRnMeYaER7AkMlnlFxZu2wZ2gUZcMSADrK5H1+5QfmK+F50z
XNEyArYBcAn9JCa64Ru+zdDSzvh11RDTPm0hu7DVWO0AEUUHTQHM+GTmewrLM4KV
f2X2MCWTc+6SY4WSlTqKSIbA1jQfWob+4Q==
-----END CERTIFICATE-----";

    static string CertBytesHex => "308203a53082028da003020102020900b27cd7676b246ee4300d06092a864886f70d01010b05003039310b3009060355040613025553310d300b060355040a0c0454657374311b301906035504030c12416c6c656e205465737420526f6f74204341301e170d3234303531303137333533385a170d3235303532303137333533385a3042310b3009060355040613025553310d300b060355040a0c04546573743124302206035504030c1b54657374204365727469666963617465205253415353412d50535330820120300b06092a864886f70d01010a0382010f003082010a0282010100d54f31229e2a5e67ce2b3bc7dcd0123f9f7c4f488e3e14e03a29c02854eadf23ec690641177e568f0a76cc6a2c8c284f9e430d733b659ca0e6dad08a862e40d8cf839a4a0be02eb1eddcab9c1a5adcf3a4eca288c4542144affc525ba7988ade65185c8a8efbad565c0fa94a5fa058ef27b70f51a848d9484061517bdfc3041645918a40b222da19d8ee79e437b947d388dd5716b0995b53a2c6138b3c462cb4e30144f87e96f613c9b4847f2e1fdbc04d89a0cd684b57c3af60918ab2dac888cf1f9decb848b1c5266017460583ce5ccf24b7d90eb81297918698110d714622bf0dcc5407b3edbba00d590e7f5cdc6ad5e4ebef7cd08bc52be3eec306c2c61d0203010001a381a83081a530090603551d1304023000302c06096086480186f842010d041f161d4f70656e53534c2047656e657261746564204365727469666963617465301d0603551d0e041604144fb73f515340134a9a050ff3b1dbac1ee7b29dcf301f0603551d230418301680147fb0c4b5334c328f29b9041a438a534c3faa2587300b0603551d0f0404030205e0301d0603551d250416301406082b0601050507030106082b06010505070302300d06092a864886f70d01010b050003820101003983adc85da35fd09d05ff57911491ce0691d74fb22b45819c4e4d5044ad7dcaf108ab8b9701a1ea5a6f17b5babb117657869841b63301598a5297ab3ef5967fc9ecf9e80e38ba321a9debf718239b09dee18ca90e8ad133fb79c6707ab7f00c8ba8ff7b96df6a25fa1d02ef155cc3361c9e18cf1ede797c6ff851dba7dc199c20e1c9431d21f6156d0d0c16fe37eb1fd79aa01919cc79868447b0243259e517166edb067681465c312003acae47d7ee507e62be179d335cd13202b6017009fd2426bae11bbecdd0d2cef875d510d33e6d21bbb0d558ed001145074d01ccf864e67b0acb3382957f65f630259373ee92638592953a8a4886c0d6341f5a86fee1";

    static void Main(string[] args)
    {
        Console.WriteLine("Hello, World!");

        var t1 = new System.Security.Cryptography.X509Certificates.X509Certificate2(StringtoBytes(CertBytesHex));

        var cert = System.Security.Cryptography.X509Certificates.X509Certificate2.CreateFromPem(RSARSSAPSSCertPem, RSASSAPSSPrivateKeyPem);
    }

    public static byte[] StringtoBytes(string hex)
    {
        if (hex == null)
            return null;

        if (hex.Length == 0)
        {
            return new byte[0];
        }

        return Enumerable.Range(0, hex.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(hex.Substring(x, 2), 16)).ToArray();

    }
}

Expected behavior

The expected behavior is for X509Certificate2.CreateFromPem to properly return the X509Certificate2 object for an RSASSA-PSS certificate.

Actual behavior

The X509Certificate2.CreateFromPem() function returns the following CryptographicException: "System.Security.Cryptography.CryptographicException: ''1.2.840.113549.1.1.10' is not a known key algorithm.'"

Regression?

No response

Known Workarounds

No response

Configuration

This has been tested and verified at .NET 5, 7, and 8

Other information

The Certificate present has been created solely for this purpose and is not used for any other purpose thus the key is a "safe" key.

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label May 10, 2024
@vcsjones
Copy link
Member

A more distilled version of this problem is that RSA.ImportPkcs8PrivateKey cannot handle PKCS#8 RSA keys that have an ObjectIdentifier of 1.2.840.113549.1.1.10 (RSASSA-PSS).

The RSAKeyFormatHelper here:

private static readonly string[] s_validOids =
{
Oids.Rsa,
};

Does not handle the RSA-PSS OID.

I do not think it is quite as simple of "Add that OID to the array". We would still need to teach the RSA PKCS#8 handler to know what to do with RSASSA-PSS-params if they are present.

@vcsjones vcsjones self-assigned this May 10, 2024
@vcsjones
Copy link
Member

How exactly to fix this is probably worth some point of consideration. @bartonjs can probably remember things better here, but my memory is that RSA-PSS keys are not really encouraged anymore. PSS-ness is a property of the signature, not the key.

Having PSS parameters on the key is intended to restrict how signatures are produced, but we don't really have a good path for doing that. We could just ignore the parameters, but I could understand that not being an ideal implicit decision.

@vcsjones vcsjones removed their assignment May 10, 2024
@vcsjones vcsjones removed the untriaged New issue has not been triaged by the area owner label May 10, 2024
@vcsjones vcsjones added this to the Future milestone May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants