1

I am working on encrypting (and later decrypting) strings in .Net and Java (on Android), using AES encryption with a password and an initialization vector. I got the respective en- and decryption on each side individually running well, but I keep getting different results in comparison, thus not allowing to encrypt on one and decrypt on the other system. I especially dont get why the first half of the encrypted byte-Array is identical, while the second half differs (while all the other byte-arrays are totally identical)?

Here is what I get as byte-arrays from the two encryption codes I use:

Java (for easy comparison added +256 on values which have been negative):[202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 70, 63, 184, 118, 228, 50, 242, 224, 231, 37, 34, 16, 123, 9, 143, 81]

.Net:[202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 109, 127, 84, 129, 168, 106, 21, 159, 131, 67, 75, 209, 166, 221, 190, 243]

I post the two code fragments I use for encryption below. Although I am looking for a hint on what I do wrong for several hours now, I can't figure out where I'm wrong. Would be very kind if someone could point me on what I don't see...

Here is what I get when I print out all relevant values from both code versions:

Android-Output:
    Key (String): 6543210987654321
    IV (String): 1234567890123456
    Input (String): Encrypt_this_text

    Key (Bytes): [54, 53, 52, 51, 50, 49, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49]
    IV (Bytes): [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54]
    Input (Bytes): [69, 110, 99, 114, 121, 112, 116, 95, 116, 104, 105, 115, 95, 116, 101, 120, 116]

    Encrypted: [-54, -109, -108, -88, 9, 104, -43, -80, -82, -99, 124, -96, 54, 33, -105, -10, 70, 63, -72, 118, -28, 50, -14, -32, -25, 37, 34, 16, 123, 9, -113, 81]
    Encrypted (+256 if <0): [202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 70, 63, 184, 118, 228, 50, 242, 224, 231, 37, 34, 16, 123, 9, 143, 81]

VBNet-Output:
    Key (String)=6543210987654321
    IV (String)=1234567890123456
    Input (String)=Encrypt_this_text

    Key (Byte)=[54, 53, 52, 51, 50, 49, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49]
    IV (Byte)=[49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54]
    Input (Byte)=[69, 110, 99, 114, 121, 112, 116, 95, 116, 104, 105, 115, 95, 116, 101, 120, 116]

    Encrypted=[202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 109, 127, 84, 129, 168, 106, 21, 159, 131, 67, 75, 209, 166, 221, 190, 243]

This is the java-code used for generating the encrypted byte-array:

String skey = "6543210987654321";
String siv = "1234567890123456";
String sinput = "Encrypt_this_text";

byte[] key = skey.getBytes("UTF8");
byte[] iv = siv.getBytes("UTF8");
byte[] input = sinput.getBytes("UTF8");

Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding");
SecretKeySpec keyspec = new SecretKeySpec(key, "AES" );
IvParameterSpec ivparams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivparams);

byte[] encrypted = cipher.doFinal(input);

...and here's my Net (in this case VB) Testcode:

Dim rm As New System.Security.Cryptography.AesManaged

Dim skey As String = "6543210987654321"
Dim siv As String = "1234567890123456"
Dim sinput As String = "Encrypt_this_text"

Dim key() As Byte = System.Text.Encoding.ASCII.GetBytes(skey)
Dim IV() As Byte = System.Text.Encoding.ASCII.GetBytes(siv)
Dim input() As Byte = System.Text.Encoding.ASCII.GetBytes(sinput)

Dim ict As System.Security.Cryptography.ICryptoTransform = rm.CreateEncryptor(key, IV)

Dim encrypted() As Byte = ict.TransformFinalBlock(input, 0, input.Length)
1
  • Notes: 1) Using ASCII encoding for the plaintext silently corrupts foreign characters. Use UTF-8 instead. 2) IV and key shouldn't use ASCII (or UTF-8). They're random binary values, so if you have to convert them to text, use Hex or Base64. 3) You must generate a new random IV for each message 4) To resist active attacks, you need to apply a MAC. Use an Encrypt-then-MAC scheme. make sure to include the whole ciphertext, including IV in the MAC. And use a constant time comparison for the MAC verification. Alternatively you can go for an authenticated mode like GCM instead of writing it yourself Commented Oct 5, 2013 at 12:01

1 Answer 1

2

This is due to the default padding in .NET's AesManaged.CreateEncryptor being PKCS7.

In Java, you initialize with Zeros padding.

You can override the padding by changing the Padding property in rm to PaddingMode.Zeros.

The relevant MSDN article : MSDN.

Sign up to request clarification or add additional context in comments.

3 Comments

I'd do it the other way round, changing both to PKCS7. You can't remove Zeros padding, unless you know that the message does not end with a zero byte.
Thank you, never would have got that on my own: I thought I had read somewhere that the Net-standard was Zero padding by default, that's why I had used Zero padding in java on purpose... So, of course it works with your hint (adding rm.Padding = Security.Cryptography.PaddingMode.Zeros in VBNet), as the other way around by using Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING"); in Java.
I second CodesInChaos' comment - PKCS7 is better for most purposes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.