I am trying to use CommonCrypto to encrypt an NSMutableData object in place (copying the resulting bytes to itself, without duplicating it). Previously, I was using CCCrypt() "one-shot" method, mainly because it seemed simple. I noticed that my data object got duplicated in memory. To avoid this, I tried using an NSInputStream object with a buffer size of 2048 bytes. I am reading my NSMutableData object, and continuously call CCCryptorUpdate(), to handle the encryption. The problem is, that it still seems to be duplicated. Here's my current code (please note that it's a category on NSMutableData - mainly because of historical reasons - thus the "self" references):
- (BOOL)encryptWithKey:(NSString *)key
{
// Key creation - not relevant to the dercribed problem
char * keyPtr = calloc(1, kCCKeySizeAES256+1);
[key getCString: keyPtr maxLength: sizeof(keyPtr) encoding: NSUTF8StringEncoding];
// Create cryptographic context for encryption
CCCryptorRef cryptor;
CCCryptorStatus status = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode, keyPtr, kCCKeySizeAES256, NULL, &cryptor);
if (status != kCCSuccess)
{
MCLog(@"Failed to create a cryptographic context (%d CCCryptorStatus status).", status);
}
// Initialize the input stream
NSInputStream *inStream = [[NSInputStream alloc] initWithData:self];
[inStream open];
NSInteger result;
// BUFFER_LEN is a define 2048
uint8_t buffer[BUFFER_LEN];
size_t bytesWritten;
while ([inStream hasBytesAvailable])
{
result = [inStream read:buffer maxLength:BUFFER_LEN];
if (result > 0)
{
// Encryption goes here
status = CCCryptorUpdate(
cryptor, // Previously created cryptographic context
&result, // Input data
BUFFER_LEN, // Length of the input data
[self mutableBytes], // Result is written here
[self length], // Size of result
&bytesWritten // Number of bytes written
);
if (status != kCCSuccess)
{
MCLog(@"Error during data encryption (%d CCCryptorStatus status)", status);
}
}
else
{
// Error
}
}
// Cleanup
[inStream close];
CCCryptorRelease(cryptor);
free(keyPtr);
return ( status == kCCSuccess );
}
I am definitely missing something obvious here, encryption, and even using input streams is a bit new to me..