This question already has an answer here:
I'm trying to encrypt data to send to the API.
The API requires the data to be sent as hmac_sha512
encrypted hash.
I've found various examples of how it possibly could have been done for sha1
and others (not sha512
) and also in older versions of Swift.
None of the examples that I tried work for swift 3.1
Any help in the right direction will be appreciated.
Edit:
In PHP, I successfully send it using:
$sign = hash_hmac('sha512', $post_data, $this->secret);
Edit 2:
I did add briding header
, I don't know what to do next! As the code examples followed after that don't work for swift 3.1 :(
Edit 3:
Solved! Guess what, I was creating briding header incorrectly! :(
P.S I'm trying to avoid CryptoSwift, focusing on CommonCrypto.
The answer given below is not proper, as it doesn't allow hmac to get a key for encryption. I did research and finally got it working. This post contains the working example project for hmac: https://github.com/nabtron/hmacTest
I think the best thing to do is using Crypto pod which is a wrapper for common crypto. In case you want to use directly commonCrypto you should add the bridging header to the project and import common crypto using: #import <CommonCrypto/CommonCrypto.h>
Edit 1
Create a swift class and add the following code to it:
import Foundation extension String { var md5: String { return HMAC.hash(inp: self, algo: HMACAlgo.MD5) } var sha1: String { return HMAC.hash(inp: self, algo: HMACAlgo.SHA1) } var sha224: String { return HMAC.hash(inp: self, algo: HMACAlgo.SHA224) } var sha256: String { return HMAC.hash(inp: self, algo: HMACAlgo.SHA256) } var sha384: String { return HMAC.hash(inp: self, algo: HMACAlgo.SHA384) } var sha512: String { return HMAC.hash(inp: self, algo: HMACAlgo.SHA512) } } public struct HMAC { static func hash(inp: String, algo: HMACAlgo) -> String { if let stringData = inp.data(using: String.Encoding.utf8, allowLossyConversion: false) { return hexStringFromData(input: digest(input: 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) 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](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 } } 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) } }
then use it simply by stringName.sha512
this class extends the String class which gives the ability to use the hashing as a function in the string class.