Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Easy to use Swift implementation of CommonCrypto HMAC. You can easily hash your String to: md5, sha1, sha224, sha256, sha384, sha512 with pure Swift.
//
// HMAC.swift
//
// Created by Mihael Isaev on 21.04.15.
// Copyright (c) 2014 Mihael Isaev inc. All rights reserved.
//
// ***********************************************************
//
// How to import CommonCrypto in Swift project without Obj-c briging header
//
// To work around this create a directory called CommonCrypto in the root of the project using Finder.
// In this directory create a file name module.map and copy the following into the file.
// You will need to alter the paths to ensure they point to the headers on your system.
//
// module CommonCrypto [system] {
// header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
// export *
// }
// To make this module visible to Xcode, go to Build Settings, Swift Compiler – Search Paths
// and set Import Paths to point to the directory that contains the CommonCrypto directory.
//
// You should now be able to use import CommonCrypto in your Swift code.
//
// You have to set the Import Paths in every project that uses your framework so that Xcode can find it.
//
// ***********************************************************
//
import Foundation
import CommonCrypto
extension String {
var md5: String {
return HMAC.hash(self, algo: HMACAlgo.MD5)
}
var sha1: String {
return HMAC.hash(self, algo: HMACAlgo.SHA1)
}
var sha224: String {
return HMAC.hash(self, algo: HMACAlgo.SHA224)
}
var sha256: String {
return HMAC.hash(self, algo: HMACAlgo.SHA256)
}
var sha384: String {
return HMAC.hash(self, algo: HMACAlgo.SHA384)
}
var sha512: String {
return HMAC.hash(self, algo: HMACAlgo.SHA512)
}
}
public struct HMAC {
static func hash(inp: String, algo: HMACAlgo) -> String {
if let stringData = inp.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
return hexStringFromData(digest(stringData, algo: algo))
}
return ""
}
private static func digest(input : NSData, algo: HMACAlgo) -> NSData {
let digestLength = algo.digestLength()
var hash = [UInt8](count: digestLength, repeatedValue: 0)
switch algo {
case .MD5:
CC_MD5(input.bytes, UInt32(input.length), &hash)
break
case .SHA1:
CC_SHA1(input.bytes, UInt32(input.length), &hash)
break
case .SHA224:
CC_SHA224(input.bytes, UInt32(input.length), &hash)
break
case .SHA256:
CC_SHA256(input.bytes, UInt32(input.length), &hash)
break
case .SHA384:
CC_SHA384(input.bytes, UInt32(input.length), &hash)
break
case .SHA512:
CC_SHA512(input.bytes, UInt32(input.length), &hash)
break
}
return NSData(bytes: hash, length: digestLength)
}
private static func hexStringFromData(input: NSData) -> String {
var bytes = [UInt8](count: input.length, repeatedValue: 0)
input.getBytes(&bytes, length: input.length)
var hexString = ""
for byte in bytes {
hexString += String(format:"%02x", UInt8(byte))
}
return hexString
}
}
enum HMACAlgo {
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
func digestLength() -> Int {
var result: CInt = 0
switch self {
case .MD5:
result = CC_MD5_DIGEST_LENGTH
case .SHA1:
result = CC_SHA1_DIGEST_LENGTH
case .SHA224:
result = CC_SHA224_DIGEST_LENGTH
case .SHA256:
result = CC_SHA256_DIGEST_LENGTH
case .SHA384:
result = CC_SHA384_DIGEST_LENGTH
case .SHA512:
result = CC_SHA512_DIGEST_LENGTH
}
return Int(result)
}
}
@thbwd
Copy link

thbwd commented Sep 12, 2015

This is not pure Swift. You are calling C and Foundation APIs.

@kaishin
Copy link

kaishin commented Mar 8, 2016

@idmean yes, but the API is pure Swift at least.

@helje5
Copy link

helje5 commented Jun 22, 2016

Please adjust your tagline, this is not pure Swift.

@kutschenator
Copy link

kutschenator commented Jul 19, 2016

this is not hmac but just the hashing functions CCHmac is the correct C function to call

@inigo333
Copy link

inigo333 commented Feb 28, 2017

@commscheck
Copy link

commscheck commented Nov 1, 2017

@nabtron
Copy link

nabtron commented May 7, 2018

Full tutorial with example project in xcode 9 and swift 4: https://nabtron.com/commoncrypto-hmac-swift/

@adamwaite
Copy link

adamwaite commented Mar 6, 2019

Swift 4.2:

import Foundation
import CommonCrypto

extension String {
    
    var md5: String {
        return HMAC.hash(self, algo: .MD5)
    }
    
    var sha1: String {
        return HMAC.hash(self, algo: .SHA1)
    }
    
    var sha224: String {
        return HMAC.hash(self, algo: .SHA224)
    }
    
    var sha256: String {
        return HMAC.hash(self, algo: .SHA256)
    }
    
    var sha384: String {
        return HMAC.hash(self, algo: .SHA384)
    }
    
    var sha512: String {
        return HMAC.hash(self, algo: .SHA512)
    }
}

private struct HMAC {
    
    static func hash(_ inp: String, algo: HMACAlgo) -> String {
       
        if let stringData = inp.data(using: .utf8, allowLossyConversion: false) {
            
            return hexStringFromData(digest(stringData as NSData, algo: algo))
        }
        
        return ""
    }
    
    private static func digest(_ input: NSData, algo: HMACAlgo) -> NSData {
       
        let digestLength = algo.digestLength()
        var hash = [UInt8](repeating: 0, count: digestLength)
        switch algo {
        case .MD5: CC_MD5(input.bytes, UInt32(input.length), &hash)
        case .SHA1: CC_SHA1(input.bytes, UInt32(input.length), &hash)
        case .SHA224: CC_SHA224(input.bytes, UInt32(input.length), &hash)
        case .SHA256: CC_SHA256(input.bytes, UInt32(input.length), &hash)
        case .SHA384: CC_SHA384(input.bytes, UInt32(input.length), &hash)
        case .SHA512: CC_SHA512(input.bytes, UInt32(input.length), &hash)
        }
        return NSData(bytes: hash, length: digestLength)
    }
    
    private static func hexStringFromData(_ input: NSData) -> String {
       
        var bytes = [UInt8](repeating: 0, count: input.length)
        input.getBytes(&bytes, length: input.length)
        var hexString = ""
        for byte in bytes {
            hexString += String(format:"%02x", UInt8(byte))
        }
        return hexString
    }
}

private enum HMACAlgo {
    
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
    
    func digestLength() -> Int {
        
        var result: CInt = 0
        switch self {
        case .MD5: result = CC_MD5_DIGEST_LENGTH
        case .SHA1: result = CC_SHA1_DIGEST_LENGTH
        case .SHA224: result = CC_SHA224_DIGEST_LENGTH
        case .SHA256: result = CC_SHA256_DIGEST_LENGTH
        case .SHA384: result = CC_SHA384_DIGEST_LENGTH
        case .SHA512: result = CC_SHA512_DIGEST_LENGTH
        }
        return Int(result)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment