使用Swift 3.0实现原生的3DES加密和解密
来源:互联网 发布:lol比赛视频软件 编辑:程序博客网 时间:2024/05/24 02:19
DES(Data EncryptionStandard)又叫数据加密标准,是1973年5月15日美国国家标准局(现在是美国标准技术研究所,即NIST)在联邦记录中公开征集密码体制时出现的。DES加密算法是一种对称加密技术,该算法的要求主要为以下四点:
- 提供高质量的数据保护,防止数据未经授权的泄露和未被察觉的修改;
- 具有较高的复杂性,使得破译的开销超过可能获得的利益,同时又要便于理解和掌握;
- 密码体制的安全性应该不依赖于算法的保密,其安全性仅以加密密钥的保密为基础;
- 实现经济,运行有效,并且适用于多种完全不同的应用。
而3DES(或称为TripleDES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。
创建项目并建立桥接文件
接着我们来创建一个示例项目,对一个字符串进行3DES加密和解密。首先创建一个基于[Single View Applicaton]模板的空白项目,然后在左侧的项目名称文件夹上点击鼠标右键,并选择右键菜单中的[New File...]选项,创建一个桥接头文件,这是因为我们需要使用到Object-C的CommonCrypto。
在弹出的模板选择窗口中,依次选择[Source > Header File]选项,以创建一个.h的头文件,如图1所示:
图 1
桥接头文件创建完成后,打开并编辑该文件,以引入相关的头文件,如图2所示:
图 2
接着还需要在Build Settings面板中设置Objective-C Bridging Header,在进入Build Settings面板之后,在搜索输入框内输入objective-c bridging进行搜索,以定位Objective-C Bridging Header选项,并设置该选项的值为桥接文件所在的位置,如图3所示:
图 3
实现3DES加解密功能
完成项目的配置之后,在左侧的项目导航区打开并编辑[ViewController.swift]文件,开始3DES加解密功能的实现。在该文件中首先创建一个集合,用来生成随机的公用key值:
private let randomStringArray: [Character] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".characters.map({$0})
var key:String = ""
然后添加一个名为randomStringOfLength方法,用来获得指定长度的随机字符串,该字符串从randomStringArray集合中获得英文大小写字母和0至9之间的数字,然后由这些字符通过一个for–in 循环组成指定长度的随机字符串。其中uniform方法可以用来产生0~(n-1)范围内的随机数,不需要再进行取模运算。如果要生成1至n的随机数,可以这么写:arc4random_uniform(n)+1:
func randomStringOfLength(_ length:Int) -> String {var string = "" for _ in (1...length) {string.append(randomStringArray[Int(arc4random_uniform( UInt32(randomStringArray.count) - 1))])} return string}
然后添加一个名为encrypt方法,对字符串参数encryptData进行加密:
func encrypt(encryptData:String){ key = randomStringOfLength(kCCKeySize3DES) let inputData : Data = encryptData.data(using: String.Encoding.utf8)! let keyData: Data = key.data(using: String.Encoding.utf8, allowLossyConversion: false)! let keyBytes = UnsafeMutableRawPointer(mutating: (keyData as NSData).bytes) let keyLength = size_t(kCCKeySize3DES) let dataLength = Int(inputData.count) let dataBytes = UnsafeRawPointer((inputData as NSData).bytes) let bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)! let bufferPointer = UnsafeMutableRawPointer(bufferData.mutableBytes) let bufferLength = size_t(bufferData.length) var bytesDecrypted = Int(0) let cryptStatus = CCCrypt( UInt32(kCCEncrypt), UInt32(kCCAlgorithm3DES), UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding), keyBytes, keyLength, nil, dataBytes, dataLength, bufferPointer, bufferLength, &bytesDecrypted) if Int32(cryptStatus) == Int32(kCCSuccess) { bufferData.length = bytesDecrypted decrypt(inputData: bufferData as Data) } else { print("加密过程出错: \(cryptStatus)") } }
CCCrypt参数的配置
在该方法中的第2行至14行的代码,都是用来生成CCCrypt方法中的各种参数的值。
首先在第2行的代码中,通过randomStringOfLength方法,生成一个随机字符串作为3DES加解密的key值。其中kCCKeySize3DES是指Triple DES加解密的key的大小,其值为24,因此这里将生成一个长度为24的包含英文大小写字母和数字的随机字符串。
接着在第3行的代码中,将待加密的字符串转换为Data类型。
在第5行的代码中,将作为随机字符串的key值同样转换为Data类型。
在第6行的代码中,创建一个UnsafeMutableRawPointer指针。在 Swift 中,指针都使用一个特殊的类型来表示,那就是UnsafeRawPointer。对应地它还有一个可变变体, UnsafeMutableRawPointer 。在创建该指针时,向系统申请了个数为(keyData as NSData).bytes的UInt8泛型类型的内存。
在第7行的代码中,创建一个名为keyLength的常量,表示key值的长度。根据kCCKeySize3DES的大小可以得知,keyLenght的值为24。
然后在第9行的代码中,获得待加密的Data类型对象的长度。并在第20行的代码中,创建一个UnsafePointer指针,并从系统中分配相应的内存作为加密的input buffer。
在第11行的代码中,创建一个指定长度的NSMutableData可变的二进制数据对象,该对象将作为加密的outputbuffer,用来存储加密后的数据。其长度为input buffer的长度和3DES加密的kCCBlockSize3DES块大小之和,kCCBlockSize3DES块的大小为8。
接着在第12行的代码中,创建一个UnsafeMutablePointer类型的指针,并根据output buffer即bufferData的大小分配相应的内存。
然后在第13行的代码中,获得outputbuffer的长度。最后在第14行的代码中,创建一个变量bytesDecrypted,用来存储加密后的output buffer的最终字节数。
执行CCCrypt方法
完成所有的参数设置之后,在第16至27行的代码中,调用CommonCryptor.h中的CCCrypt方法对数据进行加密操作。
其中CCCrypt方法的第一个参数表示进行加密操作,还是进行解密操作,这里使用kCCEncrypt表示进行加密操作。
第二个参数表示进行加密的算法,在CommonCryptor.h中提供了kCCAlgorithmAES128、kCCAlgorithmAES、kCCAlgorithmDES、kCCAlgorithm3DES、kCCAlgorithmCAST、kCCAlgorithmRC4、kCCAlgorithmRC2、kCCAlgorithmBlowfish等多种类型的加密算法。
第三个参数用来设置block ciphers(block cipher表示在使用密钥和算法对文本进行加密时的方法)的选项,该选项可以是kCCOptionPKCS7Padding或kCCOptionECBMode两者中的任一个。假如使用PKCS7Padding,它的密钥可以是8个字节,也可以不是。
CCCrypt方法的其它几个参数就是我们在第2行至14行号配置好的参数。
判断CCCrypt方法执行的结果
当执行完CCCrypt方法后,会返回一个cryptStatus状态,通过cryptStatus判断是否加密成功。其中kCCSuccess表示加密成功,除此之外还有其它几种状态,如表1所示:
表1 CCCrypt结果状态列表
状态值
说明
kCCSuccess
加解密操作正常结束。
kCCParamError
非法的参数值。
kCCBufferTooSmall
选项设置的缓存不够大。
kCCMemoryFailure
内存分配失败。
kCCAlignmentError
输入大小匹配不正确。
kCCDecodeError
输入数据没有正确解码或解密。
kCCUnimplemented
函数没有正确执行当前的算法。
当判断加密操作正确完成后,设置output data的length为bytesDecrypted,以调整输出buffer的大小为最终输出加密数据的尺寸。
对密文进行解密操作
至此就完成了数据的加密操作,接着使用相同的密钥对密文进行解密操作。该功能通过调用decrypt方法来实现:
func decrypt(inputData : Data){ let keyData: Data = key.data(using: String.Encoding.utf8, allowLossyConversion: false)! let keyBytes = UnsafeMutableRawPointer(mutating: (keyData as NSData).bytes) let keyLength = size_t(kCCKeySize3DES) let dataLength = Int(inputData.count) let dataBytes = UnsafeRawPointer((inputData as NSData).bytes) let bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)! let bufferPointer = UnsafeMutableRawPointer(bufferData.mutableBytes) let bufferLength = size_t(bufferData.length) var bytesDecrypted = Int(0) let cryptStatus = CCCrypt( UInt32(kCCDecrypt), UInt32(kCCAlgorithm3DES), UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding), keyBytes, keyLength, nil, dataBytes, dataLength, bufferPointer, bufferLength, &bytesDecrypted) if Int32(cryptStatus) == Int32(kCCSuccess) { bufferData.length = bytesDecrypted let clearDataAsString = NSString(data: bufferData as Data, encoding: String.Encoding.utf8.rawValue) print("解密后的内容:\(clearDataAsString as! String)") } else { print("解密过程出错: \(cryptStatus)") }}
解密的方法与加密的方法大体相似,需要注意不同的地方是,在第13行使用kCCDecrypt进行解密运算。然后在72行的代码中,将解密后的数据转换为NSString对象,并通过print语句在日志区进行打印输出。
修改viewDidLoad方法
最后一步是修改ViewController类的viewDidLoad方法,在该方法中调用加密方法encrypt,对明文coolketang.com进行加密操作:
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. encrypt(encryptData: "coolketang.com");}
现在已经完成了所有的加解密的编码工作,点击Xcode界面左上角的[编译并运行]按钮 ,打开模拟器运行项目。项目运行后,将弹出一个空白的模拟器,并在日志区输出解密后的结果,如图4所示:
图 4
p.p1 {margin: 0.0px 0.0px 2.0px 0.0px; font: 14.0px '.PingFang SC'; color: #454545}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Helvetica Neue'; color: #e4af0a}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.PingFang SC'; color: #454545}span.s1 {font: 14.0px 'Helvetica Neue'}span.s2 {font: 12.0px '.PingFang SC'; color: #454545}span.s3 {font: 12.0px 'Helvetica Neue'; text-decoration: underline ; color: #e4af0a}span.s4 {text-decoration: underline ; color: #e4af0a}span.s5 {font: 12.0px 'Helvetica Neue'}table{width:100%}table td{padding-left:10px;}
新 作
iOS开发中的神兵利器
共140节课程,讲解GitHub中近百个过千star的iOS热门开源项目
市面上唯一大规模讲解GitHub中热门的iOS开源项目的教程
快速、优雅地解决iOS开发工作中遇到的各种棘手问题
视频观看地址:http://study.163.com/course/courseMain.htm?courseId=1003657013
互动教程下载地址:https://itunes.apple.com/cn/app/id1209739676
- 使用Swift 3.0实现原生的3DES加密和解密
- 实现DES加密和解密的类
- 使用DES加密和解密的方法
- 3DES加密和解密的实例
- java实现对称加密AES和DES的加密、解密
- 使用Swift 3.0实现原生的MD5加密
- PHP和.NET通用的加密解密函数类,均使用3DES加解密
- VC实现数据的加密和解密(MD5加密/DES/RSA加密解密)
- 使用3DES加密与解密实习Android端和后台的数据加密传输
- php实现和c#一致的DES加密解密
- Java DES 加密和解密算法的使用
- 用C#实现Des加密和解密
- 用C#实现Des加密和解密
- C#实现Des加密和解密
- 用java实现des加密和解密
- 用C#实现Des加密和解密
- 用C#实现Des加密和解密
- C#实现Des加密和解密
- Linux与我的第一次
- android app动图优化:源码giflib加载gif动图,性能秒杀glide
- Java基础学习之-02
- Java 输入外挂
- Parity check——打表找规律+大数取模
- 使用Swift 3.0实现原生的3DES加密和解密
- Leetcode Week12
- Java基础学习之-03
- AOP架构之路-AspectJ
- 初识mongodb----索引
- Android Toast
- 蓝桥杯 算法提高 学霸的迷宫(bfs+方向输出)
- MySQL 学习<一> MySQL简介
- MySql数据库索引原理