validating rsa signature from C# in java

梦想的初衷 提交于 2021-02-16 20:08:19

问题


I'm attempting to generate an RSA SHA512 signature on my server application (written in C#) and verify that signature on a client application (written in Java). Prior to the signature exchange, the server generates a public- and private-key pair and shares the public key with the client app by giving it the modulus and exponent values that were generated. The client app stores the values for later, when the signature needs to be verified.

The server is generating a 128-byte modulus and a 128-byte signature. I'm just using a byte array of [0x00, 0x01, 0x02, 0x03] as my source data for the signature while I'm testing.

For some reason, my Java application always fails when validating the signature.

My C# code (creates the signature):

RSACryptoServiceProvider crypto = new RSACryptoServiceProvider();
crypto.FromXmlString(this.myStoredPrivateKeyXml);

List<byte> signatureBytes = new List<byte>();
signatureBytes.Add(0x00);
signatureBytes.Add(0x01);
signatureBytes.Add(0x02);
signatureBytes.Add(0x03);

byte[] signature = crypto.SignData(signatureBytes.ToArray(), "SHA512");

My Java code (that receives/validates the signature):

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 :(
}

The crypto objects on the C# side are from the System.Security.Cryptography namespace and java.security on the Java side.

The bytes are passed between the apps via web services and base64 strings. I've gone through and printed the values of the byte arrays themselves to make sure the values are correct for the exponent, modulus, and signature between the two applications. Is there any reason why the signature wouldn't be compatible between the two languages/apps? Is there a parameter that I'm missing, maybe? I made them both RSA with SHA512, but perhaps other aspects of the signature need to be accounted for as well?


回答1:


In the XML representation on the C# side, the data are stored as unsigned big endian (and Base64 encoded).

However, the Java BigInteger(byte[] val)-constructor expects the data as signed (two's complement) big endian.

Therefore the BigInteger(int signum, byte[] magnitude)-constructor must be used, which expects the sign in the first parameter and the data in the second parameter as unsigned big endian, i.e. the following change is necessary:

RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(1, modulus), new BigInteger(1, exponent));


来源:https://stackoverflow.com/questions/61392586/validating-rsa-signature-from-c-sharp-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!