CompressionSample/BlockCompression.c
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Provides code that performs block compression. |
*/ |
/* |
Example code to compress/encrypt an input file, and then to decrypt/decompress the intermidiate file. |
Input should be identical to output. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdint.h> |
#include "compression.h" |
#include <CommonCrypto/CommonCryptor.h> |
float doBlockCompression(FILE* fi, FILE* fo, compression_algorithm algorithm) |
{ |
// Returns the compression ratio. |
// Input buffer: Determine buffer size, allocate, and fill. |
fseek(fi, 0L, SEEK_END); |
size_t src_size = ftell(fi); |
fseek(fi, 0L, SEEK_SET); |
uint8_t *src_buffer = malloc(src_size); |
if (src_buffer == NULL) { |
fprintf(stderr,"error: fail to allocate src buffer (%zu bytes) \n", src_size); |
return 0; |
} |
fread(src_buffer, 1, src_size, fi); |
// Output buffer: Allocate (add extra 4096 bytes). |
size_t dst_size = src_size+4096; |
uint8_t *dst_buffer = malloc(dst_size); |
if (dst_buffer == NULL) { |
fprintf(stderr,"error: fail to allocate dst buffer (%zu bytes) \n", dst_size); |
return 0; |
} |
/* |
When doing both compression and encryption, do compression first. |
Compression may not work well on encrypted data. |
*/ |
// LZFSE compression. |
dst_size = compression_encode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL, algorithm); |
// Pad bytes, if needed, for 16-byte/block encryption. |
while (dst_size&15) { |
dst_buffer[dst_size++] = 0; |
} |
float compression_ratio = ((float) src_size)/((float) dst_size); |
printf("compression ratio = %.2f\n", compression_ratio); |
printf("compression ratio = %.2f\n", ((float) src_size)/((float) dst_size)); |
if (dst_size >= src_size) { |
fprintf(stderr, "compression ratio < 1, early exit.\n"); |
return 1; |
} |
// AES-128 KEY (used for both encryption and decryption). |
const uint8_t AES_KEY[16] = "0123456789abcedf"; |
size_t byteProcessed; |
// ECB encryption. |
CCCryptorRef cryptor; |
if (kCCSuccess != CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode, AES_KEY, 16, NULL, &cryptor)) { |
fprintf(stderr," error in CCCryptorCreate encrypt\n"); |
exit(1); |
} |
if (kCCSuccess != CCCryptorUpdate(cryptor, dst_buffer, dst_size, src_buffer, dst_size, &byteProcessed)) { |
fprintf(stderr,"encrypt update fails.\n"); |
exit(2); |
} |
// Write compressed and encrypted output. |
fwrite(src_buffer, 1, dst_size, fo); |
// ECB decryption. |
CCCryptorRef decryptor; |
if (kCCSuccess != CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionECBMode, AES_KEY, 16, NULL, &decryptor)) { |
fprintf(stderr," error in CCCryptorCreate decrypt\n"); |
exit(3); |
} |
if (kCCSuccess != CCCryptorUpdate(decryptor, src_buffer, dst_size, dst_buffer, dst_size, &byteProcessed)) { |
fprintf(stderr, "decrypt update fails.\n"); |
exit(4); |
} |
// LZFSE decompression. |
src_size = compression_decode_buffer(src_buffer, src_size, dst_buffer, dst_size, NULL, algorithm); |
// Write decrypted and decompressed output. |
fwrite(src_buffer, 1, src_size, fo); |
// Close files. |
fclose(fi); |
fclose(fo); |
// Free allocated memory. |
free(src_buffer); |
free(dst_buffer); |
return compression_ratio; |
} |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-09-16