1. 程式人生 > >AES CBC加密/解密

AES CBC加密/解密

簡介

高階加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高階加密標準由美國國家標準與技術研究院(NIST)於2001年11月26日釋出於FIPS PUB 197,並在2002年5月26日成為有效的標準。2006年,高階加密標準已然成為對稱金鑰加密中最流行的演算法之一。

AES-128-CBC是一種分組對稱加密演算法,即用同一組key進行明文和密文的轉換,以128bit為一組,128bit==16Byte,意思就是明文的16位元組為一組對應加密後的16位元組的密文。
若最後剩餘的明文不夠16位元組,需要進行填充,通常採用PKCS7進行填充。比如最後缺3個位元組,則填充3個位元組的0x03;若最後缺10個位元組,則填充10個位元組的0x0a;
若明文正好是16個位元組的整數倍,最後要再加入一個16位元組0x10的組再進行加密

背景

最近開發數字貨幣個人交易錢包,需要對相關敏感資料加密。其中就使用AES 演算法實現相關加密、解密。
NSData+AES.h檔案如下:

//
//  NSData+AES.h
//  cmd-test
//
//  Created by vincent on 2018/11/14.
//  Copyright © 2018年 vincent. All rights reserved.
//

#import <Foundation/Foundation.h>

/**
 *AES 加密/解密
 *AES128 加密/解密 key 必須是16位元組(128 = 16 * 8)
 * 如果需要AES256 加密/解密 key 必須是32位元組(256 = 32 * 8)
 */


typedef NS_ENUM(NSUInteger, AESLengthType) {
    AES128Type,
    AES256Type,
};



@interface NSData (AES)

/**
 *@param    key        加密金鑰
 *@param    type       AES128/AES256型別
 *@param    iv          cbc加解密資料
 **/
-(NSData *)aesEncryptWithKey:(NSData *)key type:(AESLengthType)type initVector:(NSData *)iv;


-(NSData *)aesDecryptWithKey:(NSData *)key type:(AESLengthType)type initVector:(NSData *)iv;


@end

NSData+AES.m檔案如下:

//
//  NSData+AES.m
//  cmd-test
//
//  Created by vincent on 2018/11/14.
//  Copyright © 2018年 vincent. All rights reserved.
//

#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>


@implementation NSData (AES)


-(NSData *)cipherOperationWithKey:(NSData *)key keyLength:(int)len initVector:(NSData *)iv operation:(CCOperation)op{
    
    NSUInteger dataLength = self.length;
    
    void const *initVectorBytes = iv.bytes;
    void const *contentBytes = self.bytes;
    void const *keyBytes = key.bytes;
    
    size_t kKeySize = len;
    
    size_t operationSize = dataLength + kCCBlockSizeAES128;
    void *operationBytes = malloc(operationSize);
    if (operationBytes == NULL) {
        return nil;
    }
    size_t actualOutSize = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(op,
                                          kCCAlgorithmAES,
                                          kCCOptionPKCS7Padding,
                                          keyBytes,
                                          kKeySize,
                                          initVectorBytes,
                                          contentBytes,
                                          dataLength,
                                          operationBytes,
                                          operationSize,
                                          &actualOutSize);
    
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:operationBytes length:actualOutSize];
    }
    free(operationBytes);
    operationBytes = NULL;
    return nil;
}

-(NSData *)aesEncryptWithKey:(NSData *)key type:(AESLengthType)type initVector:(NSData *)iv{
    int len = type == AES128Type ? kCCKeySizeAES128 : kCCKeySizeAES256;
    NSString *hint = [NSString stringWithFormat:@"The key size of AES-%d should be %d bytes!", len * 8, len];
    NSCAssert(key.length == len, hint);
    return [self cipherOperationWithKey:key keyLength:len initVector:iv operation:kCCEncrypt];
}


-(NSData *)aesDecryptWithKey:(NSData *)key type:(AESLengthType)type initVector:(NSData *)iv{
    int len = type == AES128Type ? kCCKeySizeAES128 : kCCKeySizeAES256;
    NSString *hint = [NSString stringWithFormat:@"The key size of AES-%d should be %d bytes!", len * 8, len];
    NSCAssert(key.length == len, hint);
    return [self cipherOperationWithKey:key keyLength:len initVector:iv operation:kCCDecrypt];
}




@end

我們對NSData 新增分類實現對NSData 資料的加密解密!