如何使用rsa正确验证数据?

时间:2017-08-21 01:20:17

标签: c# encoding rsa digital-signature

我想使用私钥对邮件进行签名并使用公钥进行验证,但我无法让它工作..

以下是我对数据进行签名的方式(已编辑,但仍无效):

public static string SignData(string message, string privateKey) {

        byte[] plainText = ASCIIEncoding.Unicode.GetBytes(message);

        var rsaWrite = new RSACryptoServiceProvider();
        rsaWrite.FromXmlString(privateKey);

        byte[] signature = rsaWrite.SignData(plainText, new SHA1CryptoServiceProvider());

        return Convert.ToBase64String(signature);
    }

以下是我测试数据的方式(已编辑,仍无效):

public static bool VerifyData(string sign, string publicKey, string orig) {

        byte[] signature = Convert.FromBase64String(sign);
        byte[] original = ASCIIEncoding.Unicode.GetBytes(orig);

        var rsaRead = new RSACryptoServiceProvider();
        rsaRead.FromXmlString(publicKey);

        if (rsaRead.VerifyData(original, new SHA1CryptoServiceProvider(), signature)) {
            return true;
        } else {
            return false;
        }
    }

我将密钥对存储为我的帐户类中的xml字符串。此函数在account.cs的构造函数中执行:

public void addKeys() {

    RSACryptoServiceProvider provider = new RSACryptoServiceProvider(1024);

    privateKey = provider.ToXmlString(true);
    publicKey = provider.ToXmlString(false);
}

我用这个测试整体事情:

string signedHash = Utility.SignData("test" ,account.privateKey);

if (Utility.VerifyData(signedHash, account.publicKey, "test")) {          
    Console.WriteLine("WORKING!");
} else {
    Console.WriteLine("SIGNING NOT WORKING");
}

为什么整体不起作用?我的猜测是因为一些编码的东西它不起作用。

1 个答案:

答案 0 :(得分:3)

clojure.reflect

签名是任意二进制数据,它不一定是合法的Unicode / UCS-2。您需要使用任意编码(https://en.wikipedia.org/wiki/Binary-to-text_encoding#Encoding_standards)来编码所有任意数据。最受欢迎的签名传输是Base64,所以你想要

return ASCIIEncoding.Unicode.GetString(signature);

当然,在验证方法中使用return Convert.ToBase64String(signature);

如果您使用.NET 4.6或更高版本的目标进行编译,您还可以使用较新的sign / verify API:

Convert.FromBase64String

将是

rsaRead.VerifyData(original, new SHA1CryptoServiceProvider(), signature)

虽然它可能看起来不简单,但它会阻止SHA1CryptoServiceProvider的分配和最终化,而另一种方法的做法是,当你想要从Pkcs1签名填充切换到PSS签名填充时,它会为The Future设置。 (但真正的优点是该方法位于rsaRead.VerifyData(original, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1) 基类而不是RSA特定类型。)