字符串的加密与解密(3DES、sha1、MD5) - swift3.1

对于字符串的加密解密,可以给String类扩展方法,方便使用

Swift中使用3DES/sha1/MD5加密解密算法 必须要引入这个库 - 在桥接文件中
#import

3DES的加密是可逆的, sha1和MD5的是不可逆的

extension String {

    /**
     3DES的加密过程 和 解密过程

     - parameter op : CCOperation: 加密还是解密
     CCOperation(kCCEncrypt)加密
     CCOperation(kCCDecrypt) 解密

     - parameter key: 专有的key,一个钥匙一般
     - parameter iv : 可选的初始化向量,可以为nil
     - returns      : 返回加密或解密的参数
     */
    func threeDESEncryptOrDecrypt(op: CCOperation,key: String,iv: String) -> String? {

        // Key
        let keyData: NSData = (key as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
        let keyBytes         = UnsafeMutableRawPointer(mutating: keyData.bytes)

        // 加密或解密的内容
        var data: NSData = NSData()
        if op == CCOperation(kCCEncrypt) {
            data  = (self as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
        }
        else {
            data =  NSData(base64Encoded: self, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)!
        }

        let dataLength    = size_t(data.length)
        let dataBytes     = UnsafeMutableRawPointer(mutating: data.bytes)

        // 返回数据
        let cryptData    = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
        let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes)
        let cryptLength  = size_t(cryptData!.length)

        //  可选 的初始化向量
        let viData :NSData = (iv as NSString).data(using: String.Encoding.utf8.rawValue) as NSData!
        let viDataBytes    = UnsafeMutableRawPointer(mutating: viData.bytes)

        // 特定的几个参数
        let keyLength              = size_t(kCCKeySize3DES)
        let operation: CCOperation = UInt32(op)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithm3DES)
        let options:   CCOptions   = UInt32(kCCOptionPKCS7Padding)

        var numBytesCrypted :size_t = 0

        let cryptStatus = CCCrypt(operation, // 加密还是解密
            algoritm, // 算法类型
            options,  // 密码块的设置选项
            keyBytes, // 秘钥的字节
            keyLength, // 秘钥的长度
            viDataBytes, // 可选初始化向量的字节
            dataBytes, // 加解密内容的字节
            dataLength, // 加解密内容的长度
            cryptPointer, // output data buffer
            cryptLength,  // output data length available
            &numBytesCrypted) // real output data length



        if UInt32(cryptStatus) == UInt32(kCCSuccess) {

            cryptData!.length = Int(numBytesCrypted)
            if op == CCOperation(kCCEncrypt)  {
                let base64cryptString = cryptData?.base64EncodedString(options: .lineLength64Characters)
                return base64cryptString
            }
            else {
                //   let base64cryptString = NSString(bytes: cryptPointer, length: cryptLength, encoding: NSUTF8StringEncoding) as? String  // 用这个会导致返回的JSON数据格式可能有问题,最好不用
                let base64cryptString = NSString(data: cryptData! as Data,  encoding: String.Encoding.utf8.rawValue) as? String
                return base64cryptString
            }
        } else {
            print("Error: \(cryptStatus)")
        }
        return nil
    }


    /*sha1不可逆加密**/
    func sha1() -> String {
        let data = self.data(using: String.Encoding.utf8)!
        var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
        data.withUnsafeBytes {
            _ = CC_SHA1($0, CC_LONG(data.count), &digest)
        }
        let hexBytes = digest.map { String(format: "%02hhx", $0) }
        return hexBytes.joined()
    }


    func MD5() -> String {
        let str = self.cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer.allocate(capacity: digestLen)
        //        let result = UnsafeMutablePointer.init(allocatingCapacity: digestLen)
        CC_MD5(str!, strLen, result)
        let hash = NSMutableString()
        for i in 0 ..< digestLen {
            hash.appendFormat("%02x", result[i])
        }
        result.deinitialize()

        return String(format: hash as String)
    }

}

使用方法:
直接在xib界面拖一个textFiled的控件,然后放置3个按钮,分别是进行MD5、sha1、3DES加密点击方法,然后分别测试加密解密数据

  //3DES
    @IBAction func desButtonClick(_ sender: UIButton) {
        let keyStr = "ns@$65ds$%^^vdiefif934I&^%#46gn1a"
        print("----原密码---**\(tf.text)**")

        /**
         3DES的加密过程 和 解密过程

         - parameter op : CCOperation: 加密还是解密
         CCOperation(kCCEncrypt)加密
         CCOperation(kCCDecrypt) 解密

         - parameter key: 专有的key,一个钥匙一般
         - parameter iv : 可选的初始化向量,可以为nil
         - returns      : 返回加密或解密的参数
         */

        let mi_string = tf.text?.threeDESEncryptOrDecrypt(op: CCOperation(kCCEncrypt), key: keyStr, iv: "")
        print("--加密--mi_string----***\(mi_string)**")

        let ming_string = mi_string?.threeDESEncryptOrDecrypt(op: CCOperation(kCCDecrypt), key: keyStr, iv: "")
        print("--解密--ming_string----***\(ming_string)**")
    }
    
  //sha1
    @IBAction func sha1ButtonClick(_ sender: UIButton) {
        self.view.endEditing(true)
        print("---sha1加密---**\(tf.text)")

        let psw_sha1 = tf.text?.sha1()
        print("---psw_sha1- 加密后的字符串 *****----****\(psw_sha1)")
    }

  //MD5
    @IBAction func MD5ButtonClick(_ sender: UIButton) {
        self.view.endEditing(true)
        print("---MD5加密---**\(tf.text)")

        let psw_MD5 = tf.text?.MD5()
        print("---psw_MD5- 加密后的字符串 *****----****\(psw_MD5)")
    }
重点问题: 如果遇到3DES解密与java后台的不符合或者解密不成功的情况,可能的原因是需要使用3DES+base64进行加密解密

可以参考文章http://www.cnblogs.com/jukaiit/p/5039803.html
使用这个第三方来实现 JKEncrypt
** https://github.com/jukai9316/JKEncrypt。**

你可能感兴趣的:(字符串的加密与解密(3DES、sha1、MD5) - swift3.1)