項目中需要用到3DES加密,進行與后臺的接口數據交互。因為加密傳參的過程是,先將字典類型的參數轉換為JSONstring,所以將3DES加密擴展到string類型里面,調用的時候方便
extension String{
//3des加解密
func threeDESEncryptOrDecrypt(op: Int) -> String? {
//op傳1位加密,0為解密
//CCOperation(kCCEncrypt)加密 1
//CCOperation(kCCDecrypt) 解密 0
var ccop = CCOperation()
let key = "跟后臺同志商量好的加密串"
let iv = "偏移量"
// Key
let keyData: NSData = (key as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
let keyBytes = UnsafeRawPointer(keyData.bytes)
// 加密或解密的內容
var data: NSData = NSData()
if op == 1 {
ccop = CCOperation(kCCEncrypt)
data = (self as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
}
else {
ccop = CCOperation(kCCDecrypt)
data = NSData(base64Encoded: self, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)!
}
let dataLength = size_t(data.length)
let dataBytes = UnsafeRawPointer(data.bytes)
// 返回數據
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes)
let cryptLength = size_t(cryptData!.length)
// 可選 的初始化向量
let viData :NSData = (iv as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
let viDataBytes = UnsafeRawPointer(viData.bytes)
// 特定的幾個參數
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(ccop)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
var numBytesCrypted :size_t = 0
let cryptStatus = CCCrypt(operation, // 加密還是解密
algoritm, // 算法類型
options, // 密碼塊的設置選項
keyBytes, // 秘鑰的字節
keyLength, // 秘鑰的長度
viDataBytes, // 可選初始化向量的字節
dataBytes, // 加解密內容的字節
dataLength, // 加解密內容的長度
cryptPointer, // output data buffer
cryptLength, // output data length available
&numBytesCrypted) // real output data length
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData!.length = Int(numBytesCrypted)
if op == 1 {
let base64cryptString = cryptData!.base64EncodedString(options: .lineLength64Characters)
//返回加密的數據
return base64cryptString
}
else {
let base64cryptString = NSString(data: cryptData! as Data, encoding: String.Encoding.utf8.rawValue) as String?
//返回解密的數據
return base64cryptString
}
} else {
print("Error: \(cryptStatus)")
}
return nil
}
}
//字典轉換為jsonString
func getJsonStringFromDictionary(dictionary:NSDictionary) -> String {
if (!JSONSerialization.isValidJSONObject(dictionary)) {
print("無法解析出JSONString")
return ""
}
let data : NSData! = try? JSONSerialization.data(withJSONObject: dictionary, options: []) as NSData!
let JSONString = String(data: data as Data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
return JSONString!
}
在開始調用之前有一點需要跟大家交代一下,轉為3DES加密串之后傳給后臺或者接口后臺返回參數的時候是base64位的,base64進行http請求的時候不能識別"/"、"+"、"="等特殊字符,需要轉換一下
extension String{
//向后臺傳值的時候
func urlBase64EncodedString() -> String {
let first = self.replacingOccurrences(of: "/", with: "_")
let second = first.replacingOccurrences(of: "+", with: "-")
let third = second.replacingOccurrences(of: "=", with: "")
return third
}
//接收后臺返回的值的時候
func urlBase64DecodedString() -> String {
let first = NSMutableString(string: self)
let mod4:Int = first.length % 4
print(first.length)
if(mod4>0){
var str = "===="
let start1 = str.index(str.startIndex, offsetBy: 0)
str = str.substring(from: start1)
let end1 = str.index(str.startIndex, offsetBy: 4-mod4)
let sub5 = str.substring(to: end1)
first.append(sub5)
}
let second = first.replacingOccurrences(of: "_", with: "/")
let third = second.replacingOccurrences(of: "-", with: "+")
return third
}
}
最后調用后臺接口傳參的時候只需要將參數字典轉化為jsonString,然后調用加密方法,賦值給后臺規定的加密參數就可以了
var params:[String:Any] = [:]
let paramsString = getJsonStringFromDictionary(dictionary: paramsDic as NSDictionary)
params["parameter"] = paramsString.threeDESEncryptOrDecrypt(op: 1)!.urlBase64EncodedString()
解密后臺接口返回的數據并轉為字典類型
extension String{
//解密加轉換字典
func toDecryptJsonDic() -> [String:Any]{
let decryptJsonString = self.urlBase64DecodedString().threeDESEncryptOrDecrypt(op: 0)
let decryptJsonDic = decryptJsonString?.toDictionary()
if decryptJsonDic != nil {
return decryptJsonDic!
}
return [String:Any].init()
}
}
使用方式
返回值(jsonString). toDecryptJsonDic()