问题
The following is an extract from using AES encryption in Java:
encryptedData = encryptCipher.doFinal(strToEncrypt.getBytes());
The following is an extract in c#
DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);
Both use a byte array one to encrypt the other to decrypt, the encryption in Java encrypts producing some negative values stored in a byte array.
C# uses a byte array to decrypt but a byte in C# is defined as only containing the numbers from 0..255 - Java defines its Byte type as -128 to 127.
Therefore, I cannot send encrypted data to the remote application which is written in C# because it cannot decrypt using the byte array that has been sent from the Java aplication.
Has anyone come up with a solution that would allow me to tell java not to produce negative numbers when encrypting?
The code is from Micrsoft, the MemoryStream requires the byte[] to create the stream for the crypto code... As mentioned or not, I replaced byte[] with sbyte but to no avail as MemoryStream requires byte[]
static string DecryptStringFromBytes_Aes(sbyte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream((byte)cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
回答1:
Java's bytes are signed, C# bytes are unsigned (there's also an sbyte
type in C#, that no one uses, which works like Java's bytes).
It doesn't matter. They are different in some regards, namely
- when converted to
int
, C#'s bytes will be zero-extended, Java's bytes will be sign-extended (which is why you almost always see& 0xFF
when bytes are used in Java). - when converted to string, Java's bytes will have their 128 - 255 range mapped to -128 - -1. Just ignore that.
The actual value of those bytes (that is, their bit-pattern) is what actually matters, a byte that is 0xAA will be 0xAA regardless of whether you interpret it as 170 (as in C#) or -86 (as in Java). It's the same thing, just a different way to print it as string.
new MemoryStream((byte)cipherText))
definitely doesn't do the right thing (or anything, it shouldn't even compile). The related new MemoryStream((byte[])cipherText))
wouldn't work either, you can't cast between primitive arrays like that. cipherText
should just be a byte[]
to begin with.
回答2:
You could turn it into a string with some encoding, like:
encryptedData = encryptCipher.doFinal(strToEncrypt.getBytes());
String s = new String(encryptedData, "Base-64");
Using the same standardized encoding, both C# and Java should be able to reconstruct each others encrypted data from that string.
来源:https://stackoverflow.com/questions/23079047/aes-negative-bytes