Swift009-加密

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)    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容