AES是加密的算法,使用12八、192 和 256 位密鑰,將被加密數據劃分爲128位(16字節)一塊,而後使用某種加密模式進行加密 關鍵詞: 塊大小:16字節 密鑰長度:AES算法下,key的長度有三種:12八、192和256 bits。 加密模式:AES屬於塊加密(Block Cipher),塊加密中有CBC、ECB、CTR、OFB、CFB等幾種工做模式。 填充模式: NoPadding,數據長度不對齊時使用"\0"填充,不然不填充 PKCS7Padding,假設數據長度須要填充n(n>0)個字節纔對齊,那麼填充n個字節,每一個字節都是n;若是數據自己就已經對齊了,則填充一塊長度爲塊大小的數據,每一個字節都是塊大小 PKCS5Padding,PKCS7Padding的子集,塊大小固定爲8字節。 AES加密,若是輸入是16*n字節,NoPadding填充的狀況下,輸出和輸入相同;有填充的狀況下,輸出是16*(n+1)。 若是輸入不是16字節整數倍,而是大於16*n小於16*(n+1),NoPadding填充狀況下(只能是CFB和OFB模式),輸出和輸入長度相同;其餘狀況下,輸出長度是16*(n+1)
#import <CommonCrypto/CommonCrypto.h> #import <CommonCrypto/CommonDigest.h>
//加密 + (NSData *)encryptAES:(NSString *)content key:(NSString *)key { NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger dataLength = contentData.length; // 爲結束符'\\0' +1 char keyPtr[kCCKeySizeAES128 + 1]; memset(keyPtr, 0, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; // 密文長度 <= 明文長度 + BlockSize size_t encryptSize = dataLength + kCCBlockSizeAES128; void *encryptedBytes = malloc(encryptSize); size_t actualOutSize = 0; NSString *const kInitVector = @"1234567890123456"; //16位偏移,CBC模式纔有 NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding]; CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt,//kCCEncrypt 表明加密 kCCDecrypt表明解密 kCCAlgorithmAES,//加密算法 kCCOptionPKCS7Padding, // 系統默認使用 CBC,而後指明使用 PKCS7Padding,iOS只有CBC和ECB模式,若是想使用ECB模式,能夠這樣編寫 kCCOptionPKCS7Padding | kCCOptionECBMode keyPtr,//公鑰 kCCKeySizeAES128,//密鑰長度128 initVector.bytes,//偏移字符串 contentData.bytes,//編碼內容 dataLength,//數據長度 encryptedBytes,//加密輸出緩衝區 encryptSize,//加密輸出緩衝區大小 &actualOutSize);//實際輸出大小 if (cryptStatus == kCCSuccess) { // 返回編碼後的數據 return [NSData dataWithBytesNoCopy:encryptedBytes length:actualOutSize]; } free(encryptedBytes); return nil; }
// 解密 + (NSData *)decryptAESWithData:(NSData *)data key:(NSString *)key{ char keyPtr[kCCKeySizeAES128 + 1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [data length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesDecrypted = 0; NSString *const kInitVector = @"1234567890123456"; //16位偏移,CBC模式纔有 NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding]; //字段含義在上面加密已經解釋過了,這裏不作贅述 CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, keyPtr, kCCBlockSizeAES128, initVector.bytes, [data bytes], dataLength, buffer, bufferSize, &numBytesDecrypted); if(cryptStatus == kCCSuccess){ return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; } free(buffer); return nil; }
//pod引入openssl庫 pod 'OpenSSL-Universal'
#import "crypto.h" #import "evp.h" #import "aes.h" + (NSData *)encryptStringWithString:(NSString *)string key:(NSString *)key{ const char *p_str = [string cStringUsingEncoding:NSUTF8StringEncoding]; const char *p_key = [key cStringUsingEncoding:NSUTF8StringEncoding]; unsigned char *p_out = malloc(string.length + 16); memset(p_out, 0, string.length * 2); int result = aes_encrypt(p_str, (char *)p_key, (unsigned char *)p_out); // NSLog(@"result = %d enOut = %s",result,p_out); NSInteger len = getlen(p_out); NSData *data = [NSData dataWithBytes:p_out length:len]; return data; } + (NSData *)decryptDataWithData:(NSData *)data andKey:(NSString *)key{ const char *p_key = [key cStringUsingEncoding:NSUTF8StringEncoding]; unsigned char *p_out = malloc(data.length*2); memset(p_out, 0, data.length * 2); int result = aes_decrypt((const char *)data.bytes, (char *)p_key, p_out); // NSLog(@"result = %d deOut = %s",result,p_out); NSInteger len = getlen(p_out); NSData *dataOut = [NSData dataWithBytes:p_out length:len]; return dataOut; } /********************************************************** 函數名:PKCS7Padding 參數:unsigned char *str --字符串地址 返回值:int --正向測試填充後的字符串長度 說明:對初始數據進行PKCS7Padding填充 ***********************************************************/ int PKCS7Padding(unsigned char *str){ int remain, i; int len=getlen(str); remain = 16 - len%16; //printf("remain = %d\n",remain); for(i=0; i<remain; i++) { str[len+i] = remain; //printf("str[len+i]= %d\n",str[len+i]); } str[len+i] = '\0'; return len + remain; } /********************************************************** 函數名:DePKCS7Padding 參數:unsigned char *p --字符串地址 返回值:int --反填充個數 說明:對明文進行PKCS7Padding填充反填充(去除後面的填充亂碼) ***********************************************************/ int DePKCS7Padding(unsigned char *str) { int remain,i; while (*str != '\0'){str++;} //定位到\0 str--; remain = *str;//讀取填充的個數 //printf("remain = %d\n",remain); //定位到最前面的填充數 for(i=0;i<remain;i++){str--;} str++; *str = '\0';//截斷 return remain; } /********************************************************** 函數名:getlen 參數:char *result --字符串地址 返回值:int --字符串長度 說明: --獲取字符串長度 ***********************************************************/ int getlen(unsigned char *result){ int i = 0; while (result[i] != '\0'){ i++; } return i; } /********************************************************** 函數名:aes_encrypt 參數:const char* str_in --輸入字符 參數:unsigned char* key --key 參數:unsigned char* out --輸出字符 返回值:int --0失敗 1成功 說明:加密 ***********************************************************/ int aes_encrypt(const char* str_in, char* key, unsigned char* out) { OPENSSL_cleanse(NULL, 0); if (!str_in || !key || !out) return 0; //加密的初始化向量 unsigned char iv[AES_BLOCK_SIZE]; //16位密碼 char tmpIV[] = "1234567890123456"; for (int i = 0; i < 16; ++i) iv[i] = tmpIV[i]; AES_KEY aes; if (AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0) { return 0; } // size_t len = strlen(str_in); unsigned char *aes_encode_temp = malloc(len + 16); memset(aes_encode_temp,'\0', len + 16); memcpy(aes_encode_temp, str_in, len); len = PKCS7Padding(aes_encode_temp); AES_cbc_encrypt((unsigned char*)aes_encode_temp, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT); // for (int nIndex = 0; nIndex < getlen((char *)str_in); nIndex += 16) { // AES_ecb_encrypt((unsigned char*)str_in + nIndex, (unsigned char*)out + nIndex,&aes,AES_ENCRYPT); // } return 1; } /********************************************************** 函數名:aes_decrypt 參數:const char* str_in --輸入 參數:unsigned char* key --key 參數:unsigned char* out --輸出 返回值:int --0失敗 1成功 說明: --解密 ***********************************************************/ int aes_decrypt(const char* str_in, char* key,unsigned char* out) { OPENSSL_cleanse(NULL, 0); if (!str_in || !key || !out) return 0; unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量 char tmpIV[] = "1234567890123456"; for (int i = 0; i < 16; ++i) iv[i] = tmpIV[i]; AES_KEY aes; if (AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0) { return 0; } size_t len = strlen(str_in); // for (int nIndex = 0; nIndex < getlen((char *)str_in); nIndex += 16) { // AES_ecb_encrypt((unsigned char*)str_in + nIndex, (unsigned char*)out + nIndex,&aes,AES_DECRYPT); // } AES_cbc_encrypt((unsigned char*)str_in, (unsigned char*)out, len, &aes, iv, AES_DECRYPT); DePKCS7Padding(out); return 1; }
上述代碼中,把AES-CBC-PKCS7的代碼註釋了。可自行解開註釋獲得此模式的加解密代碼。算法