3

i dont even expect this problem, but it appears. I try to get md5 hash from string in swift. I search about that on SO and assume that i need to import library like that:

#import <CommonCrypto/CommonCrypto.h>

First of all compiler said that '#' is not okay. Then i removed and compiler said that '<' is not okay. I tried to figure out that and find recommendations to add folder named "CommonCrypto" and create a file named "module.map". I cant understand how to create file with this extension. Okay, i create swift file and replace its extension. Then write code there:

module CommonCrypto [system] {
    header "/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}

and again its not okay Then in recommendations was adding the new module to Import Paths under Swift Compiler – Search Paths in your project settings ${SRCROOT}/CommonCrypto).

and its again not okay.

i cant belive that its so difficult to do that. i think i misunderstand some steps or something. if you know step by step answer please help))

Mike
  • 185
  • 1
  • 2
  • 13
  • 2
    Did you put it in your bridging header? – Kametrixom Aug 12 '15 at 11:48
  • possible duplicate of [How to use CC\_MD5 method in swift language.](http://stackoverflow.com/questions/24123518/how-to-use-cc-md5-method-in-swift-language) – vadian Aug 12 '15 at 11:52
  • I prefer this native implementation: https://github.com/krzyzanowskim/CryptoSwift – Logan Aug 12 '15 at 14:32
  • @Logan Note that the CryptoSwift version is more than 500 times slower than the Common Crypto version. – zaph Aug 12 '15 at 15:16
  • @zaph good to know! Never profiled it. – Logan Aug 12 '15 at 15:50
  • @zaph well.. that's not true, unless you think about debug build. – Marcin Sep 30 '15 at 00:15
  • @Marcin As you are aware I have done timings with release optimizations, perhaps I made an error, if so please provide the correct figure and add it to the project ReadMe. Better yet provide benchmark figures. Just saying it is incorrect without a figure is meaningless. Without that information available developers are making a choice blindly and probably with incorrect performance assumptions. Common Crypto uses the hardware crypto engine build into the iOS device so it is substantially faster. – zaph Sep 30 '15 at 11:24
  • @zaph well.. discussion was specifically about AES algorithm AFAIR, and there are reasons for that with the current algoritms, anyway it changing. We don't know that Common Crypto uses because it is not open source when it comes to crypto algorithms implementation. Though, for Xcode usage issues if you have any, there is better place to discuss than comments here. – Marcin Sep 30 '15 at 13:16
  • @Marcin In the [Issues section](https://github.com/krzyzanowskim/CryptoSwift/issues/30) of the GitHub project I also posted SHA256 timings that were over 500+ times slower. Now for the good news, I ran SHA256 and MD5 with Swift 2 on an iPhone 6s (Fast [-O], CocoaPods). MD5 is substantially better, only 5.8 times slower on 1MB data, SHA256 was also better at 445 times slower. Add benchmarks against Common Crypto (The gold standard) to the ReadMe for transparency. RE: "better place to discuss" You replied to my comment so this is the proper place. – zaph Sep 30 '15 at 14:29
  • 1
    @zaph as I said, you were wrong with number 500, then you started about something else in general trying to prove me something, but you don’t have to really, you already know my response. I hoped for your contribution since then. There is a way to improve performance, but need hands to do actual work to accomplish that. I bet it's better way of spend time than this discussion here. Regards. – Marcin Oct 01 '15 at 11:34
  • If you want a home grown implementation in Swift, then https://github.com/onmyway133/SwiftHash – onmyway133 Jul 02 '16 at 17:10

2 Answers2

7

You need to add a bridging header and add the #import <CommonCrypto/CommonCrypto.h> statement to it.

The easiest way to add a bridging header is to add an Objective-C file to the project, you will be aked ig you want to add a bridging header, reply yes. After that you can delete the Objective-C file file that was added.

Example code:

func md5(#string: String) -> NSData {
    var digest = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))!
    if let data :NSData = string.dataUsingEncoding(NSUTF8StringEncoding) {
        CC_MD5(data.bytes, CC_LONG(data.length),
            UnsafeMutablePointer<UInt8>(digest.mutableBytes))
    }
    return digest
}

//Test:
let digest = md5(string:"Here is the test string")
println("digest: \(digest)")

Output:

digest: 8f833933 03a151ea 33bf6e3e bbc28594

Here is a more Swift 2.0 version returning an array of UInt8:

func md5(string string: String) -> [UInt8] {
    var digest = [UInt8](count: Int(CC_MD5_DIGEST_LENGTH), repeatedValue: 0)
    if let data = string.dataUsingEncoding(NSUTF8StringEncoding) {
        CC_MD5(data.bytes, CC_LONG(data.length), &digest)
    }

    return digest
}
zaph
  • 111,848
  • 21
  • 189
  • 228
0

A solution for Swift 4.1:

import CommonCrypto

extension Data
{
    func md5() -> Data
    {
        var digest = Data(count: Int(CC_MD5_DIGEST_LENGTH))

        self.withUnsafeBytes { (bytes : UnsafePointer<UInt8>) -> Void in
            digest.withUnsafeMutableBytes { (mutableBytes : UnsafeMutablePointer<UInt8>) -> Void in
                CC_MD5(bytes, CC_LONG(self.count), mutableBytes)
            }
        }

        return digest
    }
}

See Importing CommonCrypto in a Swift framework for the CommonCrypto part.

jjrscott
  • 1,386
  • 12
  • 16