★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10346852.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
本文将演示如何编写原生的3DES加密和解密程序。
首先创建一个桥接头文件,因为需要使用到OC语言的通用加密解密类库。
在项目文件夹【DemoApp】上点击鼠标右键,弹出右键菜单。
【New File】->【Header File】->【Next】->
【Save As】:Header.h->【Create】
在该文件中,添加需要引用到的框架。
1 //添加需要引用到的框架。 2 #ifndef Header_h 3 #define Header_h 4 5 #import <CommonCrypto/CommonCrypto.h> 6 #import "SecurityUtil.h" 7 8 #endif /* Header_h */
点击项目名称【DemoApp】,显示项目的属性信息,
将头文件添加到桥接头选项中->【Build Settings】
->在搜索框内,输入需要定位的设置项目的名称:【Objective-C Bridging Hader】
->鼠标双击选项右侧【Objective-C Bridging Hader】,弹出桥接头文件设置窗口。
->在打开的输入窗口中,输入刚刚创建的头文件的相对路径:【DemoApp/Header.h】
在项目导航区,打开视图控制器的代码文件【ViewController.swift】
现在开始编写代码,实现3DES的加密和解密功能。
1 import UIKit 2 3 //首先创建一个集合,用来生成随机的公用的密钥 4 private let randomStringArray: [Character] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".map({$0}) 5 6 class ViewController: UIViewController { 7 8 //给类添加一个字符串属性, 9 //作为加密解密的公钥和私钥, 10 //并对其进行初始化操作。 11 var key:String = "" 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 // Do any additional setup after loading the view, typically from a nib. 16 //调用方法 17 encrypt(encryptData: "https://www.cnblogs.com/strengthen/") 18 } 19 20 //添加一个方法,用来生成指定长度的字符串 21 func randomStringOfLength(_ length:Int) -> String 22 { 23 //初始化一个字符串变量 24 var string = "" 25 //添加一个指定次数的循环语句 26 ////往字符串变量中添加随机的字符 27 for _ in (1...length) 28 { 29 //从集合中获得英文大小写字母和0~9之间的随机数字, 30 //并将随机字符添加到字符串中。 31 string.append(randomStringArray[Int(arc4random_uniform(UInt32(randomStringArray.count) - 1))]) 32 } 33 //返回生成的随机字符串 34 return string 35 } 36 37 //添加一个方法,对字符串参数进行加密 38 func encrypt(encryptData:String) 39 { 40 //生成一个随机的字符串,作为加密解密的密钥。 41 //其参数的值是24, 42 //因此这里将生成一个长度为24的,包含英文大小写字母和数字的随机字符串。 43 key = randomStringOfLength(kCCKeySize3DES) 44 //将待加密的字符串,转换成指定编码的数据类型。 45 let inputData : Data = encryptData.data(using: String.Encoding.utf8)! 46 //将随机字符串的密钥,同样转换成数据类型。 47 let keyData: Data = key.data(using: String.Encoding.utf8, allowLossyConversion: false)! 48 //创建一个非安全的可变原始指针, 49 //在创建该指针时,向系统申请了个数为密钥字节数的内存。 50 let keyBytes = UnsafeMutableRawPointer(mutating: (keyData as NSData).bytes) 51 //创建一个常量,表示密钥的长度,它的值是24 52 let keyLength = size_t(kCCKeySize3DES) 53 //获得待加密的数据类型对象的长度。 54 let dataLength = Int(inputData.count) 55 //创建一个非安全的指针,并从系统中分配相应的内存,作为加密的输入缓存。 56 let dataBytes = UnsafeRawPointer((inputData as NSData).bytes) 57 //创建一个指定长度的可变二进制数据对象, 58 //该对象作为加密的输出缓存,用来存储加密后的数据。 59 //其长度为输入缓存的长度和块大小的和,块的大小为8。 60 let bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)! 61 //创建一个非安全的可变指针,并根据输出缓存的大小,分配相应的内存。 62 let bufferPointer = UnsafeMutableRawPointer(bufferData.mutableBytes) 63 //获得输出缓存的长度。 64 let bufferLength = size_t(bufferData.length) 65 //创建一个变量,用来存储加密后的输出缓存的最终字节数。 66 var bytesDecrypted = Int(0) 67 68 //调用来自头文件中的加密解密方法, 69 //参数1:用来区分加密或解密,这里选择加密 70 //参数2:加密的算法 71 //参数3:使用密钥和算法,对文本进行加密时的方法。 72 let cryptStatus = CCCrypt(UInt32(kCCEncrypt), UInt32(kCCAlgorithm3DES), 73 UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding), 74 keyBytes, keyLength, nil, dataBytes, dataLength, 75 bufferPointer, bufferLength, &bytesDecrypted) 76 77 //当执行完加密方法后,会返回一个状态,通过对状态的检测, 78 //可以判断加密操作是否成功, 79 //加密操作有可能返回七种状态。 80 if Int32(cryptStatus) == Int32(kCCSuccess) 81 { 82 //当判断加密操作正确后,设置输出数据的长度, 83 //以调整输出缓存的大小。为最终输出的加密数据的长度。 84 bufferData.length = bytesDecrypted 85 86 //在控制台输出日志 87 print(bufferData) 88 //对加密后的数据进行解密。 89 decrypt(inputData: bufferData as Data) 90 } 91 else 92 { 93 print("Error:\(cryptStatus)") 94 } 95 } 96 97 //添加一个方法,用来实现指定类型的解密操作。 98 //解密的代码和加密的代码大致相同 99 func decrypt(inputData : Data) 100 { 101 //将作为随机字符串的密钥,转换成数据类型 102 let keyData: Data = key.data(using: String.Encoding.utf8, allowLossyConversion: false)! 103 //创建一个非安全的可变原始指针, 104 //在创建该指针时,向系统申请了个数为密钥字节数的内存。 105 let keyBytes = UnsafeMutableRawPointer(mutating: (keyData as NSData).bytes) 106 //创建一个常量,表示密钥的长度,它的值是 24 107 let keyLength = size_t(kCCKeySize3DES) 108 //获得待加密数据类型对象的长度 109 let dataLength = Int(inputData.count) 110 //创建一个非安全的指针,并从系统中分配相应的内存,作为解密的输入缓存。 111 let dataBytes = UnsafeRawPointer((inputData as NSData).bytes) 112 //创建一个指定长度的可变二进制数据对象, 113 //该对象作为解密的输出缓存,用来存储解密后的数据。 114 //其长度为输入缓存的长度和块大小的和,块的大小为8。 115 let bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)! 116 //创建一个非安全的可变指针,并根据输出缓存的大小,分配相应的内存。 117 let bufferPointer = UnsafeMutableRawPointer(bufferData.mutableBytes) 118 //获得输出缓存的长度 119 let bufferLength = size_t(bufferData.length) 120 //创建一个变量,用来存储解密后的输出缓存的最终字节数。 121 var bytesDecrypted = Int(0) 122 123 //调用来自头文件中的加密解密方法, 124 //参数1:用来区分加密或解密,这里选择解密 125 //参数2:解密的算法 126 //参数3:使用密钥和算法,对文本进行解密时的方法。 127 let cryptStatus = CCCrypt(UInt32(kCCDecrypt), UInt32(kCCAlgorithm3DES), 128 UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding), 129 keyBytes, keyLength, nil, dataBytes, dataLength, 130 bufferPointer, bufferLength, &bytesDecrypted) 131 132 //当执行完加密方法后,会返回一个状态,通过对状态的检测, 133 //可以判断解密操作是否成功, 134 if Int32(cryptStatus) == Int32(kCCSuccess) 135 { 136 //当判断解密操作正确后,设置输出数据的长度, 137 //以调整输出缓存的大小。为最终输出的解密数据的长度。 138 bufferData.length = bytesDecrypted 139 140 //将解密后的数据,以指定的编码方式,转换成字符串对象。 141 let clearDataAsString = NSString(data: bufferData as Data, encoding: String.Encoding.utf8.rawValue) 142 //打印日志 143 print("The result:\(clearDataAsString! as String)") 144 } 145 else 146 { 147 //打印日志 148 print("Error in crypto operation:\(cryptStatus)") 149 } 150 } 151 152 override func didReceiveMemoryWarning() { 153 super.didReceiveMemoryWarning() 154 // Dispose of any resources that can be recreated. 155 } 156 }