2

I'm using AES encryption/decryption algorithm in my application.

On the server side I use c# to encrypt/decrypt the data.

And on client side(android) I use java to decrypt the data.

C# encryption/decryption code

    static readonly string PasswordHash = "52";

    static readonly string SaltKey = "dfkjsadfinewdfadsfkmeoinmsdflksdflk";

    static readonly string VIKey = "@EUBRHDFBFG8867";

public static string Encrypt(string plainText)
    {
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

        byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash,Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);

        var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding =PaddingMode.Zeros };

        var encryptor = symmetricKey.CreateEncryptor(keyBytes,Encoding.ASCII.GetBytes(VIKey));
        byte[] cipherTextBytes;

        using (var memoryStream = new MemoryStream())
        {
            using (var cryptoStream = new CryptoStream(memoryStream, encryptor,CryptoStreamMode.Write))
            {
                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                cryptoStream.FlushFinalBlock();
                cipherTextBytes = memoryStream.ToArray();
                cryptoStream.Close();
            }
            memoryStream.Close();
        }           
       return Convert.ToBase64String(cipherTextBytes);
    }

    public static string Decrypt(string encryptedText)
    {
        byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);

        byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash,Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);

        var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding =PaddingMode.None }

        var decryptor = symmetricKey.CreateDecryptor(keyBytes,Encoding.ASCII.GetBytes(VIKey));

        var memoryStream = new MemoryStream(cipherTextBytes);

        var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);

        byte[] plainTextBytes = new byte[cipherTextBytes.Length];

        int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

        memoryStream.Close();
        cryptoStream.Close();

        return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray());
    }

Java Decryption method

public String decrypt(String dataToDecrypt) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException 
{

    byte[] encryptedCombinedBytes = Base64.decodeBase64(dataToDecrypt.getBytes());

    String saltKey = "dfkjsadfinewdfadsfkmeoinmsdflksdflk";
    String password = "52";
    String IVKey = "@EUBRHDFBFG8867";

    PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA256", "ASCII", saltKey.getBytes(), 8);

    byte[] mEncryptedPassword = new PBKDF2Engine(p).deriveKey(password);


    byte[] ivbytes = Arrays.copyOfRange(IVKey.getBytes(), 0, 16);

    SecretKeySpec mSecretKeySpec = new SecretKeySpec(mEncryptedPassword, "AES");

    Cipher mCipher = Cipher.getInstance("AES/CBC/NoPadding");

    mCipher.init(Cipher.DECRYPT_MODE, mSecretKeySpec, new IvParameterSpec(ivbytes));

    byte[] encryptedTextBytes = Arrays.copyOfRange(encryptedCombinedBytes, 16, encryptedCombinedBytes.length);

    byte[] decryptedTextBytes = mCipher.doFinal(encryptedTextBytes);

    return new String(decryptedTextBytes, "UTF-8");
}

C# decryption method works fine and give the result string.

I cannot figure out the problem in Java decryption code. It runs and give me some garbage value.

EDIT

  1. I can not edit anything on the server side.I just have to replicate the decryption in java decryption.
  2. I dont know how to use passwordHash, saltKey and IVkey
VinothKathir
  • 200
  • 2
  • 9
  • Have you made sure you get all key values correct etc? – Sami Kuhmonen Aug 14 '15 at 10:43
  • 1
    possible duplicate of [AES Encrypt in C# (Help) and Decrypt in Java (Done)](http://stackoverflow.com/questions/3632392/aes-encrypt-in-c-sharp-help-and-decrypt-in-java-done) – Maciej Lach Aug 14 '15 at 10:49
  • Using CBC over network connections is completely insecure. Desist and use TLS, possibly using self signed client & server certificates + GCM cipher suite. – Maarten Bodewes Aug 14 '15 at 11:14
  • yes @SamiKuhmonen. as you can see i've used the same key on C# as well as Java method. – VinothKathir Aug 14 '15 at 11:15
  • @VinothKathir But you derive keys etc, there are exactly the same? – Sami Kuhmonen Aug 14 '15 at 11:19
  • The number of rounds differ. On c# side the default value is used (AFAIK this is 1000). On Java side you use 8 rounds... – Robert Aug 14 '15 at 11:47
  • @Robert i replaced that with 1000 and i'm getting the same result – VinothKathir Aug 14 '15 at 11:57
  • @VinothKathir: Why do you use "ASCII" as password on Java side? BTW: You don't mention which PBKDF2Engine you use on Java. As it is not part of Java/Android it is a 3rd party lib. May be the implementation is simply defect. – Robert Aug 14 '15 at 12:14
  • @Robert i found this PBKDF2Engine is the java equivalent for Rfc2898DeriveBytes. it is available here: https://github.com/m9aertner/PBKDF2 – VinothKathir Aug 14 '15 at 12:31

1 Answers1

1

First of all, you've switched the password and the salt around.

Second, PBKDF2 uses HMAC/SHA-1 as default. As far as I know that's also the default for Rfc2898DeriveBytes:

Implements password-based key derivation functionality, PBKDF2, by using a pseudo-random number generator based on HMACSHA1.

You should also never call getBytes without specifying the character set in Java, but this is probably not an issue for your current runtime.


These are comments on the code only; do not use CBC over network connections without integrity/authenticity protection.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263