0

I am trying to use AES256 on a file on a android device, and decoded in c#. This is the first time I try this, so I am really confused. I read a lot of information but the important thing I get is that the key used on the encryption will establish which encryption is used. I get this classes from here:

Encryption compatible between Android and C#

I made a really few modifications and it works really great but I have questions about it.

  1. Is this AES256 or AES128?

  2. Does it show the correct way to use AES?

  3. What is the purpose of the method encodeDigest(String)?

Furthermore, I made a change on the encodeDigest(String) method on both classes so they return a byte[] of size 32. Why? because I debug the android piece in this line kgen.init(256): This line and the few next ones return a byte[] of size 32 for the key. I know that is a not really good idea but i make it work. I just want to get this right but now I am really lost.

This is How i create my object in Android:

 AESEncryption aesEnc = new AESEncryption("asdfgasdfgasdfgasdfgasdfgasdfgas");

For Android I use this Class:

public class AESEncryption {
  public static final String TAG = "AES";

    private static Cipher aesCipher;
    private static SecretKey secretKey;
    private static IvParameterSpec ivParameterSpec;

    private static String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static String CIPHER_ALGORITHM = "AES";
    // Replace me with a 16-byte key, share between Java and C#
    private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    private static String MESSAGEDIGEST_ALGORITHM = "MD5";

    public AESEncryption(String passphrase) {

        byte[] passwordKey = encodeDigest(passphrase);
       // KeyGenerator kgen = null;
        try {
            aesCipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
       //kgen = KeyGenerator.getInstance("AES");
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "No such algorithm " + CIPHER_ALGORITHM, e);
        } catch (NoSuchPaddingException e) {
            Log.e(TAG, "No such padding PKCS5", e);
        }


    //kgen.init(256); // 192 and 256 bits may not be available
   // Generate the secret key specs.
   //SecretKey skey = kgen.generateKey(); //Cantget 'test' in here...
   //byte[] raw = skey.getEncoded();
   //secretKey = new SecretKeySpec(raw, "AES");
        secretKey = new SecretKeySpec(passwordKey, CIPHER_ALGORITHM);
        ivParameterSpec = new IvParameterSpec(rawSecretKey);
    }

    public String encryptAsBase64(byte[] data) {
        byte[] encryptedData = encrypt(data);
        return  Base64.encodeToString(encryptedData, Base64.DEFAULT);
    }

    public byte[] encrypt(byte[] clearData) {
        try {
            aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        } catch (InvalidKeyException e) {
            Log.e(TAG, "Invalid key", e);
            return null;
        } catch (InvalidAlgorithmParameterException e) {
            Log.e(TAG, "Invalid algorithm " + CIPHER_ALGORITHM, e);
            return null;
        }

        byte[] encryptedData;
        try {
            encryptedData = aesCipher.doFinal(clearData);
        } catch (IllegalBlockSizeException e) {
            Log.e(TAG, "Illegal block size", e);
            return null;
        } catch (BadPaddingException e) {
            Log.e(TAG, "Bad padding", e);
            return null;
        }
        return encryptedData;
    }

    public byte[] dencrypt(byte[] clearData) {
        try {
            aesCipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        } catch (InvalidKeyException e) {
            Log.e(TAG, "Invalid key", e);
            return null;
        } catch (InvalidAlgorithmParameterException e) {
            Log.e(TAG, "Invalid algorithm " + CIPHER_ALGORITHM, e);
            return null;
        }

        byte[] dencryptedData;
        try {
            dencryptedData = aesCipher.doFinal(clearData);
        } catch (IllegalBlockSizeException e) {
            Log.e(TAG, "Illegal block size", e);
            return null;
        } catch (BadPaddingException e) {
            Log.e(TAG, "Bad padding", e);
            return null;
        }
        return dencryptedData;
    }

    private byte[] encodeDigest(String text) {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance(MESSAGEDIGEST_ALGORITHM);
            //return digest.digest(text.getBytes());
            return text.getBytes();
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "No such algorithm " + MESSAGEDIGEST_ALGORITHM, e);
        }

        return null;
    }
}

For C# this is how i create my object:

Crypto cr = new Crypto("asdfgasdfgasdfgasdfgasdfgasdfgas");

For C# I use this class:

public class Crypto
{
    private ICryptoTransform rijndaelDecryptor;
    // Replace me with a 16-byte key, share between Java and C#
    private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    public Crypto(string passphrase)
    {
        byte[] passwordKey = encodeDigest(passphrase);

        //AesManaged as256 = new AesManaged();
        //as256.CreateDecryptor(passwordKey, rawSecretKey);
        RijndaelManaged rijndael = new RijndaelManaged();
        rijndael.KeySize = 256;
        rijndael.Mode = CipherMode.CBC;
        rijndael.Padding = PaddingMode.PKCS7;
        rijndaelDecryptor = rijndael.CreateDecryptor(passwordKey, rawSecretKey);



    }

    public byte[] Decrypt(byte[] encryptedData)
    {
        byte[] newClearData = rijndaelDecryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
       // return Encoding.ASCII.GetString(newClearData);
        return newClearData;
    }

    public string DecryptFromBase64(string encryptedBase64)
    {
        return null;// Decrypt(Convert.FromBase64String(encryptedBase64));
    }

    private byte[] encodeDigest(string text)
    {
        MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
        return Encoding.ASCII.GetBytes(text);
        //return x.ComputeHash(data);
    }
}
Community
  • 1
  • 1
Tobiel
  • 1,543
  • 12
  • 19
  • 1
    Don't reuse the key as IV. You need to create a new IV for each message you want to encrypt, and transfer it alongside the ciphertext. The IV must be 16 bytes, regardless of the key size. – CodesInChaos Nov 23 '13 at 22:03

1 Answers1

0

Actually, your C# code is wrong. 256 / 8 = 32 bytes. You supplied 16 bytes as your AES key (byte[] rawSecretKey). I think the same goes for Android. It would give you an error on compiling.

prime6669
  • 1
  • 1
  • they work perfectly i don't get any error. If i set on the android class with 32 bytes, i get an error that say IV parameter should be 16 bytes long and on the c# class i get : Specified initialization vector (IV) does not match the block size for this algorithm. – Tobiel Nov 23 '13 at 00:21
  • IV should always be the blocksize for CBC, for AES that is 16 bytes. But I don't see any mention of the IV in the answer of prime6669, I only see a mention of *key size*. – Maarten Bodewes Nov 23 '13 at 00:53
  • in this line rijndaelDecryptor = rijndael.CreateDecryptor(passwordKey, rawSecretKey) I need to pass the KEY and the IV – Tobiel Nov 23 '13 at 01:01