iOS 中 3DES加密、MD5加密

加密算法通常分为对称性加密算法和非对称性加密算法,以及线性散列算法,对应着比较常见的是 DES,RSA,MD5。

  • 对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行加解密了。
  • 非对称加密算法,发送双方A,B事先均生成一堆密匙,然后A将自己的公有密匙发送给B,B将自己的公有密匙发送给A,如果A要给B发送消 息,则先需要用B的公有密匙进行消息加密,然后发送给B端,此时B端再用自己的私有密匙进行消息解密,B向A发送消息时为同样的道理。
  • 线性散列加密算法, 只生成一串不可逆的密文,经常用其效验数据传输过程中是否经过修改,因为相同的生成算法对于同一明文只会生成唯一的密文,若相同算法生成的密文不同,则证明传输数据进行过了修改。

3DES 和 MD5 是我用到过的,特此记录下。

3DES

3DES是一种基于DES的加密算法,使用3个不同密匙对同一个分组数据块进行3次加密,如此以使得密文强度更高。

当然一般我们现有的涉及到文件/信息加密,或提高数据安全级别一般都会选择 CommonCrypto 来完成任务。

可以从Oc 上面先了解它的函数声明:

CCCryptorStatus CCCrypt(
       CCOperation op,          // operation: kCCEncrypt or kCCDecrypt
       CCAlgorithm alg,         // algorithm: kCCAlgorithmAES128... 
       CCOptions options,       // operation: kCCOptionPKCS7Padding...
       const void *key,         // key
       size_t keyLength,        // key length
       const void *iv,          // initialization vector (optional)
       const void *dataIn,      // input data
       size_t dataInLength,     // input data length
       void *dataOut,           // output data buffer
       size_t dataOutAvailable, // output data length available
       size_t *dataOutMoved)    // real output data length generated
  )

Swift + 3DES

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).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let keyBytes         = UnsafeMutablePointer<Void>(keyData.bytes)
        
        // 加密或解密的内容
        var data: NSData = NSData()
        if op == CCOperation(kCCEncrypt) {
            data  = (self as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        }
        else {
            data =  NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)!
        }
        
        let dataLength    = size_t(data.length)
        let dataBytes     = UnsafeMutablePointer<Void>(data.bytes)
        
        // 返回数据
        let cryptData    = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
        let cryptPointer = UnsafeMutablePointer<Void>(cryptData!.mutableBytes)
        let cryptLength  = size_t(cryptData!.length)
        
        //  可选 的初始化向量
        let viData :NSData = (iv as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let viDataBytes    = UnsafeMutablePointer<Void>(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!.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
                return base64cryptString
            }
            else {
           //   let base64cryptString = NSString(bytes: cryptPointer, length: cryptLength, encoding: NSUTF8StringEncoding) as? String  // 用这个会导致返回的JSON数据格式可能有问题,最好不用
                let base64cryptString = NSString(data: cryptData!,  encoding: NSUTF8StringEncoding) as? String
                return base64cryptString
            }
        } else {
            print("Error: \(cryptStatus)")
        }
        return nil
    }
    

}

补充:
CCOperation(操作)、CCAgorithm(算法) 和 CCOptions(设置)本质上就是 uint32_t(一个占32位存储的 unsigned int),所以我们可以通过 CommonCrypto 常量来构造它们。

let operation = CCOperation(kCCEncrypt)
let algorithm = CCAlgorithm(kCCAlgorithmAES) // 后面算法随你选择
let options = CCOptions(kCCOptionECBMode) // 设置项

附带一个Oc版的 3DES加解密 (此处没有用系统的base64,用的是GTMBase64)

