快速实现HMAC和SHA1encryption

我相对较新的Swift,我卡住encryption使用HMAC和SHA1。 我发现以下回答https://stackoverflow.com/a/24411522/4188344,但我不能解决如何正确实施。 任何帮助将是惊人的。

问题解决了! 首先,我没有正确使用string函数…我结束了这个:

  let hmacResult:String = "myStringToHMAC".hmac(HMACAlgorithm.SHA1, key: "myKey") 

然后我忘了我需要base64编码hmac结果。 所以我修改了我的问题链接的string函数…

 enum HMACAlgorithm { case MD5, SHA1, SHA224, SHA256, SHA384, SHA512 func toCCHmacAlgorithm() -> 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) } 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) } } extension String { func hmac(algorithm: HMACAlgorithm, key: String) -> String { let cKey = key.cStringUsingEncoding(NSUTF8StringEncoding) let cData = self.cStringUsingEncoding(NSUTF8StringEncoding) var result = [CUnsignedChar](count: Int(algorithm.digestLength()), repeatedValue: 0) CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, strlen(cKey!), cData!, strlen(cData!), &result) var hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength()))) var hmacBase64 = hmacData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding76CharacterLineLength) return String(hmacBase64) } } 

这是给我正确的结果

 lGCtbW+DNHFraNoxPGK3trgM/98= 

这里是@David Wood的解决scheme更新了Swift 3:

 enum HMACAlgorithm { case MD5, SHA1, SHA224, SHA256, SHA384, SHA512 func toCCHmacAlgorithm() -> 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) } 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) } } extension String { func hmac(algorithm: HMACAlgorithm, key: String) -> String { let cKey = key.cString(using: String.Encoding.utf8) let cData = self.cString(using: String.Encoding.utf8) var result = [CUnsignedChar](repeating: 0, count: Int(algorithm.digestLength())) CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, Int(strlen(cKey!)), cData!, Int(strlen(cData!)), &result) let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength()))) let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength76Characters) return String(hmacBase64) } } // usage: let hmacResult: String = "myStringToHMAC".hmac(algorithm: HMACAlgorithm.SHA1, key: "foo") 

我已经使用这个模块,我添加到我的项目作为一个框架:

https://github.com/CryptoCoinSwift/SHA256-Swift

而且我还向SHA256.swift添加了以下String扩展名:

 public extension String { func sha256(key: String) -> String { let inputData: NSData = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! let keyData: NSData = key.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! let algorithm = HMACAlgorithm.SHA256 let digestLen = algorithm.digestLength() let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen) CCHmac(algorithm.toCCEnum(), keyData.bytes, UInt(keyData.length), inputData.bytes, UInt(inputData.length), result) let data = NSData(bytes: result, length: digestLen) result.destroy() return data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength) } } 

通过这种方式从String生成base64编码签名可以这样完成:

 let signature: String = "\(payload)".sha256(secretKey) 

如果您想以hex格式获得相同的结果,则可以使用以下扩展名:

 extension String { func hmac(algorithm: HMACAlgorithm, key: String) -> String { let cKey = key.cStringUsingEncoding(NSUTF8StringEncoding) let cData = self.cStringUsingEncoding(NSUTF8StringEncoding) var result = [CUnsignedChar](count: Int(algorithm.digestLength()), repeatedValue: 0) let length : Int = Int(strlen(cKey!)) let data : Int = Int(strlen(cData!)) CCHmac(algorithm.toCCHmacAlgorithm(), cKey!,length , cData!, data, &result) let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength()))) var bytes = [UInt8](count: hmacData.length, repeatedValue: 0) hmacData.getBytes(&bytes, length: hmacData.length) var hexString = "" for byte in bytes { hexString += String(format:"%02hhx", UInt8(byte)) } return hexString } } 

我已经检查了上面的答案,发现它太冗长了。

解决scheme :我得到了第三方: IDZSwiftCommonCrypto

使用pod: pod 'IDZSwiftCommonCrypto'

并使用以下function来实现所需的输出:

 func getHMacSHA1(forMessage message: String, key: String) -> String? { let hMacVal = HMAC(algorithm: HMAC.Algorithm.sha1, key: key).update(string: message)?.final() if let encryptedData = hMacVal { let decData = NSData(bytes: encryptedData, length: Int(encryptedData.count)) let base64String = decData.base64EncodedString(options: .lineLength64Characters) print("base64String: \(base64String)") return base64String } else { return nil } } 

检查结果使用以下网站:

https://hash.online-convert.com/sha1-generator

在Swift 4.0中testing