Last active
February 1, 2016 14:39
-
-
Save Erkened/4726765783007ef8ed8c to your computer and use it in GitHub Desktop.
Method to XOR multiple strings into one MD5 hexadecimal hash string in Swift 2. This means that [string1, string2, string3] gives the same MD5 hash as [string3, string2, string1]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Remember to #import <CommonCrypto/CommonCrypto.h> in the Bridging-Header.h file | |
/* Example of use | |
let query = "#test1 #test2 #test3" | |
let queryArray = query.characters.split{$0 == "#"}.map(String.init) | |
guard let hash = combineStringsIntoHash(queryArray) else{ | |
return | |
} | |
print("hash: \(hash)") | |
*/ | |
func combineStringsIntoHash(stringsArray:[String]) -> String?{ | |
// If no strings are passed, return nil | |
guard stringsArray.count > 0 else{ | |
return nil | |
} | |
// If only one string is passed there is no need to XOR | |
if stringsArray.count == 1{ | |
return hex(md5(stringsArray[0])) | |
} | |
// If there are 2 strings or more, XOR the strings together to achieve one hash | |
let hashArray:[[UInt8]] = stringsArray.map({md5($0)}) | |
// Get the array to start at index 1 rather than index 0 and use the value at index 0 as the initial value | |
var subArray = hashArray | |
subArray.removeFirst() | |
return hex(subArray.reduce(hashArray[0], combine: {xor($0, hash2: $1)})) | |
} | |
// Transform a string into an MD5 hash bytes array | |
private func md5(string: String) -> [UInt8] { | |
// Make the string lowercase and remove all non-alphanumeric characters | |
let nonAlphaNumericCharactersSet = NSCharacterSet.alphanumericCharacterSet().invertedSet | |
let alphaNumericString = string.lowercaseString.componentsSeparatedByCharactersInSet(nonAlphaNumericCharactersSet).joinWithSeparator("") | |
// Remove all accents - source: http://nshipster.com/cfstringtransform/ | |
let noAccentsString = NSMutableString(string: alphaNumericString) as CFMutableStringRef | |
CFStringTransform(noAccentsString, nil, kCFStringTransformStripCombiningMarks, false) | |
// Cast CFMutableString into NSString | |
let cleanString = NSString(string: noAccentsString) | |
print("cleanString: \(cleanString)") | |
// Get the MD5 hash out of the string as a byte array [UInt8] | |
var digest = [UInt8](count: Int(CC_MD5_DIGEST_LENGTH), repeatedValue: 0) | |
if let data = cleanString.dataUsingEncoding(NSUTF8StringEncoding) { | |
CC_MD5(data.bytes, CC_LONG(data.length), &digest) | |
} | |
return digest | |
} | |
// Combine 2 byte arrays into one using the XOR operation | |
private func xor(hash1:[UInt8], hash2:[UInt8]) -> [UInt8]{ | |
var xorArray:[UInt8] = [] | |
for i in 0..<hash1.count{ | |
xorArray.append(hash1[i] ^ hash2[i]) | |
} | |
return xorArray | |
} | |
// Transform a byte array into an hex string | |
private func hex(hash:[UInt8]) -> String{ | |
var returnedHex = "" | |
// Create the hex string, for example "63C6DD1FA19DA678C85BD4A4B65145 2" | |
for byte in hash{ | |
returnedHex += NSString(format: "%2X", byte) as String | |
} | |
// If we have any spaces genererated from ' 0', we simply fill the spaces in with a 0 | |
// e.g. "63C6DD1FA19DA678C85BD4A4B6514502" | |
return returnedHex.stringByReplacingOccurrencesOfString("\u{0020}", withString: "0") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment