高級(jí)加密標(biāo)準(zhǔn)(英語:Advanced Encryption Standard素挽,縮寫:AES)蔑赘,在密碼學(xué)中又稱Rijndael加密法,是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。
iOS開發(fā)之Objective-c的AES加密和解密算法的實(shí)現(xiàn)
Rijndael密碼的設(shè)計(jì)力求滿足以下3條標(biāo)準(zhǔn):
1. 抵抗所有已知的攻擊米死。
2. 在多個(gè)平臺(tái)上速度快锌历,編碼緊湊。
3. 設(shè)計(jì)簡(jiǎn)單峦筒。
當(dāng)前的大多數(shù)分組密碼究西,其輪函數(shù)是Feistel結(jié)構(gòu)。Rijndael沒有這種結(jié)構(gòu)物喷。
1.NSData加密
NSData+AES256.h中
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
@interface NSData (AES256)
-(NSData *) aes256_encrypt:(NSString *)key;
-(NSData *) aes256_decrypt:(NSString *)key;
@end
NSData+AES256.m中
#import "NSData+AES256.h"
@implementation NSData (AES256)
// 加密
- (NSData *)aes256_encrypt:(NSString *)key{
char keyPtr[kCCKeySizeAES256 + 1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
// CCCryptorStatus cryptStatus1 = CCCrypt(<#CCOperation op#>, <#CCAlgorithm alg#>, <#CCOptions options#>, <#const void *key#>, <#size_t keyLength#>, <#const void *iv#>, <#const void *dataIn#>, <#size_t dataInLength#>, <#void *dataOut#>, <#size_t dataOutAvailable#>, <#size_t *dataOutMoved#>)
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [self bytes], dataLength, buffer, bufferSize, &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
// 解密
- (NSData *)aes256_decrypt:(NSString *)key{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
@end
2.NSString加密
NSString+AES256.h中
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import "NSData+AES256.h"
@interface NSString (AES256)
-(NSString *) aes256_encrypt:(NSString *)key;
-(NSString *) aes256_decrypt:(NSString *)key;
@end
NSString+AES256.m中
#import "NSString+AES256.h"
@implementation NSString (AES256)
// 加密
- (NSString *) aes256_encrypt:(NSString *)key{
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
//對(duì)數(shù)據(jù)進(jìn)行加密
NSData *result = [data aes256_encrypt:key];
//轉(zhuǎn)換為2進(jìn)制字符串
if (result && result.length > 0) {
Byte *datas = (Byte*)[result bytes];
NSMutableString *output = [NSMutableString stringWithCapacity:result.length * 2];
for(int i = 0; i < result.length; i++){
[output appendFormat:@"%02x", datas[i]];
}
return output;
}
return nil;
}
// 解密
-(NSString *) aes256_decrypt:(NSString *)key{
//轉(zhuǎn)換為2進(jìn)制Data
NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [self length] / 2; i++) {
byte_chars[0] = [self characterAtIndex:i*2];
byte_chars[1] = [self characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
//對(duì)數(shù)據(jù)進(jìn)行解密
NSData* result = [data aes256_decrypt:key];
if (result && result.length > 0) {
return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
}
return nil;
}
@end
3.加密卤材、解密的使用
NSString *userName = @"userName:Coder_Sun";
NSLog(@"加密前的字符串:%@",userName);
NSString *string = [userName aes256_encrypt:@"Coder"];
NSLog(@"加密后的字符串:%@",string);
NSLog(@"%lu",(unsigned long)string.length); // 打印加密后的字符串的位數(shù)
NSString *string1 = [string aes256_decrypt:@"Coder"];
NSLog(@"解密后的字符串:%@",string1);
代碼已經(jīng)上傳至git:
--> 傳送門:https://github.com/272095249/AES.git
補(bǔ)充:
加密算法原理:
AES算法基于排列和置換運(yùn)算。排列是對(duì)數(shù)據(jù)重新進(jìn)行安排峦失,置換是將一個(gè)數(shù)據(jù)單元替換為另一個(gè)扇丛。AES 使用幾種不同的方法來執(zhí)行排列和置換運(yùn)算。
AES是一個(gè)迭代的尉辑、對(duì)稱密鑰分組的密碼帆精,它可以使用128、192 和 256 位密鑰隧魄,并且用 128 位(16字節(jié))分組加密和解密數(shù)據(jù)卓练。與公共密鑰密碼使用密鑰對(duì)不同,對(duì)稱密鑰密碼使用相同的密鑰加密和解密數(shù)據(jù)购啄。通過分組密碼返回的加密數(shù)據(jù)的位數(shù)與輸入數(shù)據(jù)相同
加密模式:
| 加密模式 | 優(yōu)點(diǎn) | 缺點(diǎn) |
| ------------- |::-------------:|: -------------:|
| ECB模式 | <ol><li>簡(jiǎn)單</li><li> 有利于并行計(jì)算</li><li>誤差不會(huì)被傳送</li></ol>|<ol><li>不能隱藏明文的模式</li><li> 可能對(duì)明文進(jìn)行主動(dòng)攻擊</li></ol>|
| CBC模式 | <ol><li>不容易主動(dòng)攻擊,安全性好于ECB,適合傳輸長(zhǎng)度長(zhǎng)的報(bào)文,是SSL襟企、IPSec的標(biāo)準(zhǔn)</li><ol> |<ol><li>不利于并行計(jì)算</li><li>誤差傳遞</li><li>需要初始化向量IV</li></ol>|
| CFB模式 | <ol><li>隱藏了明文模式</li><li>分組密碼轉(zhuǎn)化為流模式</li><li>可以及時(shí)加密傳送小于分組的數(shù)據(jù)</li></ol>|<ol><li>不利于并行計(jì)算</li><li>誤差傳送:一個(gè)明文單元損壞影響多個(gè)單元</li><li>唯一的IV</li>|
| ofb模式 |<ol><li>隱藏了明文模式</li><li>分組密碼轉(zhuǎn)化為流模式</li><li>可以及時(shí)加密傳送小于分組的數(shù)據(jù)</li></ol>|<ol><li>不利于并行計(jì)算</li><li>對(duì)明文的主動(dòng)攻擊是可能的</li><li>誤差傳送:一個(gè)明文單元損壞影響多個(gè)單元</li></ol>|