iOS 对称加解密之AES

本篇将要说的是iPhone系统自带的对称加解密函数;

对称加解密:

i. DES 数据加密标准
ii. 3DES 同DES,只是采用了3个key进行了多次运算
iii. AES 高级密码标准
DES是早期的数据加密标准,AES是高级加密标准,而3DES是DES向AES转型的中间过渡产物;

下面就说下AES:
首先,如果需要使用AES,那么至少需要3个参数:
1、带加密原文 text
2、加密使用的key
3、填充向量 iv

一、引入加密头文件

//加密库
#import <CommonCrypto/CommonCryptor.h>

二、实现AES加密

//AES 加密
- (NSString *)aesEnc:(NSData *)data key:(NSData *)key iv:(NSData *)iv {
    if ([iv length] != 16) {
        NSLog(@"iv length error!");
        return nil;
    }
    if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) {
        NSLog(@"key length error!");
        return nil;
    }

    size_t bufferSize = [data length] + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t encrySize = 0;
    CCCryptorStatus status = CCCrypt(kCCEncrypt,
                                     kCCAlgorithmAES128,
                                     kCCOptionPKCS7Padding,
                                     [key bytes],
                                     [key length],
                                     [iv bytes],
                                     [data bytes],
                                     [data length],
                                     buffer,
                                     bufferSize,
                                     &encrySize);
    if (status!= kCCSuccess) {
        free(buffer);
        return nil;
    }
    NSData *dataResult = [NSData dataWithBytes:buffer length:encrySize];
    NSString *res = [[NSString alloc]initWithData:dataResult encoding:NSUTF8StringEncoding];
    NSLog(@"result-enc-source-:%@",res);
    NSString *result = [dataResult base64EncodedStringWithOptions:0];
    NSLog(@"result--enc-base64-:%@",result);
    free(buffer);
    return result;
}

三、实现AES解密

//AES 解密
- (NSString *)aesDenc:(NSData *)data key:(NSData *)key iv:(NSData *)iv {
    if ([iv length] != 16) {
        NSLog(@"iv length error!");
        return nil;
    }
    if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) {
        NSLog(@"key length error!");
        return nil;
    }

    size_t bufferSize = [data length] + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t encrySize = 0;
    CCCryptorStatus status = CCCrypt(kCCDecrypt,
                                     kCCAlgorithmAES128,
                                     kCCOptionPKCS7Padding,
                                     [key bytes],
                                     [key length],
                                     [iv bytes],
                                     [data bytes],
                                     [data length],
                                     buffer,
                                     bufferSize,
                                     &encrySize);
    if (status!= kCCSuccess) {
        free(buffer);
        return nil;
    }
    NSData *dataResult = [NSData dataWithBytes:buffer length:encrySize];
    NSString *res = [[NSString alloc]initWithData:dataResult encoding:NSUTF8StringEncoding];
    NSLog(@"result-enc-source-:%@",res);
    NSString *result = [dataResult base64EncodedStringWithOptions:0];
    NSLog(@"result--aes-base64-:%@",result);
    free(buffer);

    return result;
}

四、总结

AES对称加解密主要调用的是系统函数:

CCCryptorStatus CCCrypt(
    CCOperation op,         /* kCCEncrypt, etc. */
    CCAlgorithm alg,        /* kCCAlgorithmAES128, etc. */
    CCOptions options,      /* kCCOptionPKCS7Padding, etc. */
    const void *key,
    size_t keyLength,
    const void *iv,         /* optional initialization vector */
    const void *dataIn,     /* optional per op and alg */
    size_t dataInLength,
    void *dataOut,          /* data RETURNED here */
    size_t dataOutAvailable,
    size_t *dataOutMoved)
    __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);

通过函数可以看到该函数总共需要11个参数,但是这些参数并不麻烦
第一个参数为枚举型(加密 | 解密):

enum {
    kCCEncrypt = 0, 
    kCCDecrypt,     
};
typedef uint32_t CCOperation;

第二个参数:对称加密算法(支持多种算法)

enum {
    kCCAlgorithmAES128 = 0,
    kCCAlgorithmAES = 0,
    kCCAlgorithmDES,
    kCCAlgorithm3DES,       
    kCCAlgorithmCAST,       
    kCCAlgorithmRC4,
    kCCAlgorithmRC2,   
    kCCAlgorithmBlowfish    
};
typedef uint32_t CCAlgorithm;

第三个参数:加密模式 (ECB | CBC)

enum {
    /* options for block ciphers */
    kCCOptionPKCS7Padding   = 0x0001,
    kCCOptionECBMode        = 0x0002
    /* stream ciphers currently have no options */
};
typedef uint32_t CCOptions;

第四、五个参数:加密key及其长度 (加密种子)

//该数据的长度为特定值,根据实际情况选用

enum {
    kCCKeySizeAES128          = 16,
    kCCKeySizeAES192          = 24,
    kCCKeySizeAES256          = 32,
    kCCKeySizeDES             = 8,
    kCCKeySize3DES            = 24,
    kCCKeySizeMinCAST         = 5,
    kCCKeySizeMaxCAST         = 16,
    kCCKeySizeMinRC4          = 1,
    kCCKeySizeMaxRC4          = 512,
    kCCKeySizeMinRC2          = 1,
    kCCKeySizeMaxRC2          = 128,
    kCCKeySizeMinBlowfish     = 8,
    kCCKeySizeMaxBlowfish     = 56,
};

第六个参数:填充向量iv

    @param      iv              Initialization vector, optional. Used for 
                                Cipher Block Chaining (CBC) mode. If present, 
                                must be the same length as the selected 
                                algorithm's block size. If CBC mode is
                                selected (by the absence of any mode bits in 
                                the options flags) and no IV is present, a 
                                NULL (all zeroes) IV will be used. This is 
                                ignored if ECB mode is used or if a stream 
                                cipher algorithm is selected. For sound encryption,
                                always initialize IV with random data.

第七、八个参数:输入数据

第七个参数传入带加密原文数据;
第八个参数带加密数据长度;

第九个参数:输出数据存储区

//存储加密或解密后的数据;
void *buffer = malloc(bufferSize);

第十个参数:原数据+扩展长度

//dataOutAvailable The size of the dataOut buffer in bytes.
//初始化数据长度
    size_t bufferSize = [data length] + kCCBlockSizeAES128;

第十一个参数:返回数据实际长度

//最终需要的数据长度
//dataOutMoved    On successful return, the number of bytes
                    written to dataOut. If kCCBufferTooSmall is
                returned as a result of insufficient buffer
                space being provided, the required buffer space
                is returned here. 

至此,所有步骤都已说明;

点赞