0

I receive from a Server in Python a file encrypted in this manner:

import os
from Crypto.Cipher import AES
from Crypto import Random


def pad(s):
    return s + b"\0" * (AES.block_size - len(s) % AES.block_size)


def encrypt(message, key):
    message = pad(message)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    return iv + cipher.encrypt(message)


def encrypt_file(file_name, key):
    with open("epub/" + file_name, 'rb') as fo:
        plaintext = fo.read()
    enc = encrypt(plaintext, key)
    file_name = "enc/" + file_name
    with open(file_name, 'wb') as fo:
        fo.write(enc)


for list in os.listdir('./epub'):
    if list.find('.epub') != -1:
        key = '0123456789012345'
        encrypt_file(list, key)

My App in Android decrypt file in this manner:

FileInputStream epubCifr = new FileInputStream(Environment.getExternalStorageDirectory() + "/Skin/readium/epub_content/" + title + "/" + title + ".epub");
FileOutputStream epubDec = new FileOutputStream(Environment.getExternalStorageDirectory() + "/Skin/readium/epub_content/" + title + "/" + title + "_dec.epub");

SecretKeySpec sks = new SecretKeySpec(key, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(epubCifr, cipher);
int b;
byte[] d = new byte[16];
while ((b = cis.read(d)) != -1)
    epubDec.write(d, 0, b);

epubDec.flush();
epubDec.close();
cis.close();

Now. I would do the same thing in an app for iOS but I'm a newbie in objective C. I can't change code on Server. I tried to use RNCrypto for iOS but with poor results. Any suggestions? Thanks

EDIT 1

Sorry. This is my code in objective C. I think that there are some settings in RNCryptor that are wrong.

int blockSize = 16;

NSInputStream *cryptedStream = [NSInputStream inputStreamWithFileAtPath:@"epub.epub"];
NSOutputStream *decryptedStream = [NSOutputStream outputStreamToFileAtPath:@"epub_dec.epub" append:NO];

[cryptedStream open];
[decryptedStream open];

__block NSMutableData *data = [NSMutableData dataWithLength:blockSize];
__block RNEncryptor *decryptor = nil;

dispatch_block_t readStreamBlock = ^{
    [data setLength:blockSize];
    NSInteger bytesRead = [cryptedStream read:[data mutableBytes] maxLength:blockSize];
    if (bytesRead < 0) {
    }
    else if (bytesRead == 0) {
        [decryptor finish];
    }
    else {
        [data setLength:bytesRead];
        [decryptor addData:data];
        NSLog(@"Sent %ld bytes to decryptor", (unsigned long)bytesRead);
    }
};

decryptor = [[RNEncryptor alloc] initWithSettings:kRNCryptorAES256Settings
password:@"0123456789012345"
handler:^(RNCryptor *cryptor, NSData *data) {
    NSLog(@"Decryptor recevied %ld bytes", (unsigned long)data.length);
    [decryptedStream write:data.bytes maxLength:data.length];
    if (cryptor.isFinished) {
        [decryptedStream close];
    }
    else {
        readStreamBlock();
    }
}];

readStreamBlock();

EDIT 2 Python code with PKCS7 and iv of 0 bytes.

from Crypto.Cipher import AES
from Crypto import Random
from pkcs7 import PKCS7Encoder


def pad(s):
    encoder = PKCS7Encoder()
    return encoder.encode(s)
    #return s + b"\0" * (AES.block_size - len(s) % AES.block_size)


def encrypt(message, key):
    message = pad(message)
    #iv = Random.new().read(AES.block_size)
    iv = b'0000000000000000'
    cipher = AES.new(key, AES.MODE_CBC, iv)
    return iv + cipher.encrypt(message)


def encrypt_file(file_name, key):
    with open("epub/" + file_name, 'rb') as fo:
        plaintext = fo.read()
    enc = encrypt(plaintext, key)
    file_name = "enc/" + file_name
    with open(file_name, 'wb') as fo:
        fo.write(enc)

key = '0123456789012345'
encrypt_file("epub1.epub", key)
decrypt_file("epub1.epub", key)
  • If your question is about your Objective-C code you should post it so that we can see what's wrong with it. – Kyll May 07 '15 at 10:15

1 Answers1

1

RNCryptor in this case is not a good choice because it imposes a format and method for encryption that does not match the method being used to encrypt.

You state that there is no padding but the Python code does pad the message with zero bytes, this is both non-standard, insecure and assumes that the data being encrypted does not end with a null byte. You will have to handle stripping the null padding after decryption. The usual padding is PKCS#7.

The iv for CBC mode is prepended to the encrypted data, this is a good scheme. You will need to separate the iv from the encryption data and apply it to the decryption function call.

It is not clear that the encryption key is exactly the correct length or what AES key size is being used. Presumably the Python method is using the length of the key to determine the AES key size, it can be 128, 192 or 256 bits and if not one of these padding the key to length. You will need to determine this and handle it in your code. The AES key size should really be specified and the key should be exactly the matching length.

With the above you can use the Apple supplied Common Crypto, specifically CCCrypt function.

It is potentially possible to modify the received data to match the requirements of RNCryptor and handle the padding after the decryption.

zaph
  • 111,848
  • 21
  • 189
  • 228
  • Thanks. So, can you suggest me some samples to encrypt and decrypt a file with CCCRypt in AES? – user2352453 May 07 '15 at 13:04
  • Sure. Do you need streaming capability? – zaph May 07 '15 at 13:50
  • Not necessarily. Encrypted file is stored on device – user2352453 May 07 '15 at 13:55
  • See [SO Answer](http://stackoverflow.com/a/23641521/451475). But you will have some work. Remove the `kCCOptionPKCS7Padding ` option. Figure out ther key size and set the algorithm as appropriate: `kCCKeySizeAES*` where `*` is 128, 192 or 254. As in the answer handle the iv and strip any padding. `CCCrypt` will null pad but I would not rely on that, pad the key yourself if necessary. – zaph May 07 '15 at 14:06
  • Works. Thanks. In an edit of answer I enter python code that I modified. – user2352453 May 07 '15 at 15:19