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

I worked on a project where we should safely store the pdf file in the android sd card. We want this to be encrypted in .net, because it must be passed through the API. I implemented in .NET but could not decrypt in android.

File Encryption Code

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 a 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 on 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 I run this code, I get an error:

 error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt 
+5
source share
1 answer

So, I found a problem with your code and architecture that you are using. When you select cryptographic files in different languages ​​and in different applications (Android ("unix") and Windows), you need to remember the concept of small and large endian. - Wikipedia Encyclopedia .

Explicitly in Java, it always threatens the BIG endian, so the most significant byte (MSB) is different from C # using the least significant byte (LSB), this step causes a complex trace task.

I created code based on yours, but using Java, not android, and couldn't get the code to work, because I always had the same BadPaddingException: Given final block not properly padded . The error message did not say the real problem, which was key .
When you read in Java, it is different from .NET because when you convert your key to a threat byte of the Java architecture using MSB, when your real key uses LSB.

So the real answer to this question is 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 that:

 //the bKey it the array of bytes and the key it 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 decoding, because you have a problem decoding and decoding an array of bytes. I found a path that you should use Apache Commons Base64 to decode a string in Java.
References

-Big / Little endian - The difference between the buy-in of a large byte and the small byte of Endian Byte
-Error with padded - BadPaddingException: This final block is not filled correctly
- Contact problem in the key - Given that the last block is incorrectly inserted
-Decode Base64 - Decoding a Base64 string in Java




The code I used for testing.

  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; } } 
+3
source

All Articles