Description
Description
The legacy RSACryptoServiceProvider
is returning valid for RSA signatures that dont comply to PKCS1 even though the RSASignaturePadding.Pkcs1
parameter is used on Windows.
Context: An external signature service produced some RSA signatures in a non-compliant PKCS1 mode. Instead of passing a DigestInfo
to the RSA encoded message:
EM = 0x00 || 0x01 || PS || 0x00 || DigestInfo <= PKCS1 v1.5
They are using the direct hash value:
EM = 0x00 || 0x01 || PS || 0x00 || Hash <= PKCS1 v1.5 NON-compliant
On Windows, the use of RSACryptoServiceProvider
apparently accepts this type of NON-compliant encode on Verify methods. While it is invalidated on other systems.
Reproduction Steps
using System.Security.Cryptography;
var publicKeyPem = @"
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvN8/CFherks1TzXJVg0g
yr5sO1Vew967Q9c1bu9l9MmGvjGqbfHoh9tEhKtIEXBkMfIZ8Gm1vXBqNvB5c3xF
y8pRXwXyB7ost3leiUnJpRa27HfsnffXesrQPYSfrucUYBzzJLHDtrg1/IxkJA2M
jT1hSy0l0xllHys+uDu39cK6Grly4KRm8V2B05papxeNhj+vkj5JtPaTjtE8cYLD
93P06jgtFK8swz+2cSBCqwnrca68BilFoDi3ck3aM9NOFrSHTLfPMlIX8D5UnJwc
Ra7W2jBdSAaIZWE5fwz/50L7D5yun3jUSRsir2y9BQVU/2X8XO7DCjodjMo1llhy
RQIDAQAB
-----END PUBLIC KEY-----";
// CNG RSA
using var pubKey = RSA.Create();
pubKey.ImportFromPem(publicKeyPem);
// CAPI RSA
using var pubKeyCsp = new RSACryptoServiceProvider();
pubKeyCsp.ImportFromPem(publicKeyPem);
var hashAlgorithm = HashAlgorithmName.SHA256;
var hash = Convert.FromHexString("c5ceba0f092198e4821f99bf3556fff4675ee64ff0076f9b88b0d5fd156e678c");
var signature = Convert.FromHexString("6ab1e0483bc7ba56149c7e1e7087fc9bea685376cf4280f9ac474ee5a0f9294c29940359847cc642fd98f0476259e5d79a42b6e143157e43794d52b20766f70e2fb3da42f245c857b4f75b1e69a7203135a6f1cfa8873a9003c031daf59b0bf920a1d8be0187a4a53c75f4f5d08a7cedf05564c20730ae5bd0a605b0611f06db4775acd79097d5fb2cb6a35d8926f5f9496b328d93bb0e0dfa02a8abeb08b6f1cb3d544a9497ff493f1ec727e5cf64fcfdc808fd42d424b8b7dcc8dc9462a27f32289a9c187a60789d924495a48aefe2a5cd07b151f2aa294c50ce5a39b0678356b4e0c4d1eecc6c38c0725967460a4750320f36b0890b2bcb6373f2906f744a");
var v = pubKey.VerifyHash(hash, signature, hashAlgorithm, RSASignaturePadding.Pkcs1);
var vCsp = pubKeyCsp.VerifyHash(hash, signature, hashAlgorithm, RSASignaturePadding.Pkcs1);
Console.WriteLine($"Verify: {v}");
Console.WriteLine($"Verify CSP: {vCsp}");
Console.WriteLine("-----------------");
Expected behavior
The expected behavior should be a consistent result between systems. It could be understood from RSASignaturePadding.Pkcs1
docs
Gets an object that uses the
PKCS #1
v1.5 padding mode.
that it says only about the padding mode of PKCS1, not a full PKCS1 compliant?
I dont know. It looks like there is not a solution without a minor breaking change.
Actual behavior
Windows:
pubKeyCsp.VerifyHash(hash, signature, hashAlgorithm, RSASignaturePadding.Pkcs1)
=> TRUE
Other Systems:
pubKeyCsp.VerifyHash(hash, signature, hashAlgorithm, RSASignaturePadding.Pkcs1)
=> FALSE
Regression?
Affects all .Net versions
Known Workarounds
No response
Configuration
No response
Other information
No response