Skip to content

RSA Verify Inconsistent for PKCS1 non-compliant #114967

Closed as duplicate of#28252
Closed as duplicate of#28252
@brunocapu

Description

@brunocapu

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions