Paul Calnan's Blog
Published May 13, 2020

Computing cryptographic hashes in Swift has gotten easier in recent times. Prior to Xcode 10, it used to be difficult to import the CommonCrypto library which did the computation. Xcode 10 added a module for that library, making it easier to do the import. But the API still looks like a C API. Using the library directly requires you to write something like this:

import CommonCrypto
import Foundation

// Compute the digest of this string:
let messageString = "The quick brown fox jumps over the lazy dog"

// Convert the string to a byte array.
let messageData = Data(messageString.utf8)

// Compute the hash using CommonCrypto.
var digestData = Data(count: Int(CC_SHA224_DIGEST_LENGTH))
digestData.withUnsafeMutableBytes { (digestBuffer: UnsafeMutableRawBufferPointer) -> Void in
    messageData.withUnsafeBytes { (messageBuffer: UnsafeRawBufferPointer) -> Void in
        _ = CC_SHA224(messageBuffer.baseAddress,
                      CC_LONG(messageBuffer.count),
                      digestBuffer.baseAddress?.assumingMemoryBound(to: UInt8.self))
    }
}

// Convert the digestData byte buffer into a hex string.
let digestString = digestData.map { String(format: "%02hhx", $0) }.joined()

// prints 730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525
print(digestString)

That's a fair amount of boilerplate to accomplish this. Also, the meat of that code — the withUnsafeMutableBytes and withUnsafeBytes — changed between Swift versions.

Rather than deal with that in production code, I wrote a small Swift library called HashAlgorithm to simplify the process.

Using it is pretty simple. Instead of the code above, you just do this:

import Foundation
import HashAlgorithm

// Compute the digest of this string:
let messageString = "The quick brown fox jumps over the lazy dog"
let digest = HashAlgorithm.SHA224.digest(messageString)

// prints 730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525
print(digest)

It supports all of the (non-deprecated) cryptographic hash algorithms currently provided by CommonCrypto: SHA1, SHA224, SHA256, SHA384, and SHA512.

The library is available on Github.