【问题标题】:C# Signing and verifying signatures with RSA. Encoding issueC# 使用 RSA 签名和验证签名。编码问题
【发布时间】:2017-09-07 08:21:00
【问题描述】:

我的问题与 2011 年的一个表格 Signing and verifying signatures with RSA C# 非常相似。尽管如此,当我比较签名数据和原始消息时,我也会得到错误。请指出我的错误。

代码:

 public static void Main(string[] args)
    {            

        //Generate a public/private key pair.  
        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

        //Save the public key information to an RSAParameters structure.
        RSAParameters RSAPublicKeyInfo = RSA.ExportParameters(false);
        RSAParameters RSAPrivateKeyInfo = RSA.ExportParameters(true);    

        string message = "2017-04-10T09:37:35.351Z";

        string signedMessage = SignData(message, RSAPrivateKeyInfo);

        bool success = VerifyData(message, signedMessage, RSAPublicKeyInfo);

        Console.WriteLine($"success {success}");

        Console.ReadLine();
    }   

签名方式:

 public static string SignData(string message, RSAParameters privateKey)
    {
        ASCIIEncoding byteConverter = new ASCIIEncoding();

        byte[] signedBytes;

        using (var rsa = new RSACryptoServiceProvider())
        {
            // Write the message to a byte array using ASCII as the encoding.
            byte[] originalData = byteConverter.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 byte array back to a string message
        return byteConverter.GetString(signedBytes);
    }

验证方式:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
    {
        bool success = false;
        using (var rsa = new RSACryptoServiceProvider())
        {
            ASCIIEncoding byteConverter = new ASCIIEncoding();

            byte[] bytesToVerify = byteConverter.GetBytes(originalMessage);
            byte[] signedBytes = byteConverter.GetBytes(signedMessage);

            try
            {
                rsa.ImportParameters(publicKey);

                success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                rsa.PersistKeyInCsp = false;
            }
        }
        return success;
    }

基本上问题在于字符串到字节[] 的编码。我在 ASCIIEncoding 和 UTF8Encoding 上遇到了同样的问题。

提前谢谢你!

【问题讨论】:

    标签: c# encoding rsa signing


    【解决方案1】:

    您不能在编码消息上使用ASCIIEncoding,因为它包含无效的 ASCII 字符字节。存储编码消息的典型方式是使用 base64 字符串。

    SignData中,使用以下代码将字节数组编码为字符串:

    return Convert.ToBase64String(signedBytes);
    

    VerifyData 中,使用以下内容将字符串解码回相同的字节数组:

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

    【讨论】:

    • 感谢您的及时回复!但是,当我使用时,我得到“System.FormatException:'输入不是有效的 Base-64 字符串,因为它包含非 base 64 字符、两个以上的填充字符或填充字符中的非法字符。'” FromBase64String 用于消息“2017-04-10T09:37:35.351Z”。
    • 在验证之前字符串是否有任何变化?我使用上面的 2 处更改运行了您发布的代码,并且成功了。
    • 你是对的!我的坏处是我还试图在签名之前对原始数据的 Base64 字符串执行字符串。
    猜你喜欢
    • 2012-01-16
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多