iOS:密码学(对称加密)

Page content

数据的加密方和解密方共用一个相同的密钥来进行对数据的加解密

概要

本篇内容主要说明对称加密算法(AES)的使用。

算法特点

  1. 传统加密算法,加密可逆(解密);
  2. 加密和解密使用同一个密钥(密钥的保密从而变得尤为重要,密钥一般会定期更换)。

经典算法

  1. DES:数据加密标准(加密强度不够,用的较少);
  2. 3DES:使用三个密钥,对相同的数据进行三次加密(密钥管理非常麻烦,用的较少);
  3. AES:高级密码标准(美国国家安全局加密标准,现有手段暴力破解需要2000万年)。

加密方式

  1. ECB:电子代码本,每一个数据块独立加密;
  2. CBC:密码块链,使用一个密钥和一个初始化向量(IV)对数据进行加密。每一个数据块的加密依赖于上一个数据块。

AES

实现说明

  1. 支持的AES key size 有 128位,192位,256位;
  2. 数据填充方式:kCCOptionPKCS7Padding;
  3. 分组模式:cbc, ecb,具体实现封装为NSData的Category;

先引入头文件:

~~~objective-c
#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>
~~~

CBC加密

AES CBC模式加密需要一个key和一个向量iv;

key 长度16字节,24字节,32字节,iv 16字节:

~~~objective-c
/**
 AES cbc 加密
 
 @param key 长度16字节,24字节,32字节
 @param iv 16字节
 @return 加密结果data
 */
- (NSData *)AESCBCEncryptWith:(NSData *)key iv:(NSData *)iv {
    
    NSData *retData = nil;
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    bzero(buffer, bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding,
                                          key.bytes, key.length,
                                          iv.bytes,
                                          self.bytes, self.length,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        retData = [NSData dataWithBytes:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return retData;
    
}
~~~

CBC解密

```objective-c
/**
 AES cbc 解密
 
 @param key 长度16字节,24字节,32字节
 @param iv 16字节
 @return 解密结果data
 */
- (NSData *)AESCBCDecryptWith:(NSData *)key iv:(NSData *)iv {
    
    NSData *retData = nil;
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    bzero(buffer, bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding,
                                          key.bytes, key.length,
                                          iv.bytes,
                                          self.bytes, self.length,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        retData = [NSData dataWithBytes:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return retData;
}
```

ECB加密

```objective-c
/**
 AES ecb 加密
 
 @param key 长度16字节,24字节,32字节
 @return 加密结果data
 */
- (NSData *)AESECBEncryptWith:(NSData *)key {
    
    NSData *retData = nil;
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    bzero(buffer, bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding|kCCOptionECBMode,
                                          key.bytes, key.length,
                                          NULL,
                                          self.bytes, self.length,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        retData = [NSData dataWithBytes:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return retData;
}
```

ECB解密

```objective-c
/**
 AES ecb 解密
 
 @param key 长度16字节,24字节,32字节
 @return 解密结果data
 */
- (NSData *)AESECBDecryptWith:(NSData *)key {
    
    NSData *retData = nil;
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    bzero(buffer, bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding|kCCOptionECBMode,
                                          key.bytes, key.length,
                                          NULL,
                                          self.bytes, self.length,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        retData = [NSData dataWithBytes:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return retData;
}
```

总结

对称加密是一种高效的加密方式,AES加密方式是其中最为安全有效的一种;

但由于对称加密的特点:加密方和解密方共用同一个密钥进行加解密操作,因此对于密钥的保存尤为重要,在实际生产环境中,经常配合RSA进行体系加密,由RSA加密AES的key,发放到客户端解密,客户端拿到key后再进行AES的加密传输。