Search code examples
objective-ccocoansdatacommoncrypto

Extract subdata from NSData without copying


I have the following situation: there is a NSData that i need to decrypt. The data consists of:

  • fixed length file header
  • encrypted content

I'm using CCCrypt for decryption, but it probably doesn't matter, because this is more of an NSData related question. This is how i'm separating things now (pseudocode):

int hdrsize; // this contains the size of the header
NSData *data; // this contains full encrypted data with a header

// this gives me information, stored in the header + some additional stuff
NSDictionary *hdr = [self _headerInfoFromData:data];

// THIS IS THE PROBLEM AREA
data = [data subdataWithRange:NSMakeRange(hdrsize, [data length] - hdrsize)];

// And the decryption part
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, MS_SEC_ENC_ALGORITHM, kCCOptionPKCS7Padding,
                                      [key bytes], MS_SEC_ENC_KEY_SIZE,
                                      [[hdrdict objectForKey:@"iv"] bytes],
                                      [data bytes], dataLength,
                                      buffer, bufferSize,

As you can see, my problem here is that for decryption i need to extract the part of NSData without the header. But is there a way to simply somehow "reuse" the bytes that are already there instead of making the copy? Maybe there's some sort of way to create a no-copy byte buffer out of it, skipping first X bytes and passing that into CCCrypt instead?

Thanks for your help


Solution

  • Have you verified that -subdataWithRange: does copy the bytes? If it does, you can always use +dataWithBytesNoCopy:length:, just make sure to handle ownership properly.

    EDIT

    I'm such a fool. Just do this:

    int hdrsize; // this contains the size of the header
    NSData *data; // this contains full encrypted data with a header
    
    // this gives me information, stored in the header + some additional stuff
    NSDictionary *hdr = [self _headerInfoFromData:data];
    
    // And the decryption part
    CCCryptorStatus cryptStatus = CCCrypt(
        kCCDecrypt,
        MS_SEC_ENC_ALGORITHM,
        kCCOptionPKCS7Padding,
        [key bytes],
        MS_SEC_ENC_KEY_SIZE,
        [[hdrdict objectForKey:@"iv"] bytes],
        data.bytes + hdrsize,
        data.length - hdrsize,
        buffer,
        bufferSize,