【问题标题】:How to verify digital signature in C#如何在 C# 中验证数字签名
【发布时间】:2019-11-01 18:03:22
【问题描述】:

我是新来的。

我正在学习 C# 中的数字签名。生成证书后跟this document。我阅读的其他文件:RSACng, X509Certificate2.

我正在使用 Windows 10 Pro 1809、.Net Core 2.1、VSCode。

    class Program
    {
        static void Main(string[] args)
        {
            var passwd = "password";

            // Get client certificate.
            var clientCertPath = @"./Certificates/test.pfx";
            var clientCert = new X509Certificate2(clientCertPath, passwd);

            // Get server certificate.
            var serverCertPath = @"./Certificates/test.cer";
            var serverCert = new X509Certificate2(serverCertPath);

            // Generate data.
            var translateResultData = BuildData();
            var content = String.Join('&', translateResultData.Select(p => String.Join('=', p.Key, p.Value)));

            // Sign
            var sign = SignatureUtil.Sign(data: content, clientCert: clientCert);
            // translateResultData.TryAdd(key: "sign", value : sign);

            // Copy content ONLY for test.
            var checkSign = sign;
            var checkContent = content;

            // Verify
            var valid = SignatureUtil.Verify(data: checkContent, signature: checkSign, serverCert: serverCert);
            System.Console.WriteLine(valid);
        }
}
    public class SignatureUtil
    {
        public static string Sign(string data, X509Certificate2 clientCert)
        {
            using(var privateKey = clientCert.GetRSAPrivateKey())
            {
                var dataByteArray = Encoding.UTF8.GetBytes(data);
                var signatureByteArray = privateKey.SignData(
                    data: dataByteArray,
                    hashAlgorithm: HashAlgorithmName.SHA256,
                    padding: RSASignaturePadding.Pkcs1);
                return Convert.ToBase64String(signatureByteArray);
            }
        }

        public static bool Verify(string data, string signature, X509Certificate2 serverCert)
        {
            try
            {
                using(var publicKey = serverCert.GetRSAPublicKey())
                {
                    var dataByteArray = Encoding.UTF8.GetBytes(data);
                    var signatureByteArray = Convert.FromBase64String(signature);
                    return publicKey.VerifyData(
                        data: dataByteArray,
                        signature: signatureByteArray,
                        hashAlgorithm: HashAlgorithmName.SHA256,
                        padding: RSASignaturePadding.Pkcs1);
                }
            }
            catch (System.Exception)
            {
                return false;
            }
        }
    }

预期结果:valid 应该是 true,因为我正在检查原始数据。
事实:Verify 方法总是返回false,即使原始数据被传递。

你能告诉我我做错了什么吗?

【问题讨论】:

  • 您阅读异常文本了吗?
  • 您看到了什么错误?您好,欢迎来到 StackOverflow。请花一些时间阅读帮助页面,尤其是名为How to Ask 的部分。您可能还想了解minimal reproducible example
  • @PatrickHofman 也不例外。 false 结果由 publicKey.VerifyData() 返回。
  • @Yue 你能删除 try/catch 以确保 100% 确定吗?
  • @John 感谢您的建议。我删除了 try/catch 并得到相同的结果,总是false

标签: c# .net .net-core


【解决方案1】:

我无法告诉您代码中出了什么问题,因为我无法重现它。 Here 是一个非常详细的答案,您可以使用 RSA 和 SHA256 进行签名。您的方法和此答案中描述的方法在概念上是相同的,但与此答案相比,您的代码可能有所不同。

以下是我公司如何使用与智能卡关联的证书来签署和验证签名的示例。一个很大的区别是我们不将签名存储为字符串,而是将其保存为字节数组。

public byte[] SignData(byte[] data)
{
    using (var sha256 = SHA256.Create())
    {
        using (var rsa = Certificate.GetRSAPrivateKey())
        {
            return rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)
        }
    }
}


public bool VerifySignature(byte[] data, byte[] signature)
{
    using (var sha256 = SHA256.Create())
    {
        using (var rsa = Certificate.GetRSAPublicKey())
        {
            return rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)
        }
    }
}

【讨论】:

  • 签名和检查签名都需要私钥吗?
  • @Noman_1 不,您只需要使用私钥进行签名。使用公钥验证签名。
  • @Pete那么你为什么要使用私钥来验证签名呢?
  • 我没有使用私钥进行验证。这是我没有意识到的复制和粘贴错误。很抱歉造成混淆,我编辑了我的答案以更正它。
猜你喜欢
  • 2015-08-14
  • 2013-04-15
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 2017-10-11
  • 2016-07-10
  • 1970-01-01
  • 2011-10-09
相关资源
最近更新 更多