java - 用 C# 签名的数据,在 C# 中验证,但在 Java 中不验证
问题描述
我已经签署了我想在 C# 和 Java 中验证的数据。虽然它在 C# 中验证良好,但在 Java 中失败(没有例外,但验证函数返回 false。
C#代码:
using System;
using System.Security.Cryptography;
namespace ConsoleApp3
{
class Program
{
static void Main()
{
var publicKeyXml = "<RSAKeyValue><Modulus>19mQjm4uJASc0BGcaAm5IRNbQWkT+VlqAN3cqWgdXhjNFY1FaaMV6H7gFJdOffEMRMcPjslH1Sc2HlOSDeZIqZJFZT8Lhk5DAtcA/WtmEhF3zt6cjvPqoWRXGweb2vC0KWGUC+GF3OTlrC4QwHf2xyMe1yeY/opjigWjMJkrDfD8G3nSY5QAPUaeCfrRikC0hq66OIApEwMS4inQcHZKmIq31U2BK84qsB3UWNpsK1XcbMkHOZfvyqhfHLuLScXQgFxzTzrH5/J51UzU1Pc0o4c7T+TJq4i9f9MOs13PhY5uNQwGyQ0H5bf4VQt9dRhZF2T1TxSk0T4PEbXP50dLDjAY9/S/8ud/lhFSqre7KOxIxDcJ/bk1j4UWEChom2TaS5+4QWQyHMfeZtYFlDR3iZw5eL2SuhvG+ZkZ4rfugqY9hUwfpVmhjp6z/CKcpaSuwzxwYxR2WIC79n6uTF97ay9W6SYgKxuz5YjeIUoPamKEOTJi36IsCCjdsa8a8nE4LoFBoeCGYDZTlrHBzQ76T6M7sdaZUrR4uttftwrslcrnYPNc/DVM9Y+oQ1ZcPcTnArn+PbNiRwgj6Bk/+HJ6CpNxhtn6P5STHa5SblBNvVX4AZ//y5xGt9Sc4ouWpLIICwjBo8Xq7HkTEAH4MYzJOvlBQBLeTTxGeI1VBkxfsVk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
var data = new byte[] {1, 2, 3, 4};
var signature = Convert.FromBase64String(
"r0NOhHjRkV3muCh7paDQkKNGTAZFGCK/viWQa33Y7ysM3XsP7+HychZVYJocpKn6M01T5o2ltdjSeJeBPQY3KrLszMJhbGgK4kme6qx/qQj7mLOkefxgEfijxcDkhQ2dmI+RWNPckyqEt0hrqju1TWO4/Pju1wWvSsYiSD17xF9o+yy88Okkg4Z3DFIGXrXaGjJUfnG48tIR1plhoud9LvVFB8uq03XuY47b3JaClh96k/1X8WSCwzD0kw1zdTqkxLP4snLPgyMyG34ChiAgouH4NS6VTKF9iQ0gtOK3Mz2lPuWMDpgyC25C7yuRGtV+6G9Vyu0YBQDW8lbthuKLACoIMsonkZRoY7Sx2l85XnwNQgc40T9itPo6DCoE0FWHEvBkmLgxPTDMaLLG2aovpUGgCaPr5ia2aA10myB+CgPgM95sesHPZTINTESh2tpXim3dMxQPdkruwyLzpZ00oqM2J0Lkz8MMgmPRfrpoxZZoXByWpK1ofoREa20yjxCd7cXp39hIf3spmHsp/s1bS6dF9Iwlybo5gNX9by33TBvpOcUUX7B4XKzuYQ+s7ZnCeYxcAdk4Fd4aYcmEOpsxue+UxKZn+5KRcBm3S3hiR4CIIXG8X+0YU6haI9U3WR9ajmLiMK2aixLtzYkMo7wBPZRJDlua5mR4k2C5Jhjinvg=");
var rsaKey = new RSACryptoServiceProvider();
rsaKey.FromXmlString(publicKeyXml);
if (rsaKey.VerifyData(data, "SHA256", signature))
Console.WriteLine("VERIFIED");
}
}
}
Java代码:
import java.math.BigInteger;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
public class Main {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
String publicKeyModulus = "19mQjm4uJASc0BGcaAm5IRNbQWkT+VlqAN3cqWgdXhjNFY1FaaMV6H7gFJdOffEMRMcPjslH1Sc2HlOSDeZIqZJFZT8Lhk5DAtcA/WtmEhF3zt6cjvPqoWRXGweb2vC0KWGUC+GF3OTlrC4QwHf2xyMe1yeY/opjigWjMJkrDfD8G3nSY5QAPUaeCfrRikC0hq66OIApEwMS4inQcHZKmIq31U2BK84qsB3UWNpsK1XcbMkHOZfvyqhfHLuLScXQgFxzTzrH5/J51UzU1Pc0o4c7T+TJq4i9f9MOs13PhY5uNQwGyQ0H5bf4VQt9dRhZF2T1TxSk0T4PEbXP50dLDjAY9/S/8ud/lhFSqre7KOxIxDcJ/bk1j4UWEChom2TaS5+4QWQyHMfeZtYFlDR3iZw5eL2SuhvG+ZkZ4rfugqY9hUwfpVmhjp6z/CKcpaSuwzxwYxR2WIC79n6uTF97ay9W6SYgKxuz5YjeIUoPamKEOTJi36IsCCjdsa8a8nE4LoFBoeCGYDZTlrHBzQ76T6M7sdaZUrR4uttftwrslcrnYPNc/DVM9Y+oQ1ZcPcTnArn+PbNiRwgj6Bk/+HJ6CpNxhtn6P5STHa5SblBNvVX4AZ//y5xGt9Sc4ouWpLIICwjBo8Xq7HkTEAH4MYzJOvlBQBLeTTxGeI1VBkxfsVk=";
String publicKeyExponent = "AQAB";
byte[] data = new byte[]{1,2,3,4};
byte[] signature = Base64.getDecoder().decode(
"r0NOhHjRkV3muCh7paDQkKNGTAZFGCK/viWQa33Y7ysM3XsP7+HychZVYJocpKn6M01T5o2ltdjSeJeBPQY3KrLszMJhbGgK4kme6qx/qQj7mLOkefxgEfijxcDkhQ2dmI+RWNPckyqEt0hrqju1TWO4/Pju1wWvSsYiSD17xF9o+yy88Okkg4Z3DFIGXrXaGjJUfnG48tIR1plhoud9LvVFB8uq03XuY47b3JaClh96k/1X8WSCwzD0kw1zdTqkxLP4snLPgyMyG34ChiAgouH4NS6VTKF9iQ0gtOK3Mz2lPuWMDpgyC25C7yuRGtV+6G9Vyu0YBQDW8lbthuKLACoIMsonkZRoY7Sx2l85XnwNQgc40T9itPo6DCoE0FWHEvBkmLgxPTDMaLLG2aovpUGgCaPr5ia2aA10myB+CgPgM95sesHPZTINTESh2tpXim3dMxQPdkruwyLzpZ00oqM2J0Lkz8MMgmPRfrpoxZZoXByWpK1ofoREa20yjxCd7cXp39hIf3spmHsp/s1bS6dF9Iwlybo5gNX9by33TBvpOcUUX7B4XKzuYQ+s7ZnCeYxcAdk4Fd4aYcmEOpsxue+UxKZn+5KRcBm3S3hiR4CIIXG8X+0YU6haI9U3WR9ajmLiMK2aixLtzYkMo7wBPZRJDlua5mR4k2C5Jhjinvg=");
byte[] mod = Base64.getDecoder().decode(publicKeyModulus);
byte[] exp = Base64.getDecoder().decode(publicKeyExponent);
BigInteger modulus = new BigInteger(mod);
BigInteger exponent = new BigInteger(exp);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature s = Signature.getInstance("SHA256withRSA");
s.initVerify(pubKey);
s.update(data);
if (s.verify(signature))
System.out.println("VERIFIED");
}
}
我发现了几个类似的 SO 帖子,但找不到解决方案。有人提到了 .NET 和 Java 之间 BigInteger 编码的区别。我确认字节顺序不同:当在 java 程序中反转“mod”缓冲区时(小端 -> 大端),在创建 BigInteger 之前,“模数”与 .NET 中的相同(如果我采用从 .NET 中的 XML 中提取模数并将其转换为 BigInteger)。指数缓冲区读取 0x01 0x00 0x01,所以没关系(前后相同)。但是在这样做之后,验证仍然失败。
解决方案
推荐阅读
- javascript - Angular Material:从形式中获取价值
- java - TestNG Selenium:为什么@Before 工作正常但@BeforeTest 抛出 NullPointerException?
- python - Python中的词频而不是列表
- asp.net - 带有来自 Label1.Text 的 ASP NET 倒数计时器
- arrays - fill an array with class instances
- java - Spring boot 2 + AWS Beanstalk setting heapsize
- javascript - Vue js vuelidate 自定义验证
- python - Jupyter notebook custom.js not applied when using "Restarting & Run All"
- python - PyQt5中需要绘制图片替换矩形
- arrays - MATLAB: Is it possible to generate multiple spheres and save them as objects in one script file?