0

Can anyone help in the below code, i am trying to implement AES Encryption in Android but the code generated by android is not matching with the server side .Net AES Encryption. Please find the code below let me know what's wrong :

.Net Code

    private string GetEncryptedData(string clearText)

    {
       string EncryptionKey = "password";
        byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
        using (Aes encryptor = Aes.Create())
        {
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            encryptor.Key = pdb.GetBytes(32);
            encryptor.IV = pdb.GetBytes(16);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.Close();
                }
                clearText = System.Web.HttpContext.Current.Server.UrlEncode(Convert.ToBase64String(ms.ToArray()));
            }
        }
        return clearText;
    }

Java Code in Android :

    private static String secretKey1 = "password";
    private static String salt = "ssshhhhhhhhhhh!!!!";

    public static String encrypt(String strToEncrypt, String secret)

    {
        try
        {
            byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            KeySpec spec = new PBEKeySpec(secret.toCharArray(), salt.getBytes(), 65536, 256);
            SecretKey tmp = factory.generateSecret(spec);
            SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
            //Log.d("qwqwqwqw1",secretKey.toString());

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
            //return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));

            return URLEncoder.encode(Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))), "UTF-8");
        }
        catch (Exception e)
        {
            System.out.println("Error while encrypting: " + e.toString());
        }
        return null;
    }

.Net encryption result:

%2bJnjgtiCX9VSxwTU22jCJluBxh%2bkFxVlfBasAorRO%2fo%3d

Java encryption result

PwoZePSM%2BjoyPubZr780Fg%3D%3D

I try to change this

byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
to byte[] iv = { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }

In JAVA code still getting error "expected IV length of 16 but was 13"

Can anyone tell whats wrong in this.

Update: Now i am using this. Please let me know whats wrong:

code:

byte[] salt1 =  new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76};

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec pbeKeySpec = new PBEKeySpec(strToEncrypt.toCharArray(), salt1, 1000, 384);
byte[] derivedData = factory.generateSecret(pbeKeySpec).getEncoded();
byte[] key = new byte[32];
byte[] iv = new byte[16];
System.arraycopy(derivedData, 0, key, 0, key.length);
System.arraycopy(derivedData, key.length, iv, 0, iv.length);

SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
//return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
//byte[] result = cipher.doFinal(Base64.getEncoder().decode(strToEncrypt));

String value = Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_16LE)));
String result1 = URLEncoder.encode(value,"UTF_16LE");
10
  • If yoy want to get same results in both languages you have to use same algorithm, key, iv, block mode and padding mode. Your code is using clearly different values. The "expected IV length" is self-explanatory, the IV in that case is 13 bytes long. See this article for working interoperable encryption. mjremijan.blogspot.com/2014/08/… Commented Feb 28, 2020 at 9:52
  • 1
    This question stackoverflow.com/questions/60387628/… is presumably related, since even the salts in the C# codes are identical. Although the linked question is about decryption and this question is about encryption, the most important aspects apply in both cases and can therefore be adopted from the associated answer. Commented Feb 28, 2020 at 11:42
  • Hi @Topaco thanks for quick response , i tried the one you shared , still not same let me update my code Commented Feb 28, 2020 at 13:31
  • Probably a copy/paste issue: In the PBEKeySpec instantiation the first argument must be secret.toCharArray() and not strToEncrypt.toCharArray()! Commented Feb 28, 2020 at 14:00
  • One more thing: Regarding URLEncoder.encode(value, "UTF_16LE") you should check by comparison with the result of the C# code if Utf-8 shouldn't be used. Commented Feb 28, 2020 at 14:42

0

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.