-
一、Swift3.0系统提供的base64加密方法(可逆)
extension String {
/**
* Base64 加密
* return 加密字符串
*/
func encodeToBase64() -> String {
guard let data = self.data(using: String.Encoding.utf8) else { print("加密失败"); return "" }
return data.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)) //系统提供的方法,iOS7之后可用
}
/**
* Base64 解密
* return 解密字符串
*/
func decodeBase64() -> String {
guard let data = Data(base64Encoded: self, options: Data.Base64DecodingOptions(rawValue: 0)) else { print("解密失败"); return "" }
return String(data: data, encoding: String.Encoding.utf8)!
}
}
let base64Str = "明哥" // 打印 "明哥"
let encodeStr = base64Str.encodeToBase64() // 打印 "5piO5ZOl"
let decodeStr = encodeStr.decodeBase64() // 打印 "明哥"
-
二、HMAC_SHA1/MD5/SHA1/SHA224...... (不可逆)
// MARK: - 加密 HMAC_SHA1/MD5/SHA1/SHA224......
/** 需在桥接文件导入头文件 ,因为C语言的库
* #import <CommonCrypto/CommonDigest.h>
* #import <CommonCrypto/CommonHMAC.h>
*/
enum CryptoAlgorithm { // 2,SHA(安全散列算法:Secure Hash Algorithm) // 不可逆
/// 加密的枚举选项 HMAC
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
var HMACAlgorithm: CCHmacAlgorithm {
var result: Int = 0
switch self {
case .MD5: result = kCCHmacAlgMD5
case .SHA1: result = kCCHmacAlgSHA1
case .SHA224: result = kCCHmacAlgSHA224
case .SHA256: result = kCCHmacAlgSHA256
case .SHA384: result = kCCHmacAlgSHA384
case .SHA512: result = kCCHmacAlgSHA512
}
return CCHmacAlgorithm(result)
}
var digestLength: Int {
var result: Int32 = 0
switch self {
case .MD5: result = CC_MD5_DIGEST_LENGTH
case .SHA1: result = CC_SHA1_DIGEST_LENGTH
case .SHA224: result = CC_SHA224_DIGEST_LENGTH
case .SHA256: result = CC_SHA256_DIGEST_LENGTH
case .SHA384: result = CC_SHA384_DIGEST_LENGTH
case .SHA512: result = CC_SHA512_DIGEST_LENGTH
}
return Int(result)
}
}
extension String {
/**
func: 加密方法
- parameter algorithm: 加密方式;
- parameter key: 加密的key
*/
func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
let str = self.cString(using: String.Encoding.utf8)
let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
let digestLen = algorithm.digestLength
let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
let keyStr = key.cString(using: String.Encoding.utf8)
let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
// CCHmac是系统内部方法
CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
let digest = stringFromResult(result: result, length: digestLen)
result.deallocate(capacity: digestLen)
return digest
}
// 内部结果
private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
let hash = NSMutableString()
for i in 0..<length {
hash.appendFormat("%02x", result[i])
}
return String(hash)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
let str = "welcome to hangge.com"
let key = "67FG"
// HMAC
let hmacStr = str.hmac(algorithm: .SHA1, key: key)
print("原始字符串:\(str)")
print("key:\(key)")
print("HMAC运算结果:\(hmacStr)")
// SHA224
let SHA224 = str.hmac(algorithm: .SHA224, key: key)
print("原始字符串:\(str)")
print("key:\(key)")
print("SHA224运算结果:\(SHA224)")
// md5
let str1 = "欢迎来到zhuhai"
let key2 = "你好"
let md5 = str1.hmac(algorithm: .MD5, key: key2)
print("原始字符串:\(str1)")
print("key:\(key2)")
print("md5运算结果:\(md5)")
// 普通md5
let md55 = str1.md5
print("md55 = \(md55)")
// 普通md5测试
print("md测试 = \("lacar我是牛人才怪lacar".md5)")
print("md用户测试 = \("用户名".md5)")
print("md我们测试 = \("我们".md5)")
print("md123测试 = \("123".md5)")
print("mdming测试 = \("ming".md5)")
print("md你好测试 = \("你好".md5)")
print("mdlacar测试 = \("lacar".md5)")
}
// NSData+Extension.swift
// Created by ming.com on 17/3/21.
// Copyright © 2017年 MG明明. All rights reserved.
import UIKit
// MARK: - 加密 AES/AES128/DES/DES3/CAST/RC2/RC4/Blowfish......
/** 需在桥接文件导入头文件 ,因为C语言的库
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCrypto.h>
*/
enum CryptoAlgorithm {
/// 加密的枚举选项 AES/AES128/DES/DES3/CAST/RC2/RC4/Blowfish......
case AES, AES128, DES, DES3, CAST, RC2,RC4, Blowfish
var algorithm: CCAlgorithm {
var result: UInt32 = 0
switch self {
case .AES: result = UInt32(kCCAlgorithmAES)
case .AES128: result = UInt32(kCCAlgorithmAES128)
case .DES: result = UInt32(kCCAlgorithmDES)
case .DES3: result = UInt32(kCCAlgorithm3DES)
case .CAST: result = UInt32(kCCAlgorithmCAST)
case .RC2: result = UInt32(kCCAlgorithmRC2)
case .RC4: result = UInt32(kCCAlgorithmRC4)
case .Blowfish: result = UInt32(kCCAlgorithmBlowfish)
}
return CCAlgorithm(result)
}
var keyLength: Int {
var result: Int = 0
switch self {
case .AES: result = kCCKeySizeAES128
case .AES128: result = kCCKeySizeAES256
case .DES: result = kCCKeySizeDES
case .DES3: result = kCCKeySize3DES
case .CAST: result = kCCKeySizeMaxCAST
case .RC2: result = kCCKeySizeMaxRC2
case .RC4: result = kCCKeySizeMaxRC4
case .Blowfish: result = kCCKeySizeMaxBlowfish
}
return Int(result)
}
var cryptLength: Int {
var result: Int = 0
switch self {
case .AES: result = kCCKeySizeAES128
case .AES128: result = kCCBlockSizeAES128
case .DES: result = kCCBlockSizeDES
case .DES3: result = kCCBlockSize3DES
case .CAST: result = kCCBlockSizeCAST
case .RC2: result = kCCBlockSizeRC2
case .RC4: result = kCCBlockSizeRC2
case .Blowfish: result = kCCBlockSizeBlowfish
}
return Int(result)
}
}
// MARK: - 加密扩展NSData
extension NSData {
/*
加密
- parameter algorithm: 加密方式
- parameter keyData: 加密key
- return NSData: 加密后的数据 可选值
*/
func enCrypt(algorithm: CryptoAlgorithm, keyData:NSData) -> NSData? {
return crypt(algorithm: algorithm, operation: CCOperation(kCCEncrypt), keyData: keyData)
}
/*
解密
- parameter algorithm: 解密方式
- parameter keyData: 解密key
- return NSData: 解密后的数据 可选值
*/
func deCrypt(algorithm: CryptoAlgorithm, keyData:NSData) -> NSData? {
return crypt(algorithm: algorithm, operation: CCOperation(kCCDecrypt), keyData: keyData)
}
/*
解密和解密方法的抽取的封装方法
- parameter algorithm: 何种加密方式
- parameter operation: 加密和解密
- parameter keyData: 加密key
- return NSData: 解密后的数据 可选值
*/
func crypt(algorithm: CryptoAlgorithm, operation:CCOperation, keyData:NSData) -> NSData? {
let keyBytes = keyData.bytes
let keyLength = Int(algorithm.keyLength)
let dataLength = self.length
let dataBytes = self.bytes
let cryptLength = Int(dataLength+algorithm.cryptLength)
let cryptPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: cryptLength)
let algoritm: CCAlgorithm = CCAlgorithm(algorithm.algorithm)
let option: CCOptions = CCOptions(kCCOptionECBMode + kCCOptionPKCS7Padding)
let numBytesEncrypted = UnsafeMutablePointer<Int>.allocate(capacity: 1)
numBytesEncrypted.initialize(to: 0)
let cryptStatus = CCCrypt(operation, algoritm, option, keyBytes, keyLength, nil, dataBytes, dataLength, cryptPointer, cryptLength, numBytesEncrypted)
// 判断是否加密成功
if CCStatus(cryptStatus) == CCStatus(kCCSuccess) {
let len = Int(numBytesEncrypted.pointee)
let data:NSData = NSData(bytesNoCopy: cryptPointer, length: len)
numBytesEncrypted.deallocate(capacity: 1)
return data
} else {
numBytesEncrypted.deallocate(capacity: 1)
cryptPointer.deallocate(capacity: cryptLength)
return nil
}
}
}
static func test(){
let keyString = "12345678901234567890123456789012"
let keyData: NSData! = (keyString as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
let message = "你是大傻瓜吗?你才是"
let data: NSData! = (message as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
print("要加密的字符串:" + message)
// 下边时进行加密解密的代码
let result:NSData? = data.AES128Crypt(operation: CCOperation(kCCEncrypt), keyData: keyData)
print("encrypt = \(result!)")
let oldData = result?.AES128Crypt(operation: CCOperation(kCCDecrypt), keyData: keyData)
print("decrypt = \(oldData!)")
print(String(data: oldData as! Data, encoding: String.Encoding.utf8)!)
// 下边时进行加密解密的数据
let enData = data.enCrypt(algorithm: .AES, keyData: keyData)
let deData = enData?.deCrypt(algorithm: .AES, keyData: keyData)
print("通过解密后的字符串:" + String(data: deData as! Data, encoding: String.Encoding.utf8)!)
}
let keyString = "12345678901234567890123456789012"
let keyData: NSData! = (keyString as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
let message = "你是大傻瓜吗?你才是"
let data: NSData! = (message as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
let enData = data.enCrypt(algorithm: .AES, keyData: keyData)
let deData = enData?.deCrypt(algorithm: .AES, keyData: keyData)
print("通过解密后的字符串:" + String(data: deData as! Data, encoding: String.Encoding.utf8)!)
let enData1 = data.enCrypt(algorithm: .DES, keyData: keyData)
let deData1 = enData1?.deCrypt(algorithm: .DES, keyData: keyData)
print("通过解密后的字符串:" + String(data: deData1 as! Data, encoding: String.Encoding.utf8)!)
let enData2 = data.enCrypt(algorithm: .RC2, keyData: keyData)
let deData2 = enData2?.deCrypt(algorithm: .RC2, keyData: keyData)
print("通过解密后的字符串:" + String(data: deData2 as! Data, encoding: String.Encoding.utf8)!)
print("enData-AES: + \(enData!)")
print("enData-DES: + \(enData1!)")
print("enData-RC2: + \(enData2!)")
print("deData-AES: + \(deData!)")
print("deData-DES: + \(deData1!)")
print("deData-RC2: + \(deData2!)")
结论: 探究同一个字符串和同一个key不同加密类型发现,加密的方式不同,所生成的加密过得data不同,但是解密出来的data是相同的,当转成字符串之后,就可以看到之前加密过得字符串了
-
接上第三AES加密,给Data扩展
-
NSData扩展大致一样
- 与NSData的主要区别: 这个写法不一样
keyData.withUnsafeBytes {(bytes: UnsafePointer<Int8>)->Void in
keyBytes = bytes
}
let data = Data.init(bytes: cryptPointer, count: len)
// MARK: - Data Data打印出来是16或者32 bytes,打印需转成NSData类型打印结果比较直观
// MARK: - data
extension Data {
/*
加密
- parameter algorithm: 加密方式
- parameter keyData: 加密key
- return NSData: 加密后的数据 可选值
*/
mutating func enCrypt(algorithm: CryptoAlgorithm, keyData:Data) -> Data? {
return crypt(algorithm: algorithm, operation: CCOperation(kCCEncrypt), keyData: keyData)
}
/*
解密
- parameter algorithm: 解密方式
- parameter keyData: 解密key
- return NSData: 解密后的数据 可选值
*/
mutating func deCrypt(algorithm: CryptoAlgorithm, keyData:Data) -> Data? {
return crypt(algorithm: algorithm, operation: CCOperation(kCCDecrypt), keyData: keyData)
}
/*
解密和解密方法的抽取的封装方法
- parameter algorithm: 何种加密方式
- parameter operation: 加密和解密
- parameter keyData: 加密key
- return NSData: 解密后的数据 可选值
*/
mutating func crypt(algorithm: CryptoAlgorithm, operation:CCOperation, keyData: Data) -> Data? {
let keyLength = Int(algorithm.keyLength)
let dataLength = self.count
let cryptLength = Int(dataLength+algorithm.cryptLength)
let cryptPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: cryptLength)
let algoritm: CCAlgorithm = CCAlgorithm(algorithm.algorithm)
let option: CCOptions = CCOptions(kCCOptionECBMode + kCCOptionPKCS7Padding)
let numBytesEncrypted = UnsafeMutablePointer<Int>.allocate(capacity: 1)
numBytesEncrypted.initialize(to: 0)
var keyBytes: UnsafePointer<Int8>?
keyData.withUnsafeBytes {(bytes: UnsafePointer<Int8>)->Void in
keyBytes = bytes
}
var dataBytes: UnsafePointer<Int8>?
self.withUnsafeBytes {(bytes: UnsafePointer<CChar>)->Void in
// print(bytes)
dataBytes = bytes
}
let cryptStatus = CCCrypt(operation, algoritm, option, keyBytes!, keyLength, nil, dataBytes!, dataLength, cryptPointer, cryptLength, numBytesEncrypted)
if CCStatus(cryptStatus) == CCStatus(kCCSuccess) {
let len = Int(numBytesEncrypted.pointee)
let data = Data.init(bytes: cryptPointer, count: len)
numBytesEncrypted.deallocate(capacity: 1)
return data
} else {
numBytesEncrypted.deallocate(capacity: 1)
cryptPointer.deallocate(capacity: cryptLength)
return nil
}
}
}
// MARK: - Data测试
extension Data {
static func test1(){
let keyString = "123"
let message = "you are so stuip"
let keyData = keyString.data(using: String.Encoding.utf8)
var data = message.data(using: String.Encoding.utf8)
var result = data?.enCrypt(algorithm: CryptoAlgorithm.AES, keyData: keyData!)
print("result = \(result!)")
let data1 = NSData(data: result!)
print(data1)
print(NSString(data: result!, encoding: String.Encoding.utf8.rawValue))
let oldData = result?.deCrypt(algorithm: CryptoAlgorithm.AES, keyData: keyData!)
print("oldData = \(oldData! as NSData)")
print(String(data: oldData!, encoding: String.Encoding.utf8)!)
}
}