美文网首页Swift
Swift009-加密

Swift009-加密

作者: DDY | 来源:发表于2019-07-24 15:36 被阅读0次

    Swift009-加密

    • MD5

      MD5(Message-Digest Algorithm 5)以512位分组来处理输入文本,每组又划分为16个32位子分组。算法的输出由四个32位分组组成,将它们级联形成一个128位散列值。

      /// MD5 编码
      ///
      /// - Parameters:
      ///   - string: 需要编码的字符串
      ///   - lower: true:字母小写 false:字母大写
      /// - Returns: 编码结果
      public static func ddyMD5String(_ string: String?, lower: Bool) -> String? {
          guard let cStr = string?.cString(using: .utf8) else {
              return nil
          }
          let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 16)
          CC_MD5(cStr,(CC_LONG)(strlen(cStr)), buffer)
          let md5String = NSMutableString();
          for i in 0 ..< 16 {
              if lower {
                  md5String.appendFormat("%02x", buffer[i])
              } else {
                  md5String.appendFormat("%02X", buffer[i])
              }
          }
          free(buffer)
          return md5String as String
      }   
      
    • Base64

      Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。作用是Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。

      /// Base64 编解码
      ///
      /// - Parameters:
      ///   - string: 需要编解码的字符串
      ///   - encode: true:编码 false:解码
      /// - Returns: 编码结果
      public static func ddyBase64String(_ string: String?, encode: Bool) -> String? {
          if encode { // 编码
              guard let codingData = string?.data(using: .utf8) else {
                  return nil
              }
              return codingData.base64EncodedString()
          } else { // 解码
              guard let newStr = string else {
                  return nil
              }
              guard let decryptionData = Data(base64Encoded: newStr, options: .ignoreUnknownCharacters) else {
                  return nil
              }
              return String.init(data: decryptionData, encoding: .utf8)
          }
      }
      
    • Sha1

      SHA1和MD5本质都是摘要函数,长度不同(MD5是128位,SHA1是160位,SHA256是256位)

      public static func ddySha1String(_ string: String?) -> String? {
          guard let codingData = string?.data(using: .utf8) else {
              return nil
          }
          var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
          let newData = NSData.init(data: codingData)
          CC_SHA1(newData.bytes, CC_LONG(codingData.count), &digest)
          let output = NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
          for byte in digest {
              output.appendFormat("%02x", byte)
          }
          return output as String
      }
      
    • 综合封装

      MD5、SHA1、SHA224、SHA256、SHA384、SHA512

    ```
    // Secure Hash Algorithm
    enum DDYSHAType {
       case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
        var infoTuple: (algorithm: CCHmacAlgorithm, length: Int) {
            switch self {
            case .MD5:      return (algorithm: CCHmacAlgorithm(kCCHmacAlgMD5),    length: Int(CC_MD5_DIGEST_LENGTH))
            case .SHA1:     return (algorithm: CCHmacAlgorithm(kCCHmacAlgSHA1),   length: Int(CC_SHA1_DIGEST_LENGTH))
            case .SHA224:   return (algorithm: CCHmacAlgorithm(kCCHmacAlgSHA224), length: Int(CC_SHA224_DIGEST_LENGTH))
            case .SHA256:   return (algorithm: CCHmacAlgorithm(kCCHmacAlgSHA256), length: Int(CC_SHA256_DIGEST_LENGTH))
            case .SHA384:   return (algorithm: CCHmacAlgorithm(kCCHmacAlgSHA384), length: Int(CC_SHA384_DIGEST_LENGTH))
            case .SHA512:   return (algorithm: CCHmacAlgorithm(kCCHmacAlgSHA512), length: Int(CC_SHA512_DIGEST_LENGTH))
            }
        }
    }
    
    // MD5 SHA1 SHA256 SHA512 这4种本质都是摘要函数,不通在于长度  MD5 是 128 位,SHA1  是 160 位 ,SHA256  是 256 位
    public static func shaCrypt(string: String?, cryptType: DDYSHAType, key: String?, lower: Bool) -> String? {
        guard let cStr = string?.cString(using: String.Encoding.utf8) else {
            return nil
        }
        // let strLen = Int(string!.lengthOfBytes(using: String.Encoding.utf8))
        let strLen  = strlen(cStr)
        let digLen = cryptType.infoTuple.length
        let buffer = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digLen)
        let hash = NSMutableString()
    
        if let cKey = key?.cString(using: String.Encoding.utf8), key != "" {
            let keyLen = Int(key!.lengthOfBytes(using: String.Encoding.utf8))
            CCHmac(cryptType.infoTuple.algorithm, cKey, keyLen, cStr, strLen, buffer)
        } else {
            switch cryptType {
            case .MD5:      CC_MD5(cStr,    (CC_LONG)(strlen(cStr)), buffer)
            case .SHA1:     CC_SHA1(cStr,   (CC_LONG)(strlen(cStr)), buffer)
            case .SHA224:   CC_SHA224(cStr, (CC_LONG)(strlen(cStr)), buffer)
            case .SHA256:   CC_SHA256(cStr, (CC_LONG)(strlen(cStr)), buffer)
            case .SHA384:   CC_SHA384(cStr, (CC_LONG)(strlen(cStr)), buffer)
            case .SHA512:   CC_SHA512(cStr, (CC_LONG)(strlen(cStr)), buffer)
            }
        }
        for i in 0..<digLen {
            if lower {
                hash.appendFormat("%02x", buffer[i])
            } else {
                hash.appendFormat("%02X", buffer[i])
            }
        }
        free(buffer)
        return hash as String
    }
    ```
    
    对称加密:AES、AES128、DES、DES3、CAST、RC2RC4、Blowfish     
    iOS中填充规则PKCS7,加解密模式ECB(无补码,CCCrypt函数中对应的nil),字符集UTF8,输出base64(可以自己改hex)
    
    
    ```
    // Symmetric Cryptographic Algorithm
    enum DDYSCAType {
        case AES, AES128, DES, DES3, CAST, RC2, RC4, Blowfish
        var infoTuple: (algorithm: CCAlgorithm, digLength: Int, keyLength: Int) {
        switch self {
            case .AES:     return (CCAlgorithm(kCCAlgorithmAES),       Int(kCCKeySizeAES128),      Int(kCCKeySizeAES128))
            case .AES128:  return (CCAlgorithm(kCCAlgorithmAES128),    Int(kCCBlockSizeAES128),    Int(kCCKeySizeAES256))
            case .DES:     return (CCAlgorithm(kCCAlgorithmDES),       Int(kCCBlockSizeDES),       Int(kCCKeySizeDES))
            case .DES3:    return (CCAlgorithm(kCCAlgorithm3DES),      Int(kCCBlockSize3DES),      Int(kCCKeySize3DES))
            case .CAST:    return (CCAlgorithm(kCCAlgorithmCAST),      Int(kCCBlockSizeCAST),      Int(kCCKeySizeMaxCAST))
            case .RC2:     return (CCAlgorithm(kCCAlgorithmRC2),       Int(kCCBlockSizeRC2),       Int(kCCKeySizeMaxRC2))
            case .RC4:     return (CCAlgorithm(kCCAlgorithmRC4),       Int(kCCBlockSizeRC2),       Int(kCCKeySizeMaxRC4))
            case .Blowfish:return (CCAlgorithm(kCCAlgorithmBlowfish),  Int(kCCBlockSizeBlowfish),  Int(kCCKeySizeMaxBlowfish))
            }
        }
    }
    
    public static func scaCrypt(string: String?, cryptType: DDYSCAType, key: String?, encode: Bool) -> String? {
    
        if string == nil {
            return nil
        }
        let strData = encode ? string!.data(using: .utf8) : Data(base64Encoded: string!)
        // 创建数据编码后的指针
        let dataPointer = UnsafeRawPointer((strData! as NSData).bytes)
        // 获取转码后数据的长度
        let dataLength = size_t(strData!.count)
        // 将加密或解密的密钥转化为Data数据
        guard let keyData = key?.data(using: .utf8) else {
            return nil
        }
        // 创建密钥的指针
        let keyPointer = UnsafeRawPointer((keyData as NSData).bytes)
        // 设置密钥的长度
        let keyLength = cryptType.infoTuple.keyLength
    
        // 创建加密或解密后的数据对象
        let cryptData = NSMutableData(length: Int(dataLength) + cryptType.infoTuple.digLength)
        // 获取返回数据(cryptData)的指针
        let cryptPointer = UnsafeMutableRawPointer(mutating: cryptData!.mutableBytes)
        // 获取接收数据的长度
        let cryptDataLength = size_t(cryptData!.length)
        // 加密或则解密后的数据长度
        var cryptBytesLength:size_t = 0
        // 是解密或者加密操作(CCOperation 是32位的)
        let operation = encode ? CCOperation(kCCEncrypt) : CCOperation(kCCDecrypt)
        // 算法类型
        let algoritm: CCAlgorithm = CCAlgorithm(cryptType.infoTuple.algorithm)
        // 设置密码的填充规则( PKCS7 & ECB 两种填充规则)
        let options:CCOptions = UInt32(kCCOptionPKCS7Padding) | UInt32(kCCOptionECBMode)
        // 执行算法处理
        let cryptStatus = CCCrypt(operation, algoritm, options, keyPointer, keyLength, nil, dataPointer, dataLength, cryptPointer, cryptDataLength, &cryptBytesLength)
        // 结果字符串初始化
        var resultString: String?
        // 通过返回状态判断加密或者解密是否成功
        if CCStatus(cryptStatus) == CCStatus(kCCSuccess) {
            cryptData!.length = cryptBytesLength
            if encode {
                resultString = cryptData!.base64EncodedString(options: .lineLength64Characters)
            } else {
                resultString = NSString(data:cryptData! as Data ,encoding:String.Encoding.utf8.rawValue) as String?
            }
        }
        return resultString
    }
    ```
    
    
    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 函数没有正确执行当前的算法   
    
    
    
    [验证](http://tool.chacuo.net/cryptdes)     
    [参考](https://www.jianshu.com/p/cab8f6ffb082)     
    [参考](https://www.jianshu.com/p/940aaca1e3f6)    
    [RSA加密](https://www.jianshu.com/p/d2cb314d30ec)    

    相关文章

      网友评论

        本文标题:Swift009-加密

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