在密碼學(xué)中,加密部分主要分為對(duì)稱加密和非對(duì)稱加密,非對(duì)稱加密主要有RSA非對(duì)稱加密(使用公鑰/私鑰來加密解密),對(duì)稱加密主要有DES/3DES/AES對(duì)稱加密算法,順帶提一下我們今天介紹的Hash算法,Hash屬于一種消息摘要算法,不屬于加密算法,但是由于其單向運(yùn)算,不可逆性,所以Hash是加密算法中的構(gòu)成部分,Hash算法主要有MD5/Sha1/Sha2,這幾個(gè)只是Hash算法加密精度有所不同。
那么緊接之前的非對(duì)稱加密RSA,直接上這次的干貨部分
1、Hash概述2、數(shù)字簽名3、對(duì)稱加密算法簡介4、對(duì)稱加密算法終端命令? ? 5、對(duì)稱加密算法終端演練6、對(duì)稱加密算法代碼演練7、CCCrypt函數(shù)復(fù)制代碼
一、Hash概述
1、Hash的概念
Hash, 一般翻譯為'散列', 也有直接音譯的'哈希',就是把任意長度的輸入,通過散列算法變換成固定長度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是散列值的空間通常小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值。簡單說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。
2、Hash特點(diǎn)
1、算法是公開的2、對(duì)相同的數(shù)據(jù)運(yùn)算,得到的結(jié)果是一樣的3、對(duì)于不同的數(shù)據(jù)運(yùn)算,如MD5(Hash算法的一種)的到的結(jié)果默認(rèn)是128位的,32個(gè)字符(16進(jìn)制標(biāo)識(shí))4、沒法逆運(yùn)算(因?yàn)楣V凳怯成潢P(guān)系,會(huì)存在散列碰撞【即:無限個(gè)數(shù)據(jù)加密得到有限個(gè)數(shù)據(jù),就存在一個(gè)或許多個(gè)數(shù)據(jù)存在同樣的哈希值】)5、信息摘要,信息’指紋‘,一般是用來做數(shù)據(jù)識(shí)別的(由于沒法做逆運(yùn)算,所以一般不會(huì)用來做加密數(shù)據(jù),只是把數(shù)據(jù)的哈希值取到,然后用來對(duì)比,做數(shù)據(jù)識(shí)別的)復(fù)制代碼
3、Hash函數(shù)(單向散列函數(shù))
1、MD5(Message Digest Algorithm 5)2、SHA(Secure Hash Algorithm)? SHA又分為:? SHA-1? SHA-2系列(224,256,384,512,512/224,512/256統(tǒng)稱為SHA-2系列)3、MAC(Message Authentication Code)4、CRC(Cyclic Redundancy Check)5、SM3(國產(chǎn)哈希算法)復(fù)制代碼
4、Hash用途
1、用戶密碼的加密2、搜索引擎3、版權(quán)4、數(shù)字簽名(應(yīng)用簽名)復(fù)制代碼
5、HMAC
什么是HMAC?HMAC(Hash-based message authentication code)是一種使用Hash函數(shù)(單向散列函數(shù))來構(gòu)造消息認(rèn)證碼的方法,利用哈希算法,以一個(gè)密鑰和一個(gè)消息為輸入,生成一個(gè)消息摘要作為輸出。主要是為了能讓人對(duì)對(duì)方身份正確性和消息有效性進(jìn)行驗(yàn)證,與消息摘要的最大不同,就是有簽名密鑰!
HMAC通過兩次hash兩個(gè)不同的key來生成。 目前還沒有發(fā)現(xiàn)有任何的方法來產(chǎn)生碰撞。
HMAC中所使用的單向散列函數(shù)并不僅限于一種,任何高強(qiáng)度的Hash函數(shù)(單向散列函數(shù))都可以被用于HMAC。
比如使用SHA-1、SHA-224、SHA-256、SHA-384、SHA-512所構(gòu)造的HMAC,分別稱為HMAC-SHA1、HMAC-SHA-224、HMAC-SHA-384、HMAC-SHA-512。
二、數(shù)字簽名
1、什么是數(shù)字簽名
數(shù)字簽名就是用于鑒別數(shù)字信息的方法;
2、數(shù)字簽名
下面我們以電商支付金額這個(gè)場景來描述數(shù)字簽名的具體意義:
圖示中,經(jīng)過RSA加密的原商品信息Hash值這個(gè)整體就叫做數(shù)字簽名。
三、對(duì)稱加密概述
1、對(duì)稱加密算法定義:
對(duì)稱加密方式:就是明文通過密鑰加密得到密文。密文通過密鑰解密得到明文。
2、對(duì)稱加密常見算法
1、DES(Data Encryption Standard):數(shù)據(jù)加密標(biāo)準(zhǔn),速度較快,適用于加密大量數(shù)據(jù)的場合;(題外話:實(shí)際上用的不多,因?yàn)榧用軓?qiáng)度不夠)2、3DES(Triple DES):是基于DES的對(duì)稱算法,對(duì)相同的數(shù)據(jù)用3個(gè)不同的密鑰執(zhí)行3次加密,強(qiáng)度更高;(題外話:不過因?yàn)?個(gè)密鑰管理起來麻煩,所以一般不是很常用~一出生就掛掉了,很慘。。。)3、RC2和RC4:用變長密鑰對(duì)大量數(shù)據(jù)進(jìn)行加密,比DES快哦~4、AES(Advanced Encryption Standard):高級(jí)加密標(biāo)準(zhǔn),是下一代的加密算法標(biāo)準(zhǔn),速度快,安全級(jí)別高,在21世紀(jì)AES標(biāo)準(zhǔn)的一個(gè)實(shí)現(xiàn)是Rijndael算法;(題外話:很安全,蘋果的鑰匙串訪問就是用的AES,美國國家安全局也是用的AES,想要暴力破解基本不可能)復(fù)制代碼
3、對(duì)稱加密應(yīng)用模式對(duì)稱加密主要有兩種應(yīng)用模式,下面來詳細(xì)介紹一下
ECB(Electronic Code Book):電子密碼本模式。每一塊數(shù)據(jù), 獨(dú)立加密。
ECB是最基本的加密方式,也就是通常理解的加密,相同的明文將永遠(yuǎn)加密成相同的密文,無初始向量,容易受到密碼本重放攻擊,一般情況下很少用。
CBC(Cipher Block Chaining):密碼分組鏈接模式。使用一個(gè)密鑰和一個(gè)初始化向量(IV)對(duì)數(shù)據(jù)進(jìn)行加密。
CBC加密方式,明文被加密前要與前面的密文進(jìn)行異或運(yùn)算后再加密,因此只要選擇不同的初始向量,相同的密文加密后會(huì)形成不同的密文,這是目前應(yīng)用最廣泛的模式。CBC加密后的密文是上下文相關(guān)的,但明文的錯(cuò)誤不會(huì)傳遞到后續(xù)分組,但如果一個(gè)分組丟失,后面的分組將全部作廢(同步錯(cuò)誤).
CBC可以有效的保證密文的完整性,如果一個(gè)數(shù)據(jù)塊在傳遞時(shí)丟失或者改變,后面的數(shù)據(jù)無法進(jìn)行正常的解密。
四、對(duì)稱加密算法終端命令
AES對(duì)稱加密算法兩種應(yīng)用模式下的終端命令分別如下:1、AES(ECB)的加密與解密
AES(ECB)加密'battleMage'字符串
$echo-n battleMage | openssl enc -aes-128-ecb -K 616263 -nosalt | base64復(fù)制代碼
AES(ECB)解密'battleMage'字符串
$echo-n kXcE5nnetsinAMBEcK6D5g== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt-d復(fù)制代碼
2、AES(CBC)的加密與解密
AES(CBC)加密'battleMage'字符串
$echo-n battleMage | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64復(fù)制代碼
AES(CBC)解密'battleMage'字符串
$echo-n H3tn3dXCEtKNvijJYLsStw== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt-d復(fù)制代碼
五、對(duì)稱加密算法終端演練對(duì)比
1、新建一個(gè)message.txt文本文件
$ vi message.txt復(fù)制代碼
回車進(jìn)入編輯界面,點(diǎn)擊'i',進(jìn)入編輯界面,輸入5排'1234567890',點(diǎn)擊'esc',再點(diǎn)擊'shift+:',輸入'wq'回車保存。
2、對(duì)該'message.txt'文件直接使用AES(ECB)進(jìn)行加密,然后輸出一個(gè)'meg1.bin'文件
$ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out meg1.bin復(fù)制代碼
直接敲回車,得到一個(gè) meg1.bin 的文件
然后直接修改message.txt文件,把最后一排的第一個(gè)1改成2,
再次使用上述命令進(jìn)行加密,然后輸出一個(gè)'meg2.bin'文件
$ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out meg2.bin復(fù)制代碼
直接敲回車,得到一個(gè) meg2.bin 的文件
接下來使用xxd命令查看meg1.bin 和 meg2.bin文件
同樣通過AES(CBC)加密'message.txt'并輸出一個(gè)‘meg3.bin’文件
$ openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out meg3.bin復(fù)制代碼
再次手動(dòng)編輯message.txt文件,把message.txt還原,然后通過AES(CBC)加密并輸出一個(gè)‘meg4.bin’文件
$ openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out meg4.bin復(fù)制代碼
對(duì)比如下圖,
六、對(duì)稱加密算法代碼演練
接下來開始代碼演練部分,需要導(dǎo)入一個(gè)工具類,工具類代碼并不多,這里直接貼工具類的內(nèi)容吧,工具類頭文件AES,DES各種終端命令也都包含在內(nèi)了:
.h文件
#import <Foundation/Foundation.h>#import <CommonCrypto/CommonCrypto.h>/** *? 終端測試指令 * *? DES(ECB)加密 *? $echo-n hello | openssl enc -des-ecb -K 616263 -nosalt | base64 * * DES(CBC)加密 *? $echo-n hello | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt | base64 * *? AES(ECB)加密 *? $echo-n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64 * *? AES(CBC)加密 *? $echo-n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64 * *? DES(ECB)解密 *? $echo-n HQr0Oij2kbo= | base64 -D | openssl enc -des-ecb -K 616263 -nosalt-d* *? DES(CBC)解密 *? $echo-n alvrvb3Gz88= | base64 -D | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt-d* *? AES(ECB)解密 *? $echo-n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt-d* *? AES(CBC)解密 *? $echo-n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt-d* *? 提示: *? ? ? 1> 加密過程是先加密,再base64編碼 *? ? ? 2> 解密過程是先base64解碼,再解密 */@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復(fù)制代碼
.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;? ? });returninstance;}? ? - (void)setAlgorithm:(uint32_t)algorithm {? ? _algorithm = algorithm;? ? switch (algorithm) {casekCCAlgorithmAES:? ? ? ? self.keySize = kCCKeySizeAES128;? ? ? ? self.blockSize = kCCBlockSizeAES128;break;casekCCAlgorithmDES:? ? ? ? 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? ? 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? ? 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復(fù)制代碼
接下來新建工程,把工具類.h,.m拖入工程,在ViewController.m實(shí)現(xiàn)touchBegin方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {? ? NSString * key = @"abc";? ? uint8_t iv[8] = {1,2,3,4,5,6,7,8};? ? ? ? //備注:選擇的是AES(ECB), 初始向量iv直接傳nil,如果選擇 AES(CBC),初始向量iv需要傳值,具體可見工具類.m文件中實(shí)現(xiàn),是判斷iv是否為nil來選取加密方式的? ? //1、選擇AES(ECB)? ? NSString * encStr =? [[EncryptionTools sharedEncryptionTools]encryptString:@"hello"keyString:key iv:nil];? ? ? ? NSLog(@"AES(ECB)加密的結(jié)果是:%@", encStr);? ? NSLog(@"AES(ECB)解密的結(jié)果是:%@", [[EncryptionTools sharedEncryptionTools]decryptString:encStr keyString:key iv:nil]);? ? ? ? //2、選擇AES(CBC)? ? NSData * ivData = [NSData dataWithBytes:iv length:sizeof(iv)];? ? NSString * encStr1 =? [[EncryptionTools sharedEncryptionTools]encryptString:@"hello"keyString:key iv:ivData];? ? ? ? NSLog(@"AES(CBC)加密的結(jié)果是:%@", encStr1);? ? NSLog(@"AES(CBC)解密的結(jié)果是:%@", [[EncryptionTools sharedEncryptionTools]decryptString:encStr1 keyString:key iv:ivData]);? ? }@end復(fù)制代碼
點(diǎn)擊運(yùn)行,運(yùn)行結(jié)果OK
2019-10-12 21:57:26.858675+0800 CryptDemo[1790:115503] AES(ECB)加密的結(jié)果是:d1QG4T2tivoi0Kiu3NEmZQ==2019-10-12 21:57:26.858896+0800 CryptDemo[1790:115503] AES(ECB)解密的結(jié)果是:hello2019-10-12 21:57:26.859040+0800 CryptDemo[1790:115503] AES(CBC)加密的結(jié)果是:u3W/N816uzFpcg6pZ+kbdg==2019-10-12 21:57:26.859194+0800 CryptDemo[1790:115503] AES(CBC)解密的結(jié)果是:hello復(fù)制代碼
七、CCCrypt函數(shù)
第六步已經(jīng)使用過封裝好的加密工具類EncryptionTools.h,這個(gè)工具類只是封裝了CCCrypt函數(shù),下面我們來研究一下加密工具的核心函數(shù)CCCrypt函數(shù):
使用CCCrypt函數(shù),需要引入系統(tǒng)庫
#import <CommonCrypto/CommonCrypto.h>復(fù)制代碼
不管是加密還是解密都是使用這個(gè)函數(shù),下面我們來介紹一下這個(gè)函數(shù)中的參數(shù),參數(shù)解釋我直接備注在API的后面,注意里面有坑!??!
CCCrypt函數(shù)參數(shù)介紹1、 CCOperation op :操作類型:加密or解密,枚舉值;? ? kCCEncrypt 代表加密? ? kCCDecrypt 代表解密2、 CCAlgorithm alg:加密算法,枚舉值;? ? kCCAlgorithmAES? ? 高級(jí)加密標(biāo)準(zhǔn),128位(默認(rèn))? ? kCCAlgorithmDES? ? 數(shù)據(jù)加密標(biāo)準(zhǔn)? ? 3、 CCOptions options:加密應(yīng)用模式,枚舉值;注意注意!!!?。。。。。?!這里有個(gè)坑;kCCOptionPKCS7Padding代表填充模式,這個(gè)options必須加上填充模式;? ? CCCrypt的option默認(rèn)是CBC,所以只需要補(bǔ)充一個(gè)填充模式就能代表CBC; 但是ECB就需要額外再加上一個(gè)kCCOptionECBMode,所以選擇ECB就需要kCCOptionPKCS7Padding | kCCOptionECBMode;? ? ? ? 所以想要選擇CBC和ECB,需要按下面進(jìn)行填寫!kCCOptionPKCS7Padding;? 代表CBCkCCOptionPKCS7Padding | kCCOptionECBMode; 代表ECB4、 const void *key :加密的密鑰的指針5、 size_t keyLength:密鑰的長度6、 const void *iv: 初始化向量7、 const void *dataIn:加密的原始數(shù)據(jù)8、 size_t dataInLength:加密的原始數(shù)據(jù)的長度9、 void *dataOut:加密后密文的內(nèi)存地址10、size_t dataOutAvailable:加密后密文的緩沖區(qū)大小11、size_t *dataOutMoved :加密結(jié)果的大小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)復(fù)制代碼
需要注意的是,直接使用這個(gè)函數(shù)安全隱患非常的大!因?yàn)檫@個(gè)函數(shù)是系統(tǒng)提供的,不管你是加密還是解密,都是調(diào)用了CCCrypt函數(shù),而黑客可以通過越獄手機(jī)附加調(diào)試或者是非越獄手機(jī)重簽調(diào)試,能夠用函數(shù)斷點(diǎn)斷到你的CCCrypt函數(shù),然后通過寄存器直接獲取函數(shù)的對(duì)應(yīng)參數(shù),根據(jù)上面函數(shù)的介紹,我們的數(shù)據(jù)其實(shí)是其中的第七個(gè)參數(shù)'const void *dataIn', 第七個(gè)參數(shù)的下標(biāo)為6, 然后調(diào)用匯編指令'x6',就可以拿到你的數(shù)據(jù)的地址,然后轉(zhuǎn)一下類型,就能直接打印出你的加密數(shù)據(jù)!具體操作如下:
1、還是打開之前的工程,設(shè)置函數(shù)斷點(diǎn)CCCrypt,然后使用真機(jī)運(yùn)行?。?!必須用真機(jī),因?yàn)檎鏅C(jī)和模擬器的CPU不一樣
2、運(yùn)行工程,模擬黑客調(diào)試,然后點(diǎn)擊屏幕出發(fā)touchBegin方法,然后斷點(diǎn)停在了CCCrypt函數(shù)的地方
3、因?yàn)楹瘮?shù)在調(diào)用的時(shí)候,都是存在CPU的寄存器上,輸入寄存器查看指令
registerreadx6復(fù)制代碼
read x6是讀取該函數(shù)對(duì)應(yīng)的第7個(gè)參數(shù),第一個(gè)參數(shù)是x0
4、拿到地址,然后強(qiáng)轉(zhuǎn)類型,蒙圈了吧,你的數(shù)據(jù)就泄漏了
所以這個(gè)函數(shù)不能直接使用,現(xiàn)在只說基礎(chǔ),后面會(huì)詳細(xì)說安全防護(hù)~今天就說到這里了~
最后想要下面的資料可以加小編微信 獲取資料
其實(shí),看萬卷書不如行萬里路,平時(shí)直接上手做幾個(gè)簡單的項(xiàng)目,然后在項(xiàng)目中學(xué)語法,幾者相結(jié)合,或許就離大神不遠(yuǎn)了
作者: BattleMage