RSA签名验证适用于.Net核心,但不适用于.Net 4.8

问题描述

我有一个非常简单的.Net控制台应用程序,我将在此处粘贴该应用程序,该应用程序执行RSA签名验证,并且可以在.Net Core 3.1上完美运行。但是,.net 4.8控制台应用程序上完全相同的代码(复制粘贴,不作任何更改)表示签名无效。

我不知道发生了什么。在我测试过的所有其他语言甚至在线RSA签名验证器中,此签名都是可以的。

在两者上都使用Nuget BouncyCastle 1.8.6.1。

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;


    public class Program
    {
        static void Main()
        {
            byte[] publicKeyData = Convert.FromBase64String("LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUE1RGxFVVRtQUF0ZGIvVXZGYnpiWQpxbVJYNGZ6VW80WGhIbTk1VDRvbS9OaVplbFBNYzFOUjNNMVV0OFIyQkdRdmt2MndEUUkzblk2ZklLeUtWM3VVCjR4ZTIvMW1IQkdaSVB5WHRLKzdaelJJbkl1aTVtT0x2R2FTOVBlaFJSMTVvTTZXT3pweTdOay9QRjlUUHltWEEKWEZnQWZTZFo3bUx4QldqUktjMGorUTNZRGZuWi9OMzUzZUJEc1FWN2tkamVFYVpmK3RUZll5eFVpY2RTUjZVUgpsOUl4YW5yc2RqVjF1TndmWm5yYTdDVTFhcElCcjNFeDZBb20yWDVtNjZ4TjRXeVJHRCtOS3ZBeitNVHZkSU4vClNLVU1UMnA0aEpWc3FiZ2hGN2FZeDYxNGxHbmN5dTZQNDQ4QjlBcjh2R0NLbDRnMGl0eUtjbGJSZS9wMjh2U2oKWkxwYkVjZkY2eHlJYlJraWZEbHJITUlQS1JkazRIV25wamQvaEdHN2lZN1VWYWJuUmxpVUExVDQ3T2kyaENVNwoxKzVkT1F4dDdRNVFxUFNURFNZc1E4M1c5VStmZ0xMYVVWSFA5SzhpdG1qWW1ueFF2a1FqUnc5YUhYTk5Db2M4ClZrdFBnY1A0UFJTZ0dLL2JWbWtIbjBrWDMvclVEZG9zV1dHaURUWnZwRFRKUHo3UVpmbENFRDFzV0xIaEMxOU8KdWtFdEFQYVR5VkJ5RC9yUURoTWJyb2RIVmRJNjhZeE5UdnNpU2NxdlMvZlBmYUVUcUJsVzJpQXVndE5TZGIzSApEOFVFUUgzTUE0K044RXVtK1o5bzQ2Vnk2c0hOVytVVE0wRDVwOXBvWWEwV1dxQ0hLc2ZqbFcyN0dIaDF1WDZKCmNHd0NBc1pBT2N6MEpPRWVuSDFtYXhrQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=");
            string decodedPublicKeyString = Encoding.UTF8.GetString(publicKeyData);
            string signedData = "RHClqUohXp5QOvBAYqTMa63PuYXahqKEDUIdCYfA/qq1mT18QSVIu5gneYbYjAQH4dWE5wytMnIihNZkFcY06WjIeTwJJVHZPmp/SGQvO44ouF2Qhb6n9HmgdqLzL1gPUVeElyeytDvcaRgkI2tqIZ+3a1QERVpH49xGQzf2N1YcFycOrm08CHO3o9jTWJrtURntgOV9cGUStZy2mEJ5CvNo8+5Fniidsjpn4Bem/34PdFNRjVRgrVVqVjaB6ICB6KTMPzd/jPF02cPGA5n7j5Stn9DpU1uyicEhCsMK/zxrfSYpKdXH74fjIP7Rw9HlWnAVlLv/pkVpCcRLLn7iW1V6MPvzuL9rft2QK61RDSo4Ntka6a48+FJPB2v9pTY8qu4jIUcpLGX+wYnHCt9nZnZ4UlFh6BKDFrpH1tZJ2XreS2qGlSiBii0j30VyjCinEz8rIFFes7kGbWm/6jdXZliWbgPpZ7shEVSTwPDy6UVeD0LP9m/OxLNfCF31bOLkacxA8qv5PvbntWUcuNsUqdrk5YKcaDdQq4texWm1CQtBs7gYVwARYHusHi6ISUCHGN0RnULcPLa7jfZVq/y56DV0tuxhxsxyu9BpCx6Rm5AlYJJcgRyRRsaldivHBdvNJZCDPIVBBmpbpfKoctwWSvROmnirCFc9iQb8gnNNtlc=";
            var signedBytes = Convert.FromBase64String(signedData);
            VerifyWithPublicKey("12345789",signedBytes,decodedPublicKeyString);
        }

        private static bool VerifyWithPublicKey(string data,byte[] signedHash,string decodedPublicKey)
        {
            try
            {
                using (RSA rsa = RSA.Create())
                {
                    byte[] hash;

                    using (SHA256 shaM = SHA256.Create())
                    {
                        hash = shaM.ComputeHash(Encoding.ASCII.GetBytes(data));
                    }

                    using (var keyreader = new StringReader(decodedPublicKey))
                    {
                        var pemReader = new PemReader(keyreader);
                        var y = (RsaKeyParameters)pemReader.Readobject();
                        var rsaParameters = new RSAParameters();
                        rsaParameters.Modulus = y.Modulus.ToByteArray();
                        rsaParameters.Exponent = y.Exponent.ToByteArray();
                        rsa.ImportParameters(rsaParameters);

                        RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);
                        RSADeformatter.SetHashAlgorithm("SHA256");

                        if (RSADeformatter.VerifySignature(hash,signedHash))
                        {
                            Console.WriteLine("The signature was verified.");
                            return true;
                        }
                        else
                        {
                            Console.WriteLine("The signature was not verified.");
                            return false;
                        }
                    }
                }
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
            }
            return false;
        }

    }

解决方法

在我的计算机上运行,​​对于4.6.2和4.7.2均产生false。但是,更改

rsaParameters.Modulus = y.Modulus.ToByteArray();
rsaParameters.Exponent = y.Exponent.ToByteArray();

rsaParameters.Modulus = y.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = y.Exponent.ToByteArrayUnsigned();

似乎可以解决此问题。我希望这对您有用。