Я пытаюсь, чтобы расшифровка файлов работала в Android. Файл, который у меня есть, был зашифрован из python с использованием Crypto.Cipher AES: полный код:
import os, binascii, struct
from Crypto.Cipher import AES
def encrypt_file():
chunksize=64*1024
iv = "96889af65c391c69"
k1 = "cb3a44cf3cb120cc7b8b3ab777f2d912"
file = "tick.png"
out_filename = "entick.png"
dir = os.path.dirname(__file__)+"\\"
print(iv)
encryptor = AES.new(key, AES.MODE_CBC, iv)
in_filename = dir+file
filesize = os.path.getsize(in_filename)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
outfile.write(struct.pack('<Q', filesize))
outfile.write(iv)
while True:
chunk = infile.read(chunksize)
if len(chunk) == 0:
break
elif len(chunk) % 16 != 0:
chunk += ' ' * (16 - len(chunk) % 16)
outfile.write(encryptor.encrypt(chunk))
if __name__ == "__main__":
encrypt_file()
Функция расшифровки Android (основная):
private static File main(String fname, File enfile, String IV, String key) {
try {
byte[] bkey = key.getBytes("UTF-8");
byte[] bIV = IV.getBytes("UTF-8");
Log.d("ByteLen","bkey:"+Integer.toString(bkey.length));
Log.d("ByteLen","bIV:"+ Integer.toString(bIV.length));
File aesFile;
aesFile = enfile;
Log.d("AESFILELENGTH", "aes length: " + aesFile.length());
File aesFileBis = new File(String.valueOf(Environment.getExternalStorageDirectory().toPath()), "tick.png"); //to be replaced with fname
FileInputStream fis;
FileOutputStream fos;
CipherInputStream cis;
SecretKeySpec secretKey = new SecretKeySpec(bkey, "AES");
Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(bIV);
decrypt.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
fis = new FileInputStream(aesFile);
cis = new CipherInputStream(fis, decrypt);
fos = new FileOutputStream(aesFileBis);
try {
byte[] mByte = new byte[8];
int i = cis.read(mByte);
Log.i("MBYTE", "mbyte i: " + i);
while (i != -1) {
fos.write(mByte, 0, i);
i = cis.read(mByte);
}
} catch (IOException e) {
e.printStackTrace();
}
fos.flush();
fos.close();
cis.close();
fis.close();
return aesFileBis;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Модуль Crypto.Cipher вставляет IV в файл в виде байтов 8-24, поэтому я создал этот метод для их извлечения:
private String IV(File enfile) throws UnsupportedEncodingException, FileNotFoundException {
int size = 24;
byte bytes[] = new byte[size];
byte tmpBuff[] = new byte[size];
if(enfile.canRead()){
//run decryption code
FileInputStream fis= new FileInputStream(enfile);
try {
int read = fis.read(bytes, 0, size);
if (read < size) {
int remain = size - read;
while (remain > 0) {
read = fis.read(tmpBuff, 0, remain);
System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
remain -= read;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
String IV = new String(bytes, "US-ASCII");
IV = IV.substring(8,24);
return IV;
}
Из функции расшифровки, которую я проверил и проверил, длина ключа составляет 32 байта, длина ключа - 16 байтов, и оба являются правильными ключом IV и ключом. Я знаю, что переключаюсь с байтового массива на строковый и обратно, но это только для тестирования.
Я просмотрел несколько постов, касающихся этой проблемы, и пока нашел только посты, касающиеся того, что ключ имеет неправильный размер в байтах или расшифровывает строки, а не файлы, и поэтому переключение кодировки base64, по-видимому, неприменимо. Я думаю, что проблема заключается в том, как Crypto.Cipher дополняет файлы, так как первые 8 байтов выглядят как ненужные (SO и NULL байты), а затем есть 16 байтов IV.