Home > Programming > AES 128bit Cross Platform (Java and C#) Encryption Compatibility

AES 128bit Cross Platform (Java and C#) Encryption Compatibility

It seems quite a minor issue but doing cross platform encryption and decryption specifically AES was a bit a challenge for me. When you  get it working it just seems like no big change to the original code you where working on but you wasted fruitless hours debugging. Just sharing so that another person doesn’t have to waste time wondering why same settings produce a different cipher and going through a number of unhelpful posts where it ” works on my machine”.

I initially used ISO 10126 padding, but that seemed to produce a different cipher in C# and Java. I decided to go with no padding which leads me to the  cryptographic exception: Length of the data to decrypt is invalid. After some head banging I settled with PKCS7

Same encoding of strings has to be used in java and c#, other wise you will end up having different ciphers in java and c#.

The java code below uses a base64 util class from android SDK but you can replace it like with one from apache commons

C# encryption utility

public RijndaelManaged GetRijndaelManaged(String secretKey)
        {
            var keyBytes = new byte[16];
            var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
            Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
            return new RijndaelManaged
            {
                Mode = CipherMode.CBC,
                Padding = PaddingMode.PKCS7,
                KeySize = 128,
                BlockSize = 128,
                Key = keyBytes,
                IV = keyBytes
            };
        }

        public byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
        {
            return rijndaelManaged.CreateEncryptor()
                .TransformFinalBlock(plainBytes, 0, plainBytes.Length);
        }

        public byte[] Decrypt(byte[] encryptedData, RijndaelManaged rijndaelManaged)
        {
            return rijndaelManaged.CreateDecryptor()
                .TransformFinalBlock(encryptedData, 0, encryptedData.Length);
        }

        /// <summary>
        /// Encrypts plaintext using AES 128bit key and a Chain Block Cipher and returns a base64 encoded string
        /// </summary>
        /// <param name="plainText">Plain text to encrypt</param>
        /// <param name="key">Secret key</param>
        /// <returns>Base64 encoded string</returns>
        public String Encrypt(String plainText, String key)
        {
            var plainBytes = Encoding.UTF8.GetBytes(plainText);
            return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(key)));
        }

        /// <summary>
        /// Decrypts a base64 encoded string using the given key (AES 128bit key and a Chain Block Cipher)
        /// </summary>
        /// <param name="encryptedText">Base64 Encoded String</param>
        /// <param name="key">Secret Key</param>
        /// <returns>Decrypted String</returns>
        public String Decrypt(String encryptedText, String key)
        {
            var encryptedBytes = Convert.FromBase64String(encryptedText);
            return Encoding.UTF8.GetString(Decrypt(encryptedBytes, GetRijndaelManaged(key)));
        }

Java Encryption Utility

