Pham Hoan
Pham Hoan

Reputation: 2127

Checksum and XOR in Swift

I worte these methods in Objective-C. They're just checksum and XOR some NSData

- (void)XOR:(NSMutableData *)inputData withKey:(NSData *)key
{
    unsigned char* inputByteData = (unsigned char*)[inputData mutableBytes];
    unsigned char* keyByteData   = (unsigned char*)[key bytes];
    for (int i = 0; i < [inputData length]; i++)
    {
        inputByteData[i] = inputByteData[i] ^ keyByteData[i % [key length]];
    }
}

- (Byte)checkSum:(NSMutableData *)data withLength:(Byte)dataLength
{
    Byte * dataByte = (Byte *)malloc(dataLength);
    memcpy(dataByte, [data bytes], dataLength);

    Byte result = 0;
    int count = 0;
    while (dataLength>0) {
        result += dataByte[count];
        dataLength--;
        count++;
    };
    result = result&0xff;
    return result&0xff;
}

However, I'm not familiar with Bitwise operators, especially in Swift, with these UnsafeMutablePointer<Void>... things.

Can anybody help me converting this ? (Basically, I need checksum and XOR functions)
One more things, should they be put in NSData/NSMutableData extension ?

Thank you.

Upvotes: 5

Views: 5556

Answers (5)

dhcmrlchtdj
dhcmrlchtdj

Reputation: 21

Swift makes it easy to treat Data objects as arrays of bytes, which you can manipulate using a combination of zip and map, thus avoiding the need for a for loop. That results in terser and IMHO more readable code:

extension Data {
    static func ^ (lhs: Data, rhs: Data) -> Data {
        Data(zip(Array(lhs), Array(rhs)).map { $0 ^ $1 })
    }
}

Upvotes: 1

karim
karim

Reputation: 15589

Swift support operator overloading, so you can easily do let xorData = data1 ^ data2. I have written an extension for non-similar size data to xor.

extension Data {
    static func ^ (left: Data, right: Data) -> Data {
        if left.count != right.count {
            NSLog("Warning! XOR operands are not equal. left = \(left), right = \(right)")
        }

        var result: Data = Data()
        var smaller: Data, bigger: Data
        if left.count <= right.count {
            smaller = left
            bigger = right
        } else {
            smaller = right
            bigger = left
        }

        let bs:[UInt8] = Array(smaller)
        let bb:[UInt8] = Array (bigger)
        var br = [UInt8] ()
        for i in 0..<bs.count {
            br.append(bs[i] ^ bb[i])
        }
        for j in bs.count..<bb.count {
            br.append(bb[j])
        }
        result = Data(br)
        return result
    }
}

Upvotes: 1

Pham Hoan
Pham Hoan

Reputation: 2127

Swift 3 update:

public extension Data {

    public mutating func xor(key: Data) {
        for i in 0..<self.count {
            self[i] ^= key[i % key.count]
        }
    }


    public func checkSum() -> Int {
        return self.map { Int($0) }.reduce(0, +) & 0xff
    }
}

You can also create another function: xored(key: Data) -> Data.
Then you can chain these operators: xored(key).checksum()

Upvotes: 4

Raunak
Raunak

Reputation: 1

Updated for Swift 3:

func xor(data: Data, with key: Data) -> Data {
    var xorData = data

    xorData.withUnsafeMutableBytes { (start: UnsafeMutablePointer<UInt8>) -> Void in
        key.withUnsafeBytes { (keyStart: UnsafePointer<UInt8>) -> Void in
            let b = UnsafeMutableBufferPointer<UInt8>(start: start, count: xorData.count)

            let k = UnsafeBufferPointer<UInt8>(start: keyStart, count: data.count)
            let length = data.count

            for i in 0..<xorData.count {
                b[i] ^= k[i % length]
            }
        }
    }

    return xorData
}

Upvotes: 0

findall
findall

Reputation: 2193

UnsafeBufferPointer/UnsafeMutableBufferPointer might be what you need now. I've tried translating your code into Swift below. (But the code is not tested well.)

func XOR(inputData: NSMutableData, withKey key: NSData) {
    let b = UnsafeMutableBufferPointer<UInt8>(start:
        UnsafeMutablePointer(inputData.mutableBytes), count: inputData.length)

    let k = UnsafeBufferPointer<UInt8>(start:
        UnsafePointer(key.bytes), count: key.length)

    for i in 0..<inputData.length {
        b[i] ^= k[i % key.length]
    }
}

func checkSum(data: NSData) -> Int {
    let b = UnsafeBufferPointer<UInt8>(start:
        UnsafePointer(data.bytes), count: data.length)

    var sum = 0
    for i in 0..<data.length {
        sum += Int(b[i])
    }
    return sum & 0xff
}

Upvotes: 9

Related Questions