简体   繁体   English

验证 C# 中的 RSA SHA256 签名

[英]Verify RSA SHA256 signature in C#

I have a signature and public key and I want to verify that signature matches my input data.我有一个签名和公钥,我想验证签名是否与我的输入数据匹配。 I even have a Java sample that do it and works but cannot translate it to c#.我什至有一个 Java 样本可以做到这一点并且可以工作,但不能将其转换为 c#。

This is what I have tried with C# and nothing works这是我用 C# 尝试过的,但没有任何效果

string dataForSign = "456456" + "43223174" + "2016-11-28T14:57:50+0100" + "1148034147085158089";
string signature = "247A9B78E3FE5D4376B6A0DC2E6D721653E748F35473AFCD575FF8707CE6D8933E367B3D52E1EA6D2F2E22279F4EF5C144B48988352B02976D6CB864D947B02469DE7101A371FD4342E7C173F3C4C079B3E13B35D7FA60025A360A347D2A962B12BB3607E986CD32B149D4ADA87D94B4C4D632440066AFB8017527095420DFEC74C42D6D953FF292FB323FE59332ED81E7F227ACDDCC20AE54F9791F9A0C572ACB534278FD5850AB582E33D357448FE007702B6DB93C773DBB2349B00AF5D9FB116C70A70CF4EDCB95CD20D1D47705ADB7FBF38AF910289A128F08FFF2EB20C1BDF809D8D1EC9F0E3CAEBAE5593281ED50838807ED92B77B84F881B00490C56E";
string publicKey = "<RSAKeyValue><Modulus>MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA94CbbAspiut6qnC1iLzSJY4kmEgW/euPenOvMCB0EbbjSBVncx1Vi6UvbY86bu/3ZMgDBdhcq9fvqrdL2WLvacPWnHgIGCRV/8tlGs7oAcKei9V6OcyRjh0jD4TwBGqDUbQEfBXkLL1kJB8nPsLcUVrhmwGKM3qKTchSutpnDipRRSufswM2b8ScGLMX8O5J/54o85UiSP/ZZYcx4UDEpolN0k31Xa3fDw3tYn9KlIahALzgOqksF9jbv7jKS/DzpJAmQptuoL3t/0kj9J3tujh1NBpMoac7cCBiVCc+LVHga1Okn0R/1RotceYbkl6TaLW4O56XF5QorlHlkBWY5wID</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

byte[] dataForSignEncoded = Encoding.UTF8.GetBytes(dataForSign);
byte[] signatureEncoded = Convert.FromBase64String(signature);

RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
rsaCryptoServiceProvider.FromXmlString(publicKey);

