Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CommonHMAC in Swift

I'm trying to create a HMAC SHA-1 hash of a string in Swift but can't figure out how to interact with the APIs as it doesn't seem to be importing the CommonCrypto framework. I've tried various different forms of "import CommonCrypto" and creating a bridging header file but none of it made a difference.

The odd thing is that if I create an Objective-C class, I'm able to interact with APIs without any problems, so this seems to be unique to Swift.

Also if anyone could tell me what the equivalent of uint8_t digest[CC_SHA1_DIGEST_LENGTH] is in Swift I'd be very grateful

like image 287
Matt Donnelly Avatar asked Jun 07 '14 16:06

Matt Donnelly


2 Answers

You can do it in Swift. Just make sure you add #import <CommonCrypto/CommonHMAC.h> to the bridging Objective-C bridging header.

Update: For Swift 4 see a much better solution using the Swift Package Manager here: https://github.com/jernejstrasner/SwiftCrypto

enum CryptoAlgorithm {     case MD5, SHA1, SHA224, SHA256, SHA384, SHA512      var HMACAlgorithm: CCHmacAlgorithm {         var result: Int = 0         switch self {         case .MD5:      result = kCCHmacAlgMD5         case .SHA1:     result = kCCHmacAlgSHA1         case .SHA224:   result = kCCHmacAlgSHA224         case .SHA256:   result = kCCHmacAlgSHA256         case .SHA384:   result = kCCHmacAlgSHA384         case .SHA512:   result = kCCHmacAlgSHA512         }         return CCHmacAlgorithm(result)     }      var digestLength: Int {         var result: Int32 = 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)     } }  extension String {      func hmac(algorithm: CryptoAlgorithm, key: String) -> String {         let str = self.cStringUsingEncoding(NSUTF8StringEncoding)         let strLen = Int(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))         let digestLen = algorithm.digestLength         let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)         let keyStr = key.cStringUsingEncoding(NSUTF8StringEncoding)         let keyLen = Int(key.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))          CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)          let digest = stringFromResult(result, length: digestLen)          result.dealloc(digestLen)          return digest     }      private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {         var hash = NSMutableString()         for i in 0..<length {             hash.appendFormat("%02x", result[i])         }         return String(hash)     }  } 
like image 121
Jernej Strasner Avatar answered Sep 17 '22 08:09

Jernej Strasner


Try this for Swift 3.1 :

enum CryptoAlgorithm {     case MD5, SHA1, SHA224, SHA256, SHA384, SHA512      var HMACAlgorithm: CCHmacAlgorithm {         var result: Int = 0         switch self {         case .MD5:      result = kCCHmacAlgMD5         case .SHA1:     result = kCCHmacAlgSHA1         case .SHA224:   result = kCCHmacAlgSHA224         case .SHA256:   result = kCCHmacAlgSHA256         case .SHA384:   result = kCCHmacAlgSHA384         case .SHA512:   result = kCCHmacAlgSHA512         }         return CCHmacAlgorithm(result)     }      var digestLength: Int {         var result: Int32 = 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)     } }  extension String {      func hmac(algorithm: CryptoAlgorithm, key: String) -> String {         let str = self.cString(using: String.Encoding.utf8)         let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))         let digestLen = algorithm.digestLength         let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)         let keyStr = key.cString(using: String.Encoding.utf8)         let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))          CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)          let digest = stringFromResult(result: result, length: digestLen)          result.deallocate(capacity: digestLen)          return digest     }      private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {         let hash = NSMutableString()         for i in 0..<length {             hash.appendFormat("%02x", result[i])         }         return String(hash)     }  } 

Don't forget add #import <CommonCrypto/CommonHMAC.h> to Header.h

like image 39
reza_khalafi Avatar answered Sep 17 '22 08:09

reza_khalafi