前言: app 中经常遇到把用户信息保存到本地文件中的需求,然而如果手机越狱通过砸壳,那么这些文件就会完全暴露。所以需要对这些内容进行加密。(本文参考: https://www.jianshu.com/p/6348210aeeb7)
DEMO地址:https://github.com/gree180160/KeyChainDemo
工具定义:
importFoundation
importCommonCrypto
public struct KeychainWrapper {
private static let keyChain = "hjjjjjjjjjeevvooll@#$%^&*()"
private static let iv = ""
/**
3DES的加密过程 和 解密过程
- parameter op: CCOperation: 加密还是解密
CCOperation(kCCEncrypt)加密
CCOperation(kCCDecrypt) 解密
- parameter key: 专有的key,一个钥匙一般
- parameter iv: 可选的初始化向量,可以为nil
- returns : 返回加密或解密的参数
*/
private static func threeDESEncryptOrDecrypt(op: CCOperation, sourceString: String?) -> String? {
guardsourceString!=nilelse{
returnnil
}
// Key
let keyData: NSData = ((keyChain as NSString).data(using: String.Encoding.utf8.rawValue) as NSData?)!
letkeyBytes =UnsafeMutableRawPointer(mutating: keyData.bytes)
// 加密或解密的内容
vardata:NSData=NSData()
if op == CCOperation(kCCEncrypt) {
data = ((sourceString!asNSString).data(using:String.Encoding.utf8.rawValue)asNSData?)!
}
else{
data = NSData(base64Encoded: sourceString!, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters)!
}
letdataLength =size_t(data.length)
letdataBytes =UnsafeMutableRawPointer(mutating: data.bytes)
// 返回数据
letcryptData =NSMutableData(length:Int(dataLength)+kCCBlockSize3DES)
let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes)
letcryptLength =size_t(cryptData!.length)
// 可选 的初始化向量
let viData :NSData = ((iv as NSString).data(using: String.Encoding.utf8.rawValue) as NSData?)!
letviDataBytes =UnsafeMutableRawPointer(mutating: viData.bytes)
// 特定的几个参数
letkeyLength =size_t(kCCKeySize3DES)
letoperation:CCOperation=UInt32(op)
letalgoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
letoptions: CCOptions =UInt32(kCCOptionPKCS7Padding)
varnumBytesCrypted :size_t=0
letcryptStatus =CCCrypt(operation,// 加密还是解密
algoritm,// 算法类型
options, // 密码块的设置选项
keyBytes,// 秘钥的字节
keyLength,// 秘钥的长度
viDataBytes,// 可选初始化向量的字节
dataBytes,// 加解密内容的字节
dataLength,// 加解密内容的长度
cryptPointer,// output data buffer
cryptLength, // output data length available
&numBytesCrypted)// real output data length
ifUInt32(cryptStatus)==UInt32(kCCSuccess) {
cryptData!.length=Int(numBytesCrypted)
if op == CCOperation(kCCEncrypt) {
letbase64cryptString = cryptData?.base64EncodedString(options: .lineLength64Characters)
returnbase64cryptString
}
else{
letbase64cryptString =String(data: cryptData!asData, encoding:String.Encoding(rawValue:String.Encoding.utf8.rawValue))
returnbase64cryptString
}
}else{
returnnil
}
}
static func threeDESEncrypt(sourceString: String?) -> String? {
threeDESEncryptOrDecrypt(op: CCOperation(kCCEncrypt), sourceString: sourceString)
}
static func threeDESDecrypt(decryptStr: String?) -> String? {
threeDESEncryptOrDecrypt(op: CCOperation(kCCDecrypt), sourceString: decryptStr)
}
}
使用:
func testCrypt() {
letsourceStr ="hello swift"
letdecrypStr =KeychainWrapper.threeDESEncrypt(sourceString: sourceStr)
letresult =KeychainWrapper.threeDESDecrypt(decryptStr: decrypStr)
ifresult==sourceStr {
print("success")
}else{
print("fail")
}
}