C# 使用RSA C签名和验证签名#

C# 使用RSA C签名和验证签名#,c#,encoding,rsa,signing,C#,Encoding,Rsa,Signing,我最近发布了关于使用RSA加密大数据的问题,我终于解决了这个问题,现在我将继续使用用户的私钥实现签名,并使用相应的公钥进行验证。然而,每当我比较签名数据和原始消息时,基本上只返回false。我希望你们中的一些人能看到我做错了什么 代码如下: public static string SignData(string message, RSAParameters privateKey) { //// The array to store the signed message

我最近发布了关于使用RSA加密大数据的问题,我终于解决了这个问题,现在我将继续使用用户的私钥实现签名,并使用相应的公钥进行验证。然而,每当我比较签名数据和原始消息时,基本上只返回false。我希望你们中的一些人能看到我做错了什么

代码如下:

public static string SignData(string message, RSAParameters privateKey)
    {
        //// The array to store the signed message in bytes
        byte[] signedBytes;
        using (var rsa = new RSACryptoServiceProvider())
        {
            //// Write the message to a byte array using UTF8 as the encoding.
            var encoder = new UTF8Encoding();
            byte[] originalData = encoder.GetBytes(message);

            try
            {
                //// Import the private key used for signing the message
                rsa.ImportParameters(privateKey);

                //// Sign the data, using SHA512 as the hashing algorithm 
                signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512"));
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
            finally
            {
                //// Set the keycontainer to be cleared when rsa is garbage collected.
                rsa.PersistKeyInCsp = false;
            }
        }
        //// Convert the a base64 string before returning
        return Convert.ToBase64String(signedBytes);
    }
这是签署数据的第一步,接下来我将验证数据:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
    {
        bool success = false;
        using (var rsa = new RSACryptoServiceProvider())
        {
            byte[] bytesToVerify = Convert.FromBase64String(originalMessage);
            byte[] signedBytes = Convert.FromBase64String(signedMessage);
            try
            {
                rsa.ImportParameters(publicKey);

                SHA512Managed Hash = new SHA512Managed();

                byte[] hashedData = Hash.ComputeHash(signedBytes);

                success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                rsa.PersistKeyInCsp = false;
            }
        }
        return success;
    }
下面是测试客户端:

public static void Main(string[] args)
    {
        PublicKeyInfrastructure pki = new PublicKeyInfrastructure();
        Cryptograph crypto = new Cryptograph();
        RSAParameters privateKey = crypto.GenerateKeys("email@email.com");

        const string PlainText = "This is really sent by me, really!";

        RSAParameters publicKey = crypto.GetPublicKey("email@email.com");

        string encryptedText = Cryptograph.Encrypt(PlainText, publicKey);

        Console.WriteLine("This is the encrypted Text:" + "\n " + encryptedText);

        string decryptedText = Cryptograph.Decrypt(encryptedText, privateKey);

        Console.WriteLine("This is the decrypted text: " + decryptedText);

        string messageToSign = encryptedText;

        string signedMessage = Cryptograph.SignData(messageToSign, privateKey);

        //// Is this message really, really, REALLY sent by me?
        bool success = Cryptograph.VerifyData(messageToSign, signedMessage, publicKey);

        Console.WriteLine("Is this message really, really, REALLY sent by me? " + success);

    }
我在这里漏了一步吗?根据加密API和那里的示例,我不应该手动计算任何哈希,因为我在方法调用本身中提供了算法


非常感谢您的帮助。

您的问题出现在验证数据方法的开头:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
    bool success = false;
    using (var rsa = new RSACryptoServiceProvider())
    {
        //Don't do this, do the same as you did in SignData:
        //byte[] bytesToVerify = Convert.FromBase64String(originalMessage);
        var encoder = new UTF8Encoding();
        byte[] bytesToVerify = encoder.GetBytes(originalMessage);

        byte[] signedBytes = Convert.FromBase64String(signedMessage);
        try
        ...

出于某种原因,您从Base64String切换到了
,而不是
UTF8Encoding.GetBytes

PublicKeyInfrastructure
crypto.GenerateKeys
来自何处?PublicKeyInfrastructure只是一个集合类,在存储某些公钥信息时处理一些序列化。GenerateKeys方法来自生成公钥/私钥对的助手类。很抱歉,这不够清楚。@SimonLanghoff为什么在VerifyData()中计算
hashedData
,然后不使用它?这是打字错误吗?在VerifyData中,您应该调用rsa.VerifyHash(hashedData)吗?或者这与调用rsa.VerifyData(data)相同?另请参见、、等。此外,对于签名数据,您应该使用私钥,然后使用公钥解密使用私钥签名的数据。这是因为您分发的是公钥,而不是私钥。我知道RSA可以加密的最大字符串大小。RSA是否也可以签名最大字符串大小?或者它可以在任意长度的字符串上签名?@krangprime错了。当您签名时,您使用私钥进行签名,然后公共方使用您相应的公钥进行验证,而不是解密。当涉及到加密时,公共方将使用您的公钥对数据进行加密,然后您使用私钥对其进行解密