1

I have got the exact same problem as in this thread:

MD5 of an UTF16LE (without BOM and 0-Byte End) in C#

However, I am trying to achieve this in a Swift 4 based iOS app. I tried all options discussed in

How to convert string to MD5 hash using ios swift

and also https://github.com/krzyzanowskim/CryptoSwift

but I am not able to generate the correct MD5 hash. I generated a byte array of the input string and removed the 0-byte at the end of the string and used the functions mentioned in the thread above. If someone could please point me in the right direction. Basically the utf8 string "1234567z-äbc" should become "9e224a41eeefa284df7bb0f26c2913e2"

That's what I tried so far:

        let str = "1234567z" + "-" + "äbc"
        let data = str.data(using: .utf16LittleEndian)!

        let bytesArray = data.map { $0 }
        let bytesArrayNoZero = bytesArray.filter{ $0 != 0}

        let str2 = String(bytes: bytesArrayNoZero, encoding: String.Encoding.utf16LittleEndian)

        print (fritz_01.MD5(str2!))



 func MD5(string: String) -> Data {
    let messageData = string.data(using:.utf8)!
    var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH))

    _ = digestData.withUnsafeMutableBytes {digestBytes in
        messageData.withUnsafeBytes {messageBytes in
            CC_MD5(messageBytes, CC_LONG(messageData.count), digestBytes)
        }
    }

    return digestData
}
Sergej D.
  • 25
  • 3
  • It is best to avoid using CryptoSwift, amoung other things it is 500 to 1000 times slower than Common Crypto based implementations. Apple's Common Crypto is FIPS certified and as such has been well vetted, using CryptoSwift is taking a chance on correctness and security such as timing and power attacks. – zaph Mar 11 '18 at 02:34
  • MD5 of "1234567z-äbc" using utf-8 of is: hex `935fe44e659beb5a3bb7a4564fba0513`. UTF for "ä" is hex bytes `C384`. MD5 is hex `11d8b9e9ff20d10a1925d3b5f15b6e6d`. Where did hex `9e224a41eeefa284df7bb0f26c2913e2` come from? Why use utf-16? When bytes are needed utf-8 is generally used. – zaph Mar 11 '18 at 02:50
  • Thanks, using utf-16 little endian was not my idea... I am developing a small app to control some of my lan devices via my home router (AVM FritzBox). Here's the documentation for AVM's challenge response process which requires utf-16 little endian: https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/Session-ID_english_06Feb18.pdf On a side node: I did use Apple's Common Crypto library. I imported it using a bridging header file (#import ). The above mentioned function "MD5" uses it. – Sergej D. Mar 12 '18 at 08:22

1 Answers1

1

This

let str = "1234567z" + "-" + "äbc"
let data = str.data(using: .utf16LittleEndian)!

already gives the UTF16LE data from which you want to compute the MD5 hash, there is no need to filter out 0-bytes or any other operations.

Instead, modify the function from How to convert string to MD5 hash using ios swift to take a Data argument instead of a String:

func MD5(messageData: Data) -> Data {
    var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH))
    _ = digestData.withUnsafeMutableBytes {digestBytes in
        messageData.withUnsafeBytes {messageBytes in
            CC_MD5(messageBytes, CC_LONG(messageData.count), digestBytes)
        }
    }
    return digestData
}

so that you can call it with the already-converted data:

let str = "1234567z" + "-" + "äbc"
let data = str.data(using: .utf16LittleEndian)!

let md5Data = MD5(messageData: data)
let md5Hex =  md5Data.map { String(format: "%02hhx", $0) }.joined()

print("md5Hex: \(md5Hex)")
// 9e224a41eeefa284df7bb0f26c2913e2
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Awesome! Thank you very much, especially for the explanation. – Sergej D. Mar 10 '18 at 22:17
  • @SergejD.: You are welcome! – (Note that you can *accept* an answer if it helped, by clicking on the check mark, compare https://stackoverflow.com/help/someone-answers.) – Martin R Mar 14 '18 at 07:56