在java中从C#验证rsa签名
我试图在服务器应用程序(用C#编写)上生成RSA SHA512签名,并在客户端应用程序(用Java编写)上验证该签名。在签名交换之前,服务器生成公钥和私钥对,并通过为客户端应用程序提供生成的模数和指数值,与客户端应用程序共享公钥。当签名需要验证时,客户端应用程序将存储值以供以后使用 服务器正在生成128字节模数和128字节签名。我只是在测试时使用[0x00,0x01,0x02,0x03]的字节数组作为签名的源数据 出于某种原因,我的Java应用程序在验证签名时总是失败 我的C代码(创建签名): C#端的crypto对象来自System.Security.Cryptography命名空间,java端来自java.Security在java中从C#验证rsa签名,java,c#,encryption,cryptography,rsa,Java,C#,Encryption,Cryptography,Rsa,我试图在服务器应用程序(用C#编写)上生成RSA SHA512签名,并在客户端应用程序(用Java编写)上验证该签名。在签名交换之前,服务器生成公钥和私钥对,并通过为客户端应用程序提供生成的模数和指数值,与客户端应用程序共享公钥。当签名需要验证时,客户端应用程序将存储值以供以后使用 服务器正在生成128字节模数和128字节签名。我只是在测试时使用[0x00,0x01,0x02,0x03]的字节数组作为签名的源数据 出于某种原因,我的Java应用程序在验证签名时总是失败 我的C代码(创建签名):
字节通过web服务和base64字符串在应用程序之间传递。我已经检查并打印了字节数组本身的值,以确保两个应用程序之间的指数、模和签名的值是正确的。两种语言/应用程序之间的签名不兼容有什么原因吗?有没有我遗漏的参数?我用SHA512实现了这两个签名,但可能还需要考虑签名的其他方面?在C#端的XML表示中,数据存储为未签名的big-endian(和Base64编码) 但是,Java构造函数希望数据是有符号的(两个的补码)大端 因此必须使用-constructor,它期望第一个参数中的符号和第二个参数中的数据为无符号的big-endian,即需要进行以下更改:
RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(1, modulus), new BigInteger(1, exponent));
您在C#中签名的数据是1、2、3、4。您声称在Java中需要的数据是0、1、2、3。@PresidentJamesMoveonPolk woops,我更新了示例代码来解决这个问题;谢谢你的帮助。尽管如此,这些数组的签名仍然失败。
getStoredExponent
和getStoredModulus
未在Java代码中定义。假设两种方法仅对密钥的相应数据执行Base64解码,则模数和指数将被解释为无符号值,并分别转换为BigInteger
为new BigInteger(1,模数)
或new BigInteger(1,指数)
。有了这个,验证就可以在我的机器上运行(使用我自己的测试密钥)。@Topaco你是有史以来最了不起的人!BigInteger上的1参数正是所需的参数。我想因为这些值来自C#(它使用无符号),所以我需要那个值。
byte[] expectedData = new byte[4];
expectedData[0] = 0;
expectedData[1] = 1;
expectedData[2] = 2;
expectedData[3] = 3;
byte[] exponent = getStoredExponent(); // three-byte value from server
byte[] modulus = getStoredModulus(); // 128-byte value from server
RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
Signature verifier = Signature.getInstance("SHA512withRSA");
verifier.initVerify(publicKey);
verifier.update(expectedData);
if(verifier.verify(signature)) {
System.out.println("signature verified");
} else {
System.out.println("signature failed verification"); // always ends up here :(
}
RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(1, modulus), new BigInteger(1, exponent));