MG--Swift3.0 加密相关方法

作者: Mg明明就是你 | 来源:发表于2017-03-21 11:45 被阅读365次
    • 一、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)")
        }
    
    测试结果


    • 三、AES、DES等(可逆)

      • 封装方法

    //  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)!)
        }
    
    打印结果.png
    • 探究

            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!)")
    
    NData测试打印结果.png

    结论: 探究同一个字符串和同一个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)!)
        }
    }
    
    Data测试打印.png
    • 扫一扫,关注我

    扫一扫,关注我.jpg

    相关文章

      网友评论

      • hotwill:可以在封装一个方法,传入key和需要加密的message 返回一个字符串,可以作为请求的加密串
      • 布袋的世界:要是能再上些和服务器的交互就更棒了 ...
        Mg明明就是你:@布袋的世界 该不会后台:sob:

      本文标题:MG--Swift3.0 加密相关方法

      本文链接:https://www.haomeiwen.com/subject/lsownttx.html