【实践】Swift3 封装加密工具类CryptoHelper
2017-05-16 本文已影响65人
SmartisanBool
使用OC的CommonCrypto库完成对swift的加密/解密工具类的封装。支持散列哈希(MD5, SHA1, SHA224, SHA256, SHA384, SHA512)及AES加密
1.引入CommonCrypto库
#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
2.创建CryptoAlgorithm枚举
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)
}
}
3.创建String扩展
extension String{
var md5 : String!{
let str = self.cString(using: String.Encoding.utf8)
let strLen = CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8))
let digestLen = Int(CC_MD5_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
CC_MD5(str!, strLen, result)
return stringFromBytes(bytes: result, length: digestLen)
}
var sha1: String! {
let str = self.cString(using: String.Encoding.utf8)
let strLen = CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8))
let digestLen = Int(CC_SHA1_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
CC_SHA1(str!, strLen, result)
return stringFromBytes(bytes: result, length: digestLen)
}
var sha256String: String! {
let str = self.cString(using: String.Encoding.utf8)
let strLen = CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8))
let digestLen = Int(CC_SHA256_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
CC_SHA256(str!, strLen, result)
return stringFromBytes(bytes: result, length: digestLen)
}
var sha512String: String! {
let str = self.cString(using: String.Encoding.utf8)
let strLen = CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8))
let digestLen = Int(CC_SHA512_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
CC_SHA512(str!, strLen, result)
return stringFromBytes(bytes: result, length: digestLen)
}
func stringFromBytes(bytes: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String{
let hash = NSMutableString()
for i in 0..<length {
hash.appendFormat("%02x", bytes[i])
}
bytes.deallocate(capacity: length)
return String(format: hash as String)
}
//HMAC 加密
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)
}
//AES 加密
func aes(operation: CCOperation,key: String) -> String{
let keyData = key.data(using: String.Encoding.utf8)! as NSData
let keyLen = Int(kCCKeySizeAES128)
let keyBytes = keyData.bytes
let strData = self.data(using: String.Encoding.utf8)! as NSData
let dataLen = strData.length
let dataBytes = strData.bytes
let cryptLength = Int(dataLen + kCCBlockSizeAES128)
let cryptPointer = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: cryptLength)
let algoritm = CCAlgorithm(kCCAlgorithmAES128)
let option = CCOptions(kCCOptionPKCS7Padding|kCCOptionECBMode)
let numBytesEncrypted = UnsafeMutablePointer<Int>.allocate(capacity: 1)
numBytesEncrypted.initialize(to: 1)
let cryptStatus = CCCrypt(operation, algoritm, option, keyBytes, keyLen, nil, dataBytes, dataLen, cryptPointer, cryptLength, numBytesEncrypted)
if CCStatus(cryptStatus) == CCStatus(kCCSuccess){
let len = Int(numBytesEncrypted.pointee)
let digest = stringFromResult(result: cryptPointer, length: len)
numBytesEncrypted.deallocate(capacity: 1)
return digest
}else{
return ""
}
}
}
3.测试
let str = "cyfhaha"
let aesResult = "814514553e4bc8f7ca3edf9341e81c49"
ALinLog("---------:\(str.hmac(algorithm: .SHA1, key: "chengyanfang"))")
ALinLog("---------:\(str.sha1)")
ALinLog("---------:\(str.aes(operation: CCOperation(kCCEncrypt), key: "chengyanfang"))")
ALinLog("---------:\(aesResult.aes(operation: CCOperation(kCCDecrypt), key: "chengyanfang"))")
打印结果:
---------:c792b6aac08880924ece052105cf06d1117789a9
---------:3506bc4ecb80abf331b28b0bf18b35aadebe6518
---------:814514553e4bc8f7ca3edf9341e81c49
---------:cyfhaha