[Swift通天遁地]七、数据与安全,17使用Swift实现原生的3DES加密和解密

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

➤微信公众号:山青咏芝(shanqingyongzhi)

➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/

➤GitHub地址:https://github.com/strengthen/LeetCode

➤原文地址:

➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。

➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

目录:[Swift]通天遁地Swift

本文将演示如何编写原生的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 }