Skip to content

Instantly share code, notes, and snippets.

@Erkened
Last active February 1, 2016 14:39
Show Gist options
  • Save Erkened/4726765783007ef8ed8c to your computer and use it in GitHub Desktop.
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]
// 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