简体   繁体   中英

Using base64 encoding with NSInputStream

I'm using RNCryptor to crypt files and for large files I use NSInputStream to separate file into chunks and to encode / decode those chunks. It worked great until I needed to base64 encode / decode chunks which are passed to streams.

Following code works perfectly fine for encoding, except it doesn't do base64 encoding:

  NSInputStream *tmpStream = [[NSInputStream alloc] initWithURL:fileURL];
    NSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];

    [tmpStream open];
    [outputStream open];

    __block NSMutableData *data = [NSMutableData dataWithLength:kBlockSize];
    __block RNEncryptor *encryptor = nil;

    dispatch_block_t readStreamBlock = ^{
        [data setLength:kBlockSize];
        NSInteger bytesRead = [tmpStream read:[data mutableBytes] maxLength:kBlockSize];

        if (bytesRead < 0) {

            NSLog(@"An error occurred while decrypting file stream");
            if (resultBlock) { resultBlock(nil); }
            return;
        }
        else if (bytesRead == 0){
            [encryptor finish];
        }
        else {
            [data setLength:bytesRead];
            [encryptor addData:data];
        }
    };

    encryptor = [[RNEncryptor alloc] initWithSettings:kRNCryptorAES256Settings
                                             password:HUCryptorPassword
                                              handler:^(RNCryptor *cryptor, NSData *data) {

                                                    [outputStream write:data.bytes maxLength:data.length];

                                                    if(cryptor.isFinished){

                                                        [outputStream close];

                                                        if (resultBlock) {
                                                            resultBlock([NSString stringWithFormat:@"%@", filePath]);
                                                        }
                                                    }
                                                    else {
                                                        readStreamBlock();
                                                    }
                                                }];
    readStreamBlock();

I tried adding base64 encoding after the data is encrypted and before writing to output stream:

NSData *base64Data = [data base64EncodedDataWithOptions:kNilOptions]; //Tried with all options
[outputStream write:base64Data.bytes maxLength:base64Data.length];

But that gives me incorrect results in output file.

Only correct way I get correctly encoded / decoded data is to load whole file in memory and call encode / decode methods.

NSData *resultData = [NSData dataWithContentsOfFile:filePath]; //This is location of output file stream
NSData *encodedData = [resultData base64EncodedDataWithOptions:kNilOptions]; //Gives me correct base64 encoded data

I want to avoid that since I need to make encoding / decoding big files, such as videos, sounds and images.

Is there any safe way to accomplish this?

4 base64 characters fit in three bytes.

When encoding make sure you encode chunks of 4 characters, holding over any remainder for the next portion of the stream. As the end of the stream encode what is left. Base64 pads the end of data that is not mod4, that is the "=" characters at the end.

For decoding decode in chunks that are mod3 encoded characters in length.

If you set it up so that you encode in 3 block (or multiples or 3) then the base64 encoding will also fall on a boundary.

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