引言
在现在迅速发展的互联网时代,数据安全非常重要。为了保证数据的安全,可以在数据的传送时对数据进行加密来保证数据的安全。
加密介绍
加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。
开发常用的加密
第一、MD5 加密
1> 什么是MD5 ?
MD5 的全称是 Message-Digest Algorithm 5 。MD5 以512位分组来处理输入文本,每一分组又划分为16个32位子分组。算法的输出由四个32位分组组成,将它们级联形成一个128位散列值。
2> 使用MD5要引入的头文件
MD5 在Swift 中使用需要引入头文件 #import <CommonCrypto/CommonDigest.h> 。由于 Swift 还没有 CommonCrypto/CommonDigest.h 文件。所以我们需要使用 OC 的 CommonCrypto/CommonDigest.h 。在Swfit 中使用 OC 的文件需要搭建桥接文件,桥接文件规则是:"项目的名称"-Bridging-Header.h。不会创建桥接文件的点击这里
3> MD5 的核心代码
// TODO: MD5加密处理(私有的加密处理方法)
private class func md5ToString(string:String? , type:MD5Type) -> String? {
// 判断传入对象是否存在
if string == nil {
return nil
}
let inputString = string!
if inputString.length() == 0 {
return nil
}
// 获取将要加密对象UTF8编码后的字符数据引用
let encodingArray = inputString.cString(using: String.Encoding.utf8)
// 获取要加密对象的字节数
let encryptedObjByteCount = inputString.lengthOfBytes(using: String.Encoding.utf8)
// 获取加密后的占位空间 (CC_MD5_DIGEST_LENGTH 是 16 位的)
let digestLength = Int(CC_MD5_DIGEST_LENGTH)
// 声明一个不可变的存放加密后的字符数组
let charsArray = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLength)
// 进行加密处理
CC_MD5(encodingArray, CC_LONG(encryptedObjByteCount), charsArray)
// 创建一个可变的字符串
let mutableString = NSMutableString.init()
// 判断输出规则
var printfType:String!
switch type {
case .Lower32:
printfType = "%02x"
break
case .Capitalize32:
printfType = "%02X"
break
}
// 将加密后生成的字符拼接起来
for i in 0 ..< digestLength {
mutableString.appendFormat(printfType as NSString, charsArray[i])
}
// 释放加密后的字符数组对象
charsArray.deinitialize()
// 返回加密后的字符串
return mutableString as String
}
4、MD5 的测试
- 测试代码
let str = "NetWork小贱".md5ToLower32String()
print("小写MD5加密输出"+"----"+str!)
let strmd5 = "NetWork小贱".md5ToCapitalize32String()
print("大写MD5加密输出"+"----"+strmd5!)
-
测试结果
E4599BDF-5FBB-4EE5-B48B-D1B07E2F0081.png
第二、Base64 加密
1、 什么是base64加密?
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。作用是Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。
2、 Base64 的核心代码
// TODO: base64编码处理
private class func base64CodingToString(object:String? , type:CodingType) -> String? {
// 判断传入对象是否存在
if object == nil {
return object
}
// 判断是加密还是解密
switch type {
case .Encrypting:
// 将传入的数据 UTF8 进行编码
let codingData = object?.data(using: .utf8)
return codingData!.base64EncodedString()
case .Decryption:
// 将数据转化为二进制数据
let decryptionData = Data.init(base64Encoded: object!, options: .ignoreUnknownCharacters)
return String.init(data: decryptionData!, encoding: .utf8)
}
}
3、Base64 的测试
- 测试代码
let str = "NetWork小贱".base64EncryptingToString()! as String
print("Base64加密输出"+"----"+str)
let strBase64 = str.base64DecryptionToString()
print("Base64解密输出"+"----"+strBase64!)
-
测试结果
4B1A8A93-5A7F-4AB4-AB5B-415305E829CD.png
第三 、 3DES 加密
1、 3DES 是什么?
3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。
2、 3DES 的工作流程
3DES又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密。3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),加密算法,其具体实现如下:设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,M代表明文,C代表密文,这样:
3DES加密过程为:C=Ek3(Dk2(Ek1(M)))
3DES解密过程为:M=Dk1(EK2(Dk3(C)))
3、3DES 的使用前的准备
3DES 的加密的使用,需要引入头文件 #import <CommonCrypto/CommonCryptor.h>,由于该头文件是Object-OC 的文件,如果想使用该文件,就需要我们搭建桥接文件。搭建规则。
4、3DES 核心代码
// TODO: 3des 的处理函数
private class func threeDESCodingToString(coding object:String? , key:String , type:CodingType) -> String? {
// TODO: 创建要加密或解密的数据接受对象
var data = Data.init()
// 加密
if type == .Encrypting {
// 将要加密的对象编码
data = object!.data(using: .utf8)!
}
// 解密
if type == .Decryption {
// 将要解密的对象编码
data = Data.init(base64Encoded: object!, options: .ignoreUnknownCharacters)!
}
// 创建数据编码后的指针
let dataPointer = UnsafeRawPointer((data as NSData).bytes)
// 获取转码后数据的长度
let dataLength = size_t(data.count)
// TODO: 将加密或解密的密钥转化为Data数据
let keyData = key.data(using: .utf8)! as NSData
// 创建密钥的指针
let keyPointer = UnsafeRawPointer(keyData.bytes)
// 设置密钥的长度
let keyLength = size_t(kCCKeySize3DES)
// TODO: 创建加密或解密后的数据对象
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
// 获取返回数据(cryptData)的指针
let cryptPointer = UnsafeMutableRawPointer(mutating: cryptData!.mutableBytes)
// 获取接收数据的长度
let cryptDataLength = size_t(cryptData!.length)
// 加密或则解密后的数据长度
var cryptBytesLength:size_t = 0
// TODO: 数据参数的准备
// 是解密或者加密操作(CCOperation 是32位的)
let operation:CCOperation = UInt32(type.hashValue)
// 算法的类型
let algorithm:CCAlgorithm = UInt32(kCCAlgorithm3DES)
// 设置密码的填充规则( PKCS7 & ECB 两种填充规则)
let options:CCOptions = UInt32(kCCOptionPKCS7Padding)|UInt32(kCCOptionECBMode)
// 执行算法处理
let cryptStatue = CCCrypt(operation, algorithm, options, keyPointer, keyLength,nil, dataPointer, dataLength, cryptPointer, cryptDataLength, &cryptBytesLength)
// 通过返回状态判断加密或者解密是否成功
if UInt32(cryptStatue) == kCCSuccess {
// 加密
if type == .Encrypting {
cryptData!.length = cryptBytesLength
// 返回3des加密对象
return cryptData!.base64EncodedString(options: .lineLength64Characters)
}
// 解密
if type == .Decryption {
// 返回3des解密对象
cryptData!.length = cryptBytesLength
let outString = NSString(data:cryptData! as Data ,encoding:String.Encoding.utf8.rawValue)
return outString! as String
}
}
// 3des 加密或者解密不成功
return " 3des Encrypt or Decrypt is faill"
}
代码解析:
从上面核心代码来看已经注释很详细了,但是有些地方还是要再详细的解释一下:
-
UnsafeRawPointer 和 UnsafeMutableRawPointer 的介绍
在 Swift 中,指针都使用一个特殊的类型来表示,那就是UnsafeRawPointer。对应地它还有一个可变变体 UnsafeMutableRawPointer 。在创建该指针时,向系统申请了为一定大小的UInt8泛型类型的内存。 -
kCCKeySize3DES 的介绍
kCCKeySize3DES 是指Triple DES加解密的Key的大小,其值为24。要注意了,这里必须是24位,切记,切记。 -
获取可变数据的指针对象
在获取可变数据的指针对想的时候,要注意,必须使用 mutableBytes ,而不能使用 bytes。例如:// 获取返回数据(cryptData)的指针
let cryptPointer = UnsafeMutableRawPointer(mutating: cryptData!.mutableBytes) -
CCCrypt 函数的介绍
1、参数1: 是指定加密还是解密的枚举类型(kCCEncrypt 、kCCDecrypt)。
2、参数2: 是指加密算法的类型。在CommonCryptor.h中提供了kCCAlgorithmAES128、kCCAlgorithmAES、kCCAlgorithmDES、kCCAlgorithm3DES、kCCAlgorithmCAST、kCCAlgorithmRC4、kCCAlgorithmRC2、kCCAlgorithmBlowfish等多种类型的加密算法。
3、 参数3:用来设置密码的填充规则(表示在使用密钥和算法对文本进行加密时的方法)的选项,该选项可以是kCCOptionPKCS7Padding或kCCOptionECBMode两者中的任一个。
4、参数4:密钥的数据指针。
5、参数5: 是密钥的长度 ,必须是 24 位。
6、参数6: 加密或者解密的偏移对象。
7、参数7: 要解密或者解密的数据指针对象。
8、参数8: 要解密或者解密的数据字符长度。
9、参数9: 加密或者解密的数据指针
10、参数10: 接受加密或者解密的数据长度。
11、参数11: 这是加密或者解密的数据长度。
注意::::
在加密或者解密的结果输出的时候,要重新设置接受解密或者加密的数据对象的长度为真实长度。
- CCCrypt 的返回结果
1、kCCSuccess
加解密操作正常结束
2、kCCParamError
非法的参数值
3、kCCBufferTooSmall
选项设置的缓存不够大
4、kCCMemoryFailure
内存分配失败
5、kCCAlignmentError
输入大小匹配不正确
6、kCCDecodeError
输入数据没有正确解码或解密
7、kCCUnimplemented
函数没有正确执行当前的算法
5、3DES 的测试
- 测试代码
let str = "NetWork小贱".threeDESEncryptingToString()!
print("3des加密输出"+"----" + str)
let str3des = str.threeDESDecryptionToString()
print("3des解密输出"+"----"+str3des!)
-
测试结果
4D91B6E9-3296-4F3F-B9A1-0CB1D75DA432.png
Swift 常用加密的封装
针对Swift 的开发中常用的加密方式进行了封装。让开发者使用简单,不用在考虑如何编写实现加密的功能。本次封装的类是 ZSJEncryptingManager.swift。本类含有 MD5\Base64\3DES加密和解密,使用简单方便。避免一个个的功能开发带来的麻烦。该类的方法:
// MARK: md5 加密区
// TODO: md5小写加密(32位)
class func md5ToLower32String(encrypted object:String?)->String? {
return self.md5ToString(string: object, type: .Lower32)
}
// TODO: md5大写加密(32位)
class func md5ToCapitalize32String(encrypted object:String?)->String? {
return self.md5ToString(string: object, type: .Capitalize32)
}
// MARK: 3des 加密区
// TODO: 3des 加密处理
class func threeDESEncryptingToString(encrypting object:String? ,encryptedPublickey:String ) -> String? {
return self.threeDESCodingToString(coding: object, key: TripleDESKey, type: .Encrypting)
}
// TODO: 3des 解密处理
class func threeDESDecryptionToString(decryption object:String? ,decryptionSecretKey:String ) -> String? {
return self.threeDESCodingToString(coding: object, key: TripleDESKey, type: .Decryption)
}
// MARK: base64 加密区
// TODO: base64 加密处理
class func base64EncryptingToString(encrypting object:String?) -> String? {
return self.base64CodingToString(object: object,type:.Encrypting)
}
// TODO: base64 解密处理
class func base64DecryptionToString(decryption object:String?) -> String? {
return self.base64CodingToString(object: object, type: .Decryption)
}
好消息,本次的基础上,再次对加密功能再次封装和扩展:
// MARK: 字符串的扩展
extension String {
// TODO: md5加密
func md5ToLower32String() -> String? {
return ZSJEncryptingManager.md5ToLower32String(encrypted: self)
}
func md5ToCapitalize32String() -> String? {
return ZSJEncryptingManager.md5ToCapitalize32String(encrypted: self)
}
// TODO: 3des加密
func threeDESEncryptingToString() -> String? {
return ZSJEncryptingManager.threeDESEncryptingToString(encrypting: self, encryptedPublickey: TripleDESKey)
}
func threeDESDecryptionToString() -> String? {
return ZSJEncryptingManager.threeDESDecryptionToString(decryption: self, decryptionSecretKey: TripleDESKey)
}
// TODO: base64 加密和解密
func base64EncryptingToString() -> String? {
return ZSJEncryptingManager.base64EncryptingToString(encrypting: self)
}
func base64DecryptionToString() -> String? {
return ZSJEncryptingManager.base64DecryptionToString(decryption: self)
}
}
网友评论