1

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

Marius
  • 3,976
  • 5
  • 37
  • 52

1 Answers1

0

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,
Stefan Fisk
  • 1,563
  • 13
  • 19
  • that should be `-dataWithBytesNoCopy:length:freeWhenDone:`. – Stefan Fisk Jan 24 '14 at 13:26
  • I know about dataWithBytesNoCopy, but i need it to skip first X bytes. And i assume this can be done with pointers and stuff, but i'm just terrible at that. – Marius Jan 24 '14 at 13:33
  • 1
    it's easy enough, just use data.bytes as the pointer and add the number of bytes to skip, so say `[NSData dataWithBytesNoCopy:data.byes + hdrSize length:data.length - hdrSize freeWhenDone:NO]`. – Stefan Fisk Jan 24 '14 at 13:35
  • The created object will however be entirely dependent on the original data, if data is released, the derived object will crash the app upon access of its content. – Stefan Fisk Jan 24 '14 at 13:36
  • Stefan - this is exactly the pointer stuff i was looking for. Thanks! There will be no problem with the ownership and the original data ;] – Marius Jan 24 '14 at 13:41
  • @Marius: I actually assume that `subDataWithRange:` is the better solution. `NSData` (as an *immutable* object) already does optimisations to avoid copies. On the other hand, calling `data.bytes` might force a copy and should be avoided if possible. Compare this excellent answer: http://stackoverflow.com/a/19251938/1187415. – Martin R Jan 24 '14 at 14:12
  • @MartinR this does sound logical and it should be the way things work, but i can't find any info in the official documentation, confirming that subDataWithRange optimizes things, or that bytes makes a copy. Is there any other info on this? – Marius Jan 24 '14 at 14:22
  • it shouldn't be to hard to check in the debugger, NSData is likely old enough to allow inspecting its members, so that you can see if the subdata is just pointing to the original rather than to a copy. – Stefan Fisk Jan 24 '14 at 14:49
  • see my edit, CCCrypt takes a pointer anyhow, you can just do the maths there instead of getting the subdata. – Stefan Fisk Jan 24 '14 at 14:52