【问题标题】:Verify RSA SHA256 signature in C#在 C# 中验证 RSA SHA256 签名
【发布时间】:2019-10-31 10:09:45
【问题描述】:

我有一个签名和公钥,我想验证签名是否与我的输入数据匹配。我什至有一个 Java 示例可以执行此操作,但无法将其转换为 c#。

这是我用 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);

这是一个 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);

【问题讨论】:

    标签: java c# hash rsa signature


    【解决方案1】:

    两件事;

    • 签名不是 base64 编码的,它是一个十六进制字符串,所以你在比较错误的签名。例如,可以找到正确的转换方法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();
    }
    
    • 您似乎将 RSA 密钥错误地编码到 XML 中,这也导致了不匹配。

    纠正这两件事;

    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);
    

    ...给出真/真/真/真。

    【讨论】:

    猜你喜欢
    • 2017-06-22
    • 2017-07-30
    • 2016-09-26
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    相关资源
    最近更新 更多