简体   繁体   中英

file encrypt in python decrypt in android

I have been trying to decrypt a file in android, encrypted from python, Here is python code i used in decrypting.

import os, random, struct
from Crypto.Cipher import AES
import sys
import hashlib

print("trying")

def encrypt_file(key, in_filename, out_filename=None, chunksize=64*1024):
    """ Encrypts a file using AES (CBC mode) with the
        given key.

        key:
            The encryption key - a string that must be
            either 16, 24 or 32 bytes long. Longer keys
            are more secure.

        in_filename:
            Name of the input file

        out_filename:
            If None, '<in_filename>.enc' will be used.

        chunksize:
            Sets the size of the chunk which the function
            uses to read and encrypt the file. Larger chunk
            sizes can be faster for some files and machines.
            chunksize must be divisible by 16.
    """
    if not out_filename:
        out_filename = in_filename + '.mjt'

    iv = 16 * '\x00'
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    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)
            outfile.write(bytes(iv, 'UTF-8'))

            while True:
                chunk = infile.read(chunksize)
                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                    chunk += b' ' * (16 - len(chunk) % 16)

                outfile.write(encryptor.encrypt(chunk))
                # outfile.write(bytes(encryptor.encrypt(chunk), 'UTF-8'))


def main():
    filename1 = sys.argv[-2]
    filename2 = sys.argv[-1]
    key = '0123456789abcdef'
    encrypt_file(key, filename1, filename2)
    print("done")


if __name__ == '__main__':
    main()

and here is my android function trying to decrypt with

private static byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

public static void decrypt(String inputFile, String outputFile, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
        FileInputStream fis = new FileInputStream(inputFile);

        FileOutputStream fos = new FileOutputStream(outputFile);

        IvParameterSpec iv = new IvParameterSpec(ivBytes);
        SecretKeySpec sks = new SecretKeySpec(password.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, sks, iv);
        CipherInputStream cis = new CipherInputStream(fis, cipher);

        int b;
        byte[] d = new byte[1024];
        while((b = cis.read(d)) != -1) {
            fos.write(d, 0, b);
        }
        fos.flush();
        fos.close();
        cis.close();
    }

this gives while using AES/CBC/NoPadding java.io.IOException: data not block size aligned and when AES/CBC/PKCS5Padding is used, it gives java.io.IOException: last block incomplete in decryption

AES is a block cipher so the messages need to be padded to exactly the multiple of the block size, both at encryption and decryption. Your encryption is fine. It reads the filesize, writes to first 8 bytes of your file, then writes 16 bytes IV and finally the content of file chunk by chunk ensuring the padding. However, your decryption does not follow the same pattern for decryption. AES is a 128 bit block cipher so you don't have to worry much about specifying PKCS5Padding, just need to follow the same routine in reverse as your encryption. There was a bug in your code related to iv too.

Try the following and it should work:

private static byte[] filesize = new byte[8];
private static byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

public static void decrypt(String inputFile, String outputFile, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
    FileInputStream fis = new FileInputStream(inputFile);
    FileOutputStream fos = new FileOutputStream(outputFile);
    fis.read(filesize, 0, 8);
    System.out.println(new String(filesize));
    fis.mark(9);
    fis.read(ivBytes, 0, 16);
    System.out.println(new String(ivBytes));
    fis.mark(25);
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    SecretKeySpec sks = new SecretKeySpec(password.getBytes(), "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.DECRYPT_MODE, sks, iv);
    File file = new File(inputFile);
    int byteLength = (int) file.length() - 24;
    System.out.println(Integer.toString(byteLength));
    byte[] bytes = new byte[byteLength];
    byteLength = fis.read(bytes);
    System.out.println(Integer.toString(byteLength));
    System.out.println(new String(bytes));
    InputStream bytesStream = new ByteArrayInputStream(bytes);
    CipherInputStream cis = new CipherInputStream(bytesStream, cipher);

    int b;
    byte[] d = new byte[1024];
    while((b = cis.read(d)) != -1) {
        fos.write(d, 0, b);
    }
    fos.flush();
    fos.close();
    cis.close();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM