美文网首页
字符串的加密与解密(3DES、sha1、MD5) - swift

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

作者: JoyGY | 来源:发表于2017-05-23 17:59 被阅读0次

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

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

    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<CUnsignedChar>.allocate(capacity: digestLen)
            //        let result = UnsafeMutablePointer<CUnsignedChar>.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) - swift

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