Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I do a bit-wise XOR on NSData in Objective-C?

I have two NSData objects, data1 and data2, and I'd like to do a bit-wise XOR and store the result in a third NSData object, xorData.

The first thing I tried was this:

*data1.bytes^*data2.bytes;

but it gave an error of:

Invalid operands to binary expression ('const void' and 'const void')

So I tried to write a function that would extract the bytes of the data into an array of integers, perform the xor on the integers, then save the result back into an NSData object. The function looks like this:

+(NSData *) DataXOR1:(NSData *) data1
DataXOR2:(NSData *)data2{
    const int *data1Bytes = [data1 bytes];
    const int *data2Bytes = [data2 bytes];
    NSMutableArray *xorBytes = [[NSMutableArray alloc] init ];
    for (int i = 0; i < data1.length;i++){
         [xorBytes addObject:[NSNumber numberWithInt:(data1Bytes[i]^data2Bytes[i])]];
    }
    NSData *xorData = [NSKeyedArchiver archivedDataWithRootObject:xorBytes];
    return xorData;
}

This runs, but gives the wrong answers. When I test it on two simple pieces of data (data1 = 0x7038 and data2 = 0x0038), and use NSLog to output what the values are, I get:

data1Bytes[0] = 8070450532247943280
data2Bytes[0] = 8070450532247943168
data1Bytes[0]^data2Bytes[0] = 112
data1Bytes[1] = 10376302331560798334
data2Bytes[1] = 10376302331560798334
data1Bytes[1]^data2Bytes[1] = 0

This boggles my mind a bit because the values in the dataXBytes arrays are totally wrong, but they're xor-ing to the right values! (0x70 ^ 0x00 = 0x70 = 112)

I think it might be an endian-ness problem, but when I change the initialization of data1Bytes to:

const int *data1Bytes = CFSwapInt32BigToHost([data1 bytes]);

it runs into an error when it tries to access it, saying:

Thread 1: EXC_BAD_ACCESS(code=1, address = 0xa08ad539)

Is there a much simpler way to do the xor? If not, how can I fix the endian problem?

like image 570
Sam Jaques Avatar asked Mar 16 '23 06:03

Sam Jaques


1 Answers

Casting to int then archiving an NSArray of NSNumbers will definitely not create the result you're looking for. You'll want to have some mutable NSData to which you append the individual bytes to, something like

+(NSData *) DataXOR1:(NSData *) data1
            DataXOR2:(NSData *)data2{
    const char *data1Bytes = [data1 bytes];
    const char *data2Bytes = [data2 bytes];
    // Mutable data that individual xor'd bytes will be added to
    NSMutableData *xorData = [[NSMutableData alloc] init];
    for (int i = 0; i < data1.length; i++){
        const char xorByte = data1Bytes[i] ^ data2Bytes[i];
        [xorData appendBytes:&xorByte length:1];
    }
    return xorData;
}
like image 56
Tim Johnsen Avatar answered Apr 02 '23 10:04

Tim Johnsen