在C#中验证RSA SHA256签名 - java

我有一个签名和公共密钥,我想验证签名是否与我的输入数据匹配。我什至有一个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);

参考方案

两件事情;

签名不是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);

...给出true / true / true / true。

Java Double与BigDecimal - java

我正在查看一些使用双精度变量来存储(360-359.9998779296875)结果为0.0001220703125的代码。 double变量将其存储为-1.220703125E-4。当我使用BigDecimal时,其存储为0.0001220703125。为什么将它双重存储为-1.220703125E-4? 参考方案 我不会在这里提及精度问题,而只会提及数字…

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

Java-父类正在从子类中调用方法? - java

抱歉,我还是编码的新手,可能还没有掌握所有术语。希望您仍然能理解我的问题。我想得到的输出是:"Cost for Parent is: 77.77" "Cost for Child is: 33.33" 但是,我得到这个:"Cost for Parent is: 33.33" "Cost f…

Java Map,如何将UTF-8字符串正确放置到地图? - java

我有一个地图,LinkedHashMap更确切地说。我想在上面放一个字符串对象。然后,我读取此值以查看实际存储的内容。字符串本身具有非ASCII字符(西里尔文,韩文等)。将其放到地图上然后阅读后,这些字符将替换为??? s。一些代码:Map obj = new LinkedHashMap(); System.out.println("name: &…

HIbernate创建数据库表 - java

我正在学习JPA-Hibernate。我正在关注这个article在Dog.java中,它被称为@Table(name = "dog")。 在persistence.xml中,我有以下内容<property name="hibernate.hbm2ddl.auto" value="create"…