-
對(duì)稱加密 - 傳統(tǒng)加密算法##
- 加密和解密使用同一個(gè)"密鑰"!
- 密鑰的保密工作就非常的重要!! 密鑰會(huì)定期更換!密鑰的管理很重要!!
-
經(jīng)典算法
- DES 數(shù)據(jù)加密標(biāo)準(zhǔn)(用的比較少,因?yàn)閺?qiáng)度不夠).
- 3DES 使用3個(gè)密鑰,對(duì)相同的數(shù)據(jù)執(zhí)行三次加密,強(qiáng)度增強(qiáng).
- AES 高級(jí)加密標(biāo)準(zhǔn),也是目前使用最多的對(duì)稱加密算法,目前美國(guó)國(guó)家安全局使用AES加密,蘋果的鑰匙串訪問就是使用AES加密
-
兩種加密方式 (ECB和CBC)
- ECB: 電子代碼本,就是將一個(gè)數(shù)據(jù)拆分為多塊,然后獨(dú)立加密的!
- CBC: 密碼塊鏈,使用一個(gè)密鑰和一個(gè)初始化"向量"對(duì)數(shù)據(jù)執(zhí)行加密轉(zhuǎn)換滥搭,能保證密文的完整性,如果一個(gè)數(shù)據(jù)發(fā)生改變,后面所有的數(shù)據(jù)將會(huì)被破壞!
向量:某個(gè)方向的數(shù)量.
現(xiàn)代的密碼學(xué)都和幾何有關(guān)!因?yàn)閹缀?包含圓形\橢圓\球體)的變量是有規(guī)律的,但是結(jié)果是多變的!
-
終端測(cè)試
接下來(lái)我們分別使用 DES和AES兩種算法的兩種加密方式來(lái)終端測(cè)試一下艾猜。
/**
* 終端測(cè)試指令
*
* DES(ECB)加密
* $ echo -n 加密的內(nèi)容如:(hello) | openssl enc -des-ecb -K Key的ASCII碼如:(abc=616263) -nosalt | base64
*
* DES(CBC)加密
* $ echo -n 加密的內(nèi)容如:(hello) | openssl enc -des-cbc -iv 初始化向量(8個(gè)字節(jié))如:0102030405060708 -K Key的ASCII碼如:(abc=616263) -nosalt | base64
*
* AES(ECB)加密
* $ echo -n 加密的內(nèi)容如:(hello) | openssl enc -aes-128-ecb -K Key的ASCII碼如:(abc=616263) -nosalt | base64
*
* AES(CBC)加密
* $ echo -n 加密的內(nèi)容如:(hello) | openssl enc -aes-128-cbc -iv 初始化向量(8個(gè)字節(jié))如:0102030405060708 -K Key的ASCII碼如:(abc=616263) -nosalt | base64
*
* DES(ECB)解密
* $ echo -n 解密的內(nèi)容如:(HQr0Oij2kbo=) | base64 -D | openssl enc -des-ecb -K Key的ASCII碼如:(abc=616263) -nosalt -d
*
* DES(CBC)解密
* $ echo -n 解密的內(nèi)容如:(alvrvb3Gz88=) | base64 -D | openssl enc -des-cbc -iv 初始化向量(8個(gè)字節(jié))如:0102030405060708 -K Key的ASCII碼如:(abc=616263) -nosalt -d
*
* AES(ECB)解密
* $ echo -n 解密的內(nèi)容如:(d1QG4T2tivoi0Kiu3NEmZQ==) | base64 -D | openssl enc -aes-128-ecb -K Key的ASCII碼如:(abc=616263) -nosalt -d
*
* AES(CBC)解密
* $ echo -n 解密的內(nèi)容如:(u3W/N816uzFpcg6pZ+kbdg==) | base64 -D | openssl enc -aes-128-cbc -iv 初始化向量(8個(gè)字節(jié))如:0102030405060708 -K Key的ASCII碼如:(abc=616263) -nosalt -d
*
* 提示:
* 1> 加密過程是先加密拷肌,再base64編碼
* 2> 解密過程是先base64解碼黔攒,再解密
*/
-
OC中具體的代碼實(shí)現(xiàn)
首先新建一個(gè)工具類 (EncryptionTools)EncryptionTools.h
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>
@interface EncryptionTools : NSObject
+ (instancetype)sharedEncryptionTools;
/**
@constant kCCAlgorithmAES 高級(jí)加密標(biāo)準(zhǔn),128位(默認(rèn))
@constant kCCAlgorithmDES 數(shù)據(jù)加密標(biāo)準(zhǔn)
*/
@property (nonatomic, assign) uint32_t algorithm;
/**
* 加密字符串并返回base64編碼字符串
*
* @param string 要加密的字符串
* @param keyString 加密密鑰
* @param iv 初始化向量(8個(gè)字節(jié))
*
* @return 返回加密后的base64編碼字符串
*/
- (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
/**
* 解密字符串
*
* @param string 加密并base64編碼后的字符串
* @param keyString 解密密鑰
* @param iv 初始化向量(8個(gè)字節(jié))
*
* @return 返回解密后的字符串
*/
- (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
@end
EncryptionTools.m
#import "EncryptionTools.h"
@interface EncryptionTools()
@property (nonatomic, assign) int keySize;
@property (nonatomic, assign) int blockSize;
@end
@implementation EncryptionTools
+ (instancetype)sharedEncryptionTools {
static EncryptionTools *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
instance.algorithm = kCCAlgorithmAES;
});
return instance;
}
- (void)setAlgorithm:(uint32_t)algorithm {
_algorithm = algorithm;
switch (algorithm) {
case kCCAlgorithmAES:
self.keySize = kCCKeySizeAES128;
self.blockSize = kCCBlockSizeAES128;
break;
case kCCAlgorithmDES:
self.keySize = kCCKeySizeDES;
self.blockSize = kCCBlockSizeDES;
break;
default:
break;
}
}
- (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
// 設(shè)置秘鑰
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
uint8_t cKey[self.keySize];
bzero(cKey, sizeof(cKey));
[keyData getBytes:cKey length:self.keySize];
// 設(shè)置iv
/*
kCCOptionPKCS7Padding CBC 的加密方式
kCCOptionPKCS7Padding | kCCOptionECBMode ECB 的加密方式
*/
uint8_t cIv[self.blockSize];
bzero(cIv, self.blockSize);
int option = 0;
if (iv) {
[iv getBytes:cIv length:self.blockSize];
option = kCCOptionPKCS7Padding;
} else {
option = kCCOptionPKCS7Padding | kCCOptionECBMode;
}
// 設(shè)置輸出緩沖區(qū)
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
size_t bufferSize = [data length] + self.blockSize;
void *buffer = malloc(bufferSize);
// 開始加密
size_t encryptedSize = 0;
/***
CCCrypt 對(duì)稱加密算法的核心函數(shù)(加密/解密)
參數(shù):
1.kCCEncrypt 加密/kCCDecrypt 解密
2.加密算法,默認(rèn)使用的是 AES/DES
3.加密選項(xiàng) ECB/CBC
kCCOptionPKCS7Padding CBC 的加密方式
kCCOptionPKCS7Padding | kCCOptionECBMode ECB 的加密方式
4.加密密鑰
5.密鑰長(zhǎng)度
6.iv 初始化向量,ECB 不需要指定
7.加密的數(shù)據(jù)
8.加密的數(shù)據(jù)的長(zhǎng)度
9.密文的內(nèi)存地址
10.密文緩沖區(qū)的大小
11.加密結(jié)果大小
*/
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
self.algorithm,
option,
cKey,
self.keySize,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&encryptedSize);
NSData *result = nil;
if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
} else {
free(buffer);
NSLog(@"[錯(cuò)誤] 加密失敗|狀態(tài)編碼: %d", cryptStatus);
}
return [result base64EncodedStringWithOptions:0];
}
- (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
// 設(shè)置秘鑰
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
uint8_t cKey[self.keySize];
bzero(cKey, sizeof(cKey));
[keyData getBytes:cKey length:self.keySize];
// 設(shè)置iv
uint8_t cIv[self.blockSize];
bzero(cIv, self.blockSize);
int option = 0;
if (iv) {
[iv getBytes:cIv length:self.blockSize];
option = kCCOptionPKCS7Padding;
} else {
option = kCCOptionPKCS7Padding | kCCOptionECBMode;
}
// 設(shè)置輸出緩沖區(qū)
NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
size_t bufferSize = [data length] + self.blockSize;
void *buffer = malloc(bufferSize);
// 開始解密
size_t decryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
self.algorithm,
option,
cKey,
self.keySize,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&decryptedSize);
NSData *result = nil;
if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
} else {
free(buffer);
NSLog(@"[錯(cuò)誤] 解密失敗|狀態(tài)編碼: %d", cryptStatus);
}
return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
}
@end
使用工具類加密和解密
//AES - ECB 加密
NSString * key = @"hk";
NSLog(@"加密: %@",[[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:nil]);
NSLog(@"解密: %@",[[EncryptionTools sharedEncryptionTools] decryptString:@"cKRPM1ALLG+0q5qCjADoaQ==" keyString:key iv:nil]);
//AES - CBC 加密
uint8_t iv[8] = {2,3,4,5,6,7,0,0}; //直接影響加密結(jié)果!
NSData * ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
NSLog(@"CBC加密: %@",[[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:ivData]);
NSLog(@"CBC解密: %@", [[EncryptionTools sharedEncryptionTools] decryptString:@"+dv/u4juE0WE3S9XSFyibA==" keyString:key iv:ivData]);
//DES - ECB 加密
[EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
NSLog(@"DES 加密%@",[[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:nil]);
NSLog(@"DES 解密: %@", [[EncryptionTools sharedEncryptionTools] decryptString:@"vTuv8E5AlWQ=" keyString:key iv:nil]);