private final String characterEncoding = "UTF-8";
	private final String cipherTransformation = "AES/CBC/PKCS5Padding";
	private final String aesEncryptionAlgorithm = "AES";

	public  byte[] decrypt(byte[] cipherText, byte[] key, byte [] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
	{
		Cipher cipher = Cipher.getInstance(cipherTransformation);
		SecretKeySpec secretKeySpecy = new SecretKeySpec(key, aesEncryptionAlgorithm);
		IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
		cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy, ivParameterSpec);
		cipherText = cipher.doFinal(cipherText);
		return cipherText;
	}

	public byte[] encrypt(byte[] plainText, byte[] key, byte [] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
	{
		Cipher cipher = Cipher.getInstance(cipherTransformation);
		SecretKeySpec secretKeySpec = new SecretKeySpec(key, aesEncryptionAlgorithm);
		IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
		cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
		plainText = cipher.doFinal(plainText);
		return plainText;
	}

	private byte[] getKeyBytes(String key) throws UnsupportedEncodingException{
		byte[] keyBytes= new byte[16];
		byte[] parameterKeyBytes= key.getBytes(characterEncoding);
		System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
		return keyBytes;
	}

	/// <summary>
	/// Encrypts plaintext using AES 128bit key and a Chain Block Cipher and returns a base64 encoded string
	/// </summary>
	/// <param name="plainText">Plain text to encrypt</param>
	/// <param name="key">Secret key</param>
	/// <returns>Base64 encoded string</returns>
	public String encrypt(String plainText, String key) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException{
		byte[] plainTextbytes = plainText.getBytes(characterEncoding);
		byte[] keyBytes = getKeyBytes(key);
		return Base64.encodeToString(encrypt(plainTextbytes,keyBytes, keyBytes), Base64.DEFAULT);
	}

	/// <summary>
	/// Decrypts a base64 encoded string using the given key (AES 128bit key and a Chain Block Cipher)
	/// </summary>
	/// <param name="encryptedText">Base64 Encoded String</param>
	/// <param name="key">Secret Key</param>
	/// <returns>Decrypted String</returns>
	public String decrypt(String encryptedText, String key) throws KeyException, GeneralSecurityException, GeneralSecurityException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException{
		byte[] cipheredBytes = Base64.decode(encryptedText, Base64.DEFAULT);
		byte[] keyBytes = getKeyBytes(key);
		return new String(decrypt(cipheredBytes, keyBytes, keyBytes), characterEncoding);
	}

Hopefully this saves someone time.

Categories: Programming Tags: , ,
  1. Rajesh
    January 19, 2012 at 12:43 pm

    Thanks a lot man. You saved my time. 🙂 It works like a charm.

  2. lward
    January 24, 2012 at 11:57 pm

    This was very useful. Thanks for posting your solution.

  3. Adriano
    January 30, 2012 at 1:16 am

    Amazing, I spent a few hours trying to put this encryption to work between java and c#,
    it’s working now, thanks to you.

    Thank you, realy. =)

  4. Carlos
    February 7, 2012 at 7:35 pm

    This is wonderful!!, thanks

  5. February 29, 2012 at 2:53 pm

    Thanks for the post. It was very usefull.

  6. Bas
    March 6, 2012 at 8:21 pm

    Thank you so much… I have been struggling with this for ages!

  7. Parmeet
    March 9, 2012 at 8:03 am

    Hi,

    I’ve downloaded the apache commons 1.6 jar but there seems to be a problem with “Base64.DEFAULT” which is coming as undefined. Could you point me to the correct version of commons library or perhaps let me know the value of “Base64.DEFAULT” if its a constant.

    Thanks,

    Parmeet

  8. June 19, 2012 at 4:11 pm

    Thank you so much!!! I had about a week struggling with this, THANK YOU.

  9. lakers
    October 9, 2012 at 9:00 am

    can I get the same logic in javascript?

  10. Sam
    October 13, 2012 at 11:48 pm

    This work better than medicine…I was able to complete my small program in minutes; 128 and 256.
    Thanks
    TuKanSam

  11. Chuck
    November 28, 2012 at 6:46 pm

    This worked great. Many thanks!

  12. lakers
    December 20, 2012 at 5:31 am

    is it possible to implement the same logic in Objective C? please reply as soon as possible..

  13. December 20, 2012 at 6:19 am

    Am not acquainted with Objective C.

  14. January 6, 2013 at 4:04 pm

    I’ve used Java code in android and .Net wcf service perfectly. Thank you very much!

  15. Ajeet
    February 19, 2013 at 4:34 pm

    Please any one help me that what will be in JAVA in line where Base64 is used in the above given code. Thanks for any help in this regards.

    • Govs
      March 6, 2013 at 3:50 pm

      I have similar problem. I tried using
      byte[] cipheredBytes = Base64.base64Decode(EncryptedText).getBytes()
      But it gives me an exception javax.crypto.BadPaddingException: Given final block not properly padded.

      did you find any solution for this?

  16. Max
    February 27, 2013 at 7:05 pm

    It is not a good idea to use the encryption key as initialization vector (IV) for the cipher block chaining. Encryption key and IV should be seperate values. Take a (human readable) pass phrase string and feed it into a cryptographic hash function like SHA256/384/512 to get a sufficient number of key bytes for both, encryption key AND initialization vector. Use the first 16 bytes of the hash value as encryption key and the next 16 bytes as IV.

  17. Govs
    March 6, 2013 at 3:47 pm

    Hi,

    This is an awesome document. Really very helpful.

    I am trying to implement the same code for encryption in c# and decryption in java.
    I am not able to find the same method to get the byte array for cipheredBytes like yours at line 51 i.e. byte[] cipheredBytes = Base64.decode(encryptedText, Base64.DEFAULT).

    However I am using this method:
    byte[] cipheredBytes = Base64.base64Decode(encryptedText).getBytes();

    But I am getting an error
    javax.crypto.BadPaddingException: Given final block not properly padded

    How to implement the method like yours? What packege will I need to import for that?
    Please help

  18. March 14, 2013 at 11:31 am

    I am facing the below errors pls give me a solutions

    Exception in thread “main” java.lang.RuntimeException: Stub!
    at android.util.Base64.encodeToString(Base64.java:8)
    at com.security.packs.Encry.encrypt(Encry.java:87)
    at com.security.packs.Encry.main(Encry.java:112)

  19. Evgeniy
    March 15, 2013 at 7:35 pm

    Big thanks !!!
    Wonderful)

  20. Thomas
    May 30, 2013 at 7:26 am

    As for the Base64.Default when not using the Android package, use the package org.apache.ws.security.util.Base64 and the method Base64.encode(encrypt(plainTextbytes,keyBytes, keyBytes)); (and obviously the counterpart decode…)

  21. Naturjoghurt
    June 22, 2013 at 11:08 am

    Thank you very much!
    Nice solution solving all my Problems.

  22. Marcusdev
    July 16, 2013 at 3:21 pm

    This also works with openssl.net which by default uses PKCS5Padding.

  23. September 5, 2013 at 2:56 am

    Thank you very much for this.

  24. Balian
    September 8, 2013 at 3:39 am

    Thanks a lot! It’s a perfect solution.

  25. NRHONLINE
    September 13, 2013 at 6:06 pm

    Has anyone implemented this into a java applicatio
    n yet?

  26. David Tran
    September 16, 2013 at 5:59 pm

    Hi I have a problem to convert to C# from java. Please help me out.

    javax.crypto.Cipher c = javax.crypto.Cipher.getInstance(“RSA/ECB/NOPADDING”);
    javax.security.cert.X509Certificate pcert = javax.security.cert.X509Certificate.getInstance(cer.RawData);
    c.init(javax.crypto.Cipher.ENCRYPT_MODE, pcert.getPublicKey());
    byte[] pdecrypt = pdecrypt = c.doFinal(p);

    I need the same thing but in C#

  27. Sridhar
    September 18, 2013 at 9:57 am

    if we change RijndaelManaged to AesManged then the keys generated are not same in java and .net any solution?

  28. Sridhar
    September 18, 2013 at 10:26 am

    and how to pass salt value in .net

  29. Dasu
    September 19, 2013 at 2:06 pm

    Here is the Java encryption code and which is getting decrypted and woking fine:

    private static byte[] doThis(String message) {
    byte[] messageCrypte = null;
    try {
    // Certificate Input Stream
    // LA SSL Certificate to be passed.
    InputStream inStream = new FileInputStream(certificate);

    // X509Certificate created
    CertificateFactory cf = CertificateFactory.getInstance(“X.509”);
    X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
    inStream.close();

    // Getting Public key using Certficate
    PublicKey rsaPublicKey = (PublicKey) cert.getPublicKey();

    Cipher encryptCipher = Cipher.getInstance(“RSA/ECB/PKCS1Padding”, “SunJCE”);
    encryptCipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);

    byte[] messageACrypter = message.getBytes();
    // Encrypted String
    messageCrypte = encryptCipher.doFinal(messageACrypter);
    } catch (Exception e) {
    // TODO: Exception Handling
    e.printStackTrace();
    }
    return messageCrypte;
    }

    I tried to convert above code to c#.net but it was giving an exception saying that
    javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes in java dcryption. Please suggest me anything wrong in my .net code mentioned below:

    static byte[] doThis(string message)
    {

    X509Certificate2 cert = new X509Certificate2(@”C:\Data\ABC-rsa-public-key-certificate.cer”);
    byte[] aa = cert.GetPublicKey();

    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
    RSAParameters RSAKeyInfo = new RSAParameters();
    // byte[] Exponent = { 1, 0, 1 };

    RSAKeyInfo = RSA.ExportParameters(false);
    //Set RSAKeyInfo to the public key values.
    RSAKeyInfo.Modulus = aa;
    //RSAKeyInfo.Exponent = Exponent;
    RSA.ImportParameters(RSAKeyInfo);
    byte[] bb = RSA.Encrypt(GetBytes(message), false);
    return bb;

    //Cipher encryptCipher = Cipher.getInstance(“RSA/ECB/PKCS1Padding”, “SunJCE”);
    //encryptCipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);

    //byte[] messageACrypter = message.
    //messageCrypte = encryptCipher.doFinal(messageACrypter);

    }

  30. September 26, 2013 at 12:55 pm

    You rock!

  31. September 29, 2013 at 11:43 pm

    I’m serious you rock, you saved me crap loads of time

  32. Vijay Muvva
    October 16, 2013 at 7:44 am

    You are a life saver.. Thanks a ton.. Working perfectly..

  33. October 18, 2013 at 5:56 am

    Can I get the same algorithm in C?

  34. Bas
    October 21, 2013 at 9:14 pm

    Thanks man, saved me alot of time! 🙂

  35. eWoks
    December 14, 2013 at 6:56 pm

    Thanks MAN !!!

  36. Nandkishor
    December 26, 2013 at 5:56 am

    Thanks man, your code works perfectly and saved my a lot of time..
    You are great..:)

  37. Sal
    January 19, 2014 at 10:49 pm

    Perfect, Thank you a lot man.

  38. Oyinda
    March 26, 2014 at 6:52 pm

    Thanks so much. After weeks of frustration and misery. Waooooo You are a blessing. I have more than 25 webpages opened that I am reading to get this sorted out. This worked like magic

  39. April 8, 2014 at 5:55 pm

    Thank you so much 🙂

  40. April 28, 2014 at 6:11 pm

    Thank you so much, this save my time. I find any codes on google, but nothing work. u’re the best.

  41. Denis
    May 6, 2014 at 9:41 am

    i want to use the oracle pl/sql package dbms_crypto to have the same result.
    Can somebody help me ?

  42. Denis
    May 8, 2014 at 1:07 pm

    when i try to compile the testdh class with java encryption utility, i have this error :
    14:48:10 Start Compiling 1 object(s) …
    14:48:10 Executing ALTER JAVA SOURCE “testdh” COMPILE …
    14:48:11 [0:0] testdh:49: cannot access org.apache.commons.codec.binary.Base64
    14:48:11 [0:0] bad class file: null
    14:48:11 [0:0] class file has wrong version 50.0, should be 49.0
    14:48:11 [0:0] Please remove or make sure it appears in the correct subdirectory of the classpath.
    14:48:11 [0:0] return Base64.encodeToString(encrypt(plainTextbytes,keyBytes, keyBytes), Base64.DEFAULT);
    14:48:11 [0:0] ^
    14:48:11 [0:0] 1 error
    14:48:11 Compilation complete – 7 error(s) found
    14:48:11 End Compiling 1 object(s)

    Any idea ?

  43. Denis
    May 12, 2014 at 12:23 pm

    i try to encrypt via an Oarcle package and i have this error :
    [1]: ORA-29532: Java call terminated by uncaught Java exception: java.lang.ExceptionInInitializerError

    the error comes form this line in the java code :
    Cipher cipher = Cipher.getInstance(cipherTransformation);

    Can somebody help me ?

  44. July 23, 2014 at 8:52 am

    awesome dude. works perfectly

  45. Sabastian
    August 24, 2014 at 12:00 am

    Excellent! Thank you I spent so many time trying to do this.

  46. sani
    February 13, 2015 at 4:06 pm

    hi, i have aes encryption happning in android app and decription happening on java desktop application, which is not working, could you pls me the solution….

  47. April 18, 2015 at 3:36 am

    i cannt decrypt large file?? please help me! thks so much

  48. Shiddiq
    May 25, 2015 at 4:11 am

    Excellentttttt….. Thank You very much

  49. Ray
    August 24, 2015 at 3:03 am

    Thanks for your work !!
    Please refer to the following if you want to make it work in JAVA SE.

    import java.util.Base64;

    * Encrypt
    return Base64.getEncoder().encodeToString(encrypt(plainTextbytes,keyBytes, keyBytes));

    * Decrypt
    return new String(decrypt(cipheredBytes, keyBytes, keyBytes), characterEncoding);

  50. Amigo Ge
    September 7, 2015 at 7:48 am

    Thanks man!!

    It’s not just save my time.

  51. September 23, 2015 at 1:18 pm

    Thank you!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! I spent 2 days trying this, until your tutorial and ran at first time.

  52. kurt225
    October 14, 2015 at 3:31 pm

    Thank you very much, you saved my life !

  53. daniyal
    November 22, 2015 at 7:46 pm

    Thanks mate

  54. Kirtash
    December 9, 2015 at 2:49 am

    Muchísimas gracias!!
    Me ha sido de mucha ayuda para encriptar y desencriptar a través de un servicio web (C# -> Java, Java -> C#).
    Tras buscar en muchísimas páginas y ejemplos este es el único que realmente me ha funcionado…
    Saludos :D!!

  55. December 24, 2015 at 12:47 pm

    I am trying to encrypt in java and decrypt in c# using query string.Any send coding for me or send a reference solution for me..

    Thank u in advance..i am waiting:)

  56. December 28, 2015 at 6:37 am

    I am trying to encrypt in java and decrypt in asp.net.Any send coding for that

    Advance in thanks

  57. Anal Trivedi
    February 17, 2016 at 5:56 am

    Thanks you so much Sir…… 🙂

  58. Anal Trivedi
    February 17, 2016 at 7:56 am

    Its working perfectly on Android & C#. Do you have similar code for Objective C?

  59. Joseph Ssenyange
    February 17, 2016 at 8:16 am

    No similar code for objective C

  60. Amal and Likhil
    April 30, 2016 at 11:14 am

    Very nice helped alot… thanksss

  61. Varsha
    May 11, 2016 at 9:37 am

    I get an error in c#..length of the data to decrypt is invalid…why is that so? is that related to blocksize because the encrypted data is 195bytes and block size in only 128???? is that so?

  62. Chirag
    May 19, 2016 at 2:26 am

    I am doing encryption in C# and while doing decryption in Java I am getting special characters in output. can someone share the java working decryption code (non andriod)

  63. Chirag
    May 19, 2016 at 2:46 am

    I am getting special characters in Java when trying to decrypt the encrypted C# value and also padding PKCS5Padding is not working.
    Can Someone share the working Java code non-andriod

  64. August 17, 2016 at 8:09 am

    I dont see how that can be valid (c#). In case of java we hash secret and use derived hashed byte sequence for iv and key, whilst in c# we simply use plain secret text. That 2 never gonna match.

  65. November 24, 2016 at 2:34 pm

    padding is invalid and cannot be removed
    while decryption in C#
    help me

  66. sumit magdum
    January 2, 2017 at 9:02 am

    is any compatible code or library is available for iOS in objective C or Swift

  67. Olufemi
    January 24, 2017 at 7:14 am

    Thanks Joe. This saves after a whole day of toiling.

  68. Nicolò
    March 28, 2017 at 1:17 pm

    Honestly, man, you’re a hero. Saved my day.

  1. December 3, 2014 at 5:33 pm
  2. December 23, 2014 at 11:42 pm
  3. January 6, 2015 at 9:21 am
  4. February 12, 2016 at 8:41 pm

Leave a reply to Andrea Lizbeth Cancel reply