Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to encrypt a file in .net and decrypt in android

I have been working on project where we have to securely keep a pdf in android sd card. We want this to encrypted in .net because its has to be transferred through API. I've implemented in .NET but unable to decrypt in android.

Code to encrypt a File

public static void EncryptFile(string inputFile, string outputFile)
    {
        try
        {
            string password = @"myKey123"; // Your Key Here
            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] key = UE.GetBytes(password);

            string cryptFile = outputFile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

            RijndaelManaged RMCrypto = new RijndaelManaged();
            RMCrypto.Mode = CipherMode.CBC; //remember this parameter
            RMCrypto.Padding = PaddingMode.PKCS7;  //remember this parameter
            RMCrypto.KeySize = 0x80;
            RMCrypto.BlockSize = 0x80;
            CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateEncryptor(key, key),
                CryptoStreamMode.Write);

            FileStream fsIn = new FileStream(inputFile, FileMode.Open);

            int data; 
            while ((data = fsIn.ReadByte()) != -1)
            {
                cs.WriteByte((byte)data);
            }

            fsIn.Close();
            cs.Close();
            fsCrypt.Close();

        }
        catch
        {
            Console.WriteLine("Encryption failed!", "Error");
        }
    }

Code to Decrypt file

public  static void DecryptFile(string inputFile, string outputFile)
    {

        {
            string password = @"myKey123"; // Your Key Here

            UnicodeEncoding UE = new UnicodeEncoding();
           byte[] key = UE.GetBytes(password);



            FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);

            RijndaelManaged RMCrypto = new RijndaelManaged();
            RMCrypto.Mode = CipherMode.CBC; //remember this parameter
            RMCrypto.Padding = PaddingMode.PKCS7;  //remember this parameter
            RMCrypto.KeySize = 0x80;
            RMCrypto.BlockSize = 0x80;
            CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateDecryptor(key, key),
                CryptoStreamMode.Read);

            FileStream fsOut = new FileStream(outputFile, FileMode.Create);

            int data;
            while ((data = cs.ReadByte()) != -1)
                fsOut.WriteByte((byte)data);

            fsOut.Close();
            cs.Close();
            fsCrypt.Close();

        }
    }

I tried in Android using below code

public static byte[] decodeFile(String key, byte[] fileData) throws Exception
{
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //this parameters should not be changed
    byte[] keyBytes = new byte[16];
    byte[] b = key.getBytes("UTF-16");
    System.out.println("RAM"+b);
    int len = b.length;
    if (len > keyBytes.length)
        len = keyBytes.length;
    System.arraycopy(b, 0, keyBytes, 0, len);
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
    byte[] decrypted = cipher.doFinal(fileData);
    return decrypted;
}

When running this code i get error:

error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
like image 619
Prakash Avatar asked Sep 01 '15 12:09

Prakash


1 Answers

So i found the problem with your code and the architecture you are using. When you choose to cryptography files in differents languages programs and in different envrioment (Android ("unix") and Windows) you need to remember the concept of little and big endian. - the wikipedia Endianness .

Aperently in Java the it threat always with BIG endian so the most significative byte (MSB) it s different from the C# using the Least significative byte (LSB), this step cause a hard to trace problem.

I created a code based on yours but using Java and not android and couldn't make the code work because i always had the same error message BadPaddingException: Given final block not properly padded. The error message didn't say much about the real issue that was the key file.
When you read in Java it's different from .NET because when you convert your key to byte the Java architecture threats with the MSB when your real key it's using LSB.

So the real answer it's this you need to convert your key to array of bytes telling to use the Least significative byte so you always have the same array of bytes in .NET and in Java
Something like this:

//the bKey it's the array of bytes and the key it's the String your are using.
byte[] bKey = key.getBytes("UTF-16LE");



I found the issue with the LE because i read the array of bytes from .NET and from Java and they are different so this gave me the start to find this issue

Good luck with your system !.

Ps.: I had a problem with the Decoding because the issue you have when decode and decode a array of bytes. I found a path that you should use Apache Commons Base64 to Decode the string in Java.
References

-Big/Little endian - Difference between Big Endian and little Endian Byte order
-Error with padded - BadPaddingException: Given final block not properly padded
-The tip the problem is in the key - Given final block not properly padded
-Decode Base64 - Decoding a Base64 string in Java




The code i used to test.

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.charset.Charset;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;

    public class HelloWorld {

        public static void main(String[] args) throws Exception {
            // TODO Auto-generated method stub
            Path p = Paths
                    .get("C:\\Users\\casilva\\workspace\\StackOverflow\\src\\tst.enc");

            byte[] a = Files.readAllBytes(p);
            byte[] result = decodeFile("myKey123", a);
            System.out.println("Result=" + new String(result, "UTF-8"));
        }


        public static byte[] decodeFile(String key, byte[] fileData)
                throws Exception {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] bKey = key.getBytes("UTF-16LE");

            SecretKeySpec keySpec = new SecretKeySpec(bKey, "AES");

            IvParameterSpec ivSpec = new IvParameterSpec(bKey);

            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

            byte[] decrypted = cipher.doFinal(fileData);

            return decrypted;
        }

    }
like image 101
eng.augusto Avatar answered Oct 18 '22 16:10

eng.augusto