1

I have a server written in Java which sends converts its RSA key to the XML format used by .NET before sending it to the client:

public String getPublicKeyXML() {
    try {
        KeyFactory factory = KeyFactory.getInstance("RSA");
        RSAPublicKeySpec publicKey = factory.getKeySpec(this.keyPair.getPublic(), RSAPublicKeySpec.class);

        byte[] modulus = publicKey.getModulus().toByteArray();
        byte[] exponent = publicKey.getPublicExponent().toByteArray();

        String modulusStr = Base64.encodeBytes(modulus);
        String exponentStr = Base64.encodeBytes(exponent);

        String format = 
            "<RSAKeyValue>" +
                "<Modulus>%s</Modulus>" +
                "<Exponent>%s</Exponent>" +
            "</RSAKeyValue>";

        return String.format(format, modulusStr, exponentStr);
    } catch (Exception e) {
        this.server.logException(e);
        return "";
    }
}

The client, written in C#, then loads the key and uses it to encrypt a 256 bit AES key:

    public static byte[] encrypt(string xmlKey, byte[] bytes)
    {
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(xmlKey);
        byte[] cipherBytes = rsa.Encrypt(bytes, false);
        rsa.Clear();
        return cipherBytes;
    }

The server is then supposed to decrypt the AES key using its private RSA key:

public byte[] decrypt(byte[] data) {
    try {
        PrivateKey privateKey = this.keyPair.getPrivate();
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] cipherData = cipher.doFinal(data);
        return cipherData;
    } catch (Exception e) {
        this.server.logException(e);
        return new byte[0];
    }
}

However, the server fails with an error stating "Data must not be longer than 384 bytes." Looking at the data to be decrypted, I noticed that it's 385 bytes. I tried increasing the RSA key length, and now the server tells me the data must be no longer than 512 bytes, while the encrypted data from the client is 513 bytes. Why is the encrypted data always one byte longer than expected?

EDIT:

Here's a sample XML-formatted key as is transmitted from the server to the client:

<RSAKeyValue><Modulus>ANsMd2dCF6RsD5v5qjlHEjHm0VWD99gSYHP+pvyU8OgNL9xM5+o+yMAxWISOwMii9vJk1IzYGf18Fj2sMb5BsInlG2boZHb6KHh7v8ObPa4MuwB/U63i8AVU3N/JTugaPH0TKvo1WNUooXEHT23nOk+vh1QipzgKQYGl68qU35vKmpNAa79l1spXA66LckTWal4art9T08Rxgn9cMWujlF+wh9EQKQoxxgj4gCoXWRDTFYjRo/Mp5xDPwNjloTs/vFCPLvY7oI+lVrHhrPyz1R473ZuEhZm+rSeGBcY9I8vhg0AIixN7KYBLhrIecmqoNZHi6LohjD2F9zhdLaTU0IIU8eeKpbEZ5eB1kYngMONBq3A/IoG0Qa/7EcSAMMspBEObffK9kCNzvnbFg5wLuy8EHNaK3nmnuTppgCwCyNqZyHeAbZaUBjNguLhHtqkHFiPJ063Xesj9UbSsCmlBliGTDXWfeJANnjGP6D3R+uLXVy9SZe+cY92JW3eZA2k//w==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

I have verified that the data sent is the same as the data being received.

Knocking off the last byte results in a BadPaddingException. I also tried knocking off the first byte, with the same result.

Joseph
  • 85
  • 1
  • 10
  • umm. can you post an example xml? – Markus Mikkolainen Jul 30 '12 at 21:30
  • 2
    try knocking off the last byte of the ciphertext and see what happens - it could be a null terminator, or something along those lines. – mfsiega Jul 30 '12 at 21:32
  • How have you transferred the data itself? – Jon Skeet Jul 30 '12 at 21:34
  • And maybe example data. are you sure the client is producing stuff using the same exact cipher the server is using? ie. padding and all? also check the data length just before encryption to see that it is of correct length. – Markus Mikkolainen Jul 30 '12 at 21:34
  • Have you tried a other tool for comparison? So you know what to expect. – keiki Jul 30 '12 at 21:35
  • I would do as mfrankli says, if that fails do as MarkusMikkolainen says by producing the "same" encrypted text from both Java and C# if possible and compare them. – flindeberg Jul 30 '12 at 21:45
  • Encrypting the same data server and client side results in different ciphertext. How can I make both sides use the same exact cipher? – Joseph Jul 30 '12 at 21:54
  • Your modulus has 385 bytes and your exponent has 3 bytes (decoding the base-64 data). If I then chop off the last byte of the decoded base-64 of the modulus and re-base-64 encode it, it's 384 bytes and the encrypted data is 384 bytes. So I guess the question is: why is `getPublicKeyXML` generating a too-big modulus? – Jesse C. Slicer Jul 30 '12 at 22:17
  • @Jesse Good find. I'm beginning to think it has something to do with the way the BigInteger modulus is converted to a byte array, as I have verified that the base64 encoding part is correct. – Joseph Jul 30 '12 at 22:37

2 Answers2

3

I found the problem. The BigInteger's toByteArray() function included a leading zero for some reason. I just removed the leading zeros from the array and it now works like a charm!

Joseph
  • 85
  • 1
  • 10
  • Thanks! I was beating my head on the wall. I still can't make it work, but at least this isn't the problem. – Wheezil Feb 11 '19 at 12:48
1

This will not fix the problem (I tested it to no avail), but I wanted to call to your attention that RSACryptoServiceProvider implements the IDisposable interface and therefore should be properly disposed of when complete. Your C# encrypt method can be written a bit better (and more concise!) as such:

    public static byte[] encrypt(string xmlKey, byte[] bytes)
    {
        using (var rsa = new RSACryptoServiceProvider())
        {
            rsa.FromXmlString(xmlKey);
            return rsa.Encrypt(bytes, false);
        }
    }
Community
  • 1
  • 1
Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
  • Could **downvoter** please kindly explain the reason for the downvote? Perhaps my comment to the question might be incorporated? – Jesse C. Slicer Jul 30 '12 at 22:26
  • I downvoted because you posted an answer that wasn't an answer. I agree with the style comments, but they should be in a comment. – Nick Garvey Aug 01 '12 at 14:26
  • Thanks for the comment. I'd have loved to squeeze the example into a comment, but there's only so much that can fit. – Jesse C. Slicer Aug 01 '12 at 14:34