var hashData = SHA256.Create().ComputeHash(dataForSignEncoded);
var result1 = rsaCryptoServiceProvider.VerifyHash(hashData, "SHA256", signatureEncoded);
var result2 = rsaCryptoServiceProvider.VerifyHash(hashData, signatureEncoded, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
var result3 = rsaCryptoServiceProvider.VerifyData(dataForSignEncoded, signatureEncoded, HashAlgorithmName.SHA256 ,RSASignaturePadding.Pkcs1);

And here is a working example in JAVA:这是 JAVA 中的一个工作示例:

String dataForSign = "456456" + "43223174" + "2016-11-28T14:57:50+0100" + "1148034147085158089";
String signature = "247A9B78E3FE5D4376B6A0DC2E6D721653E748F35473AFCD575FF8707CE6D8933E367B3D52E1EA6D2F2E22279F4EF5C144B48988352B02976D6CB864D947B02469DE7101A371FD4342E7C173F3C4C079B3E13B35D7FA60025A360A347D2A962B12BB3607E986CD32B149D4ADA87D94B4C4D632440066AFB8017527095420DFEC74C42D6D953FF292FB323FE59332ED81E7F227ACDDCC20AE54F9791F9A0C572ACB534278FD5850AB582E33D357448FE007702B6DB93C773DBB2349B00AF5D9FB116C70A70CF4EDCB95CD20D1D47705ADB7FBF38AF910289A128F08FFF2EB20C1BDF809D8D1EC9F0E3CAEBAE5593281ED50838807ED92B77B84F881B00490C56E";
String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA94CbbAspiut6qnC1iLzS\n"
                + "JY4kmEgW/euPenOvMCB0EbbjSBVncx1Vi6UvbY86bu/3ZMgDBdhcq9fvqrdL2WLv\n"
                + "acPWnHgIGCRV/8tlGs7oAcKei9V6OcyRjh0jD4TwBGqDUbQEfBXkLL1kJB8nPsLc\n"
                + "UVrhmwGKM3qKTchSutpnDipRRSufswM2b8ScGLMX8O5J/54o85UiSP/ZZYcx4UDE\n"
                + "polN0k31Xa3fDw3tYn9KlIahALzgOqksF9jbv7jKS/DzpJAmQptuoL3t/0kj9J3t\n"
                + "ujh1NBpMoac7cCBiVCc+LVHga1Okn0R/1RotceYbkl6TaLW4O56XF5QorlHlkBWY\n"
                + "5wIDAQAB";

byte[] publicKeyEncoded = DatatypeConverter.parseBase64Binary(publicKey);
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyEncoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(pubKeySpec);

Signature rsa = Signature.getInstance("SHA256withRSA");
rsa.initVerify(pk);
rsa.update(dataForSign.getBytes("UTF-8"));
boolean result = rsa.verify(StringUtil.tobin(signature)); // convert hex signature to bytes
System.out.println(result);

Two things;两件事情;

  • the signature is not base64 encoded, it's a hex string, so you're comparing to the wrong signature.签名不是 base64 编码的,它是一个十六进制字符串,所以你在比较错误的签名。 A correct way of converting it can for example be found here ;例如,可以在此处找到正确的转换方法;
public static byte[] StringToByteArray(string hex)
{
    return Enumerable.Range(0, hex.Length)
        .Where(x => x % 2 == 0)
        .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
        .ToArray();
}
  • You seem to have encoded your RSA key wrong into XML which also gives you a mismatch.您似乎将您的 RSA 密钥错误地编码为 XML ,这也给您带来了不匹配。

Correcting those two things;纠正这两件事;

string dataForSign = "456456" + "43223174" + "2016-11-28T14:57:50+0100" + "1148034147085158089";
string signature = "247A9B78E3FE5D4376B6A0DC2E6D721653E748F35473AFCD575FF8707CE6D8933E367B3D52E1EA6D2F2E22279F4EF5C144B48988352B02976D6CB864D947B02469DE7101A371FD4342E7C173F3C4C079B3E13B35D7FA60025A360A347D2A962B12BB3607E986CD32B149D4ADA87D94B4C4D632440066AFB8017527095420DFEC74C42D6D953FF292FB323FE59332ED81E7F227ACDDCC20AE54F9791F9A0C572ACB534278FD5850AB582E33D357448FE007702B6DB93C773DBB2349B00AF5D9FB116C70A70CF4EDCB95CD20D1D47705ADB7FBF38AF910289A128F08FFF2EB20C1BDF809D8D1EC9F0E3CAEBAE5593281ED50838807ED92B77B84F881B00490C56E";
string publicKey =
    "<RSAKeyValue><Modulus>94CbbAspiut6qnC1iLzSJY4kmEgW/euPenOvMCB0EbbjSBVncx1Vi6UvbY86bu/3ZMgDBdhcq9fvqrdL2WLvacPWnHgIGCRV/8tlGs7oAcKei9V6OcyRjh0jD4TwBGqDUbQEfBXkLL1kJB8nPsLcUVrhmwGKM3qKTchSutpnDipRRSufswM2b8ScGLMX8O5J/54o85UiSP/ZZYcx4UDEpolN0k31Xa3fDw3tYn9KlIahALzgOqksF9jbv7jKS/DzpJAmQptuoL3t/0kj9J3tujh1NBpMoac7cCBiVCc+LVHga1Okn0R/1RotceYbkl6TaLW4O56XF5QorlHlkBWY5w==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

byte[] dataForSignAsBytes = Encoding.UTF8.GetBytes(dataForSign);
byte[] signatureAsBytes = StringToByteArray(signature);

RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
rsaCryptoServiceProvider.FromXmlString(publicKey);

var hashData = SHA256.Create().ComputeHash(dataForSignAsBytes);

var result1 = rsaCryptoServiceProvider.VerifyData(dataForSignAsBytes, CryptoConfig.MapNameToOID("SHA256"), signatureAsBytes);
var result2 = rsaCryptoServiceProvider.VerifyHash(hashData, CryptoConfig.MapNameToOID("SHA256"), signatureAsBytes);
var result3 = rsaCryptoServiceProvider.VerifyHash(hashData, signatureAsBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
var result4 = rsaCryptoServiceProvider.VerifyData(dataForSignAsBytes, signatureAsBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
Console.WriteLine(result1);
Console.WriteLine(result2);
Console.WriteLine(result3);
Console.WriteLine(result4);

...gives true/true/true/true. ...给出真/真/真/真。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM