快速实现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
- 在Swift中导入和查询SQLite数据库 – iOS
- POST和SWIFT和API
- 使用AVCaptureAudioDataOutputSampleDelegate无法播放通过语音录制的audio
- UITextView使用swift自动滚动(IOS应用程序)
- 无法将types'UInt'的值转换为期望的参数types'UnsafeMutablePointer <UInt>'
- 如何为UIBarButtonItem设置标题?
- 从UIImage / CGImage中以数组forms获取像素数据
- Google SignIn:无法断开iOS应用
- Swift:将genericstypes转换为相同的genericstypes,但使用相关types的子类