+ (NSString*)TripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt key:(NSString*)key {
    
    
    const void *vplainText;
    size_t plainTextBufferSize;
    
    if (encryptOrDecrypt == kCCDecrypt)
    {
        NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]];
        plainTextBufferSize = [EncryptData length];
        vplainText = [EncryptData bytes];
    }
    else
    {
        NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
        plainTextBufferSize = [data length];
        vplainText = (const void *)[data bytes];
    }
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
 
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
 
    NSString *initVec = @"p2p_s2iv";
    const void *vkey = (const void *) [key UTF8String];
    const void *vinitVec = (const void *) [initVec UTF8String];
    
    ccStatus = CCCrypt(encryptOrDecrypt,
                       kCCAlgorithm3DES,
                       kCCOptionPKCS7Padding,
                       vkey, //"123456789012345678901234", //key
                       kCCKeySize3DES,
                       vinitVec, //"init Vec", //iv,
                       vplainText, //"Your Name", //plainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);

    
    NSString *result;
    
    if (encryptOrDecrypt == kCCDecrypt)
    {
        result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr
                                                                length:(NSUInteger)movedBytes]
                                        encoding:NSUTF8StringEncoding]
                  ;
    }
    else
    {
        NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        result = [GTMBase64 stringByEncodingData:myData];
    }
    
    return result;
    
}

附带一个Swift 版的 Base64 + String

extension String {
    
    //Encode base64
    func base64Encoded() -> String {
        let plainData = self.dataUsingEncoding(NSUTF8StringEncoding)
        let base64String = plainData?.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
        return base64String!
    }
    
    //Decode base64
    func base64Decoded() -> String {
        let decodedData = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters)
        let decodedString = NSString(data: decodedData!, encoding: NSUTF8StringEncoding)
        return decodedString! as String
    }
}

MD5

MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。

swift + MD5

extension String  {
    var MD5: String! {
        let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
        let strLen = CC_LONG(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
        
        CC_MD5(str!, strLen, result)
        
        let hash = NSMutableString()
        for i in 0..<digestLen {
            hash.appendFormat("%02x", result[i])
        }
        
        result.dealloc(digestLen)
        
        return String(format: hash as String)
    }
}

Oc + MD5

// 注意导入
#import <CommonCrypto/CommonDigest.h>
- (NSString *)MD5Hash
{
    const char *cStr = [self UTF8String];
    unsigned char result[16];
    CC_MD5(cStr, (unsigned)strlen(cStr), result);
    return [NSString stringWithFormat:
            @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            result[0], result[1], result[2], result[3], 
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]];
}

一定要注意, Swift 剔除了 Objective-C 中属于 C 的部分,因此我们需要做一些准备工作才能在 Swift 和 Cocoa 中使用 CommonCrypto,我们需要在Bridging-Header.h 中加入#import <CommonCrypto/CommonCrypto.h>

备注参考

http://www.cnblogs.com/yangywyangyw/archive/2012/07/31/2620861.html
http://stackoverflow.com/questions/25754147/issue-using-cccrypt-commoncrypt-in-swift
http://www.itupup.com/?it09/525141.htm

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 随着对于安全度的不断要求,对于数据加解密与破解之间的斗争,加解密的方式也在不断发生着变化,来看看现在流行的一些加解...
    zhouhao_180阅读 6,406评论 1 12
  • 这篇文章不是研究性的东西,主要是简单的一些知识, 开篇如此, 我尽量不让读者失望。 首先罗列一些知识点:1.加密算...
    SOI阅读 12,070评论 3 70
  • 本文主要介绍移动端的加解密算法的分类、其优缺点特性及应用,帮助读者由浅入深地了解和选择加解密算法。文中会包含算法的...
    苹果粉阅读 13,959评论 5 29
  • 还记得孩子时候的我特别爱幻想,每个女孩小的时候都特别期待白马王子,骑着一匹雪白的马,走在绿绿的草地上,缓缓的向...
    梦雅星辰阅读 2,118评论 0 0
  • this对象 this总是返回一个对象,也就是返回属性或者方法当前所在的对象。可以近似地认为,this是所有函数在...
    LeoCong阅读 1,371评论 0 0