对称加密算法原理--OpenSSL演示、iOS代码运用及CCCrypt安全隐患
之前介紹了非對稱加密算法,這篇文章介紹一下在非對稱加密算法出現(xiàn)之前的對稱加密算法,常見的對稱加密算法、終端演示OpenSSL和iOS代碼運用以及CCCrypt的安全隱患等。
對稱加密算法:明文通過密鑰加密得到密文,密文再通過這個密鑰解密得到明文。所以在業(yè)務(wù)邏輯上相對沒有非對稱加密RSA的安全性高。
常見的對稱加密算法
- DES
數(shù)據(jù)加密標(biāo)準,但由于強度不高,暴力破解難度不是很高,所以用的很少。 - 3DES
使用3個密鑰,對數(shù)據(jù)進行三次加密,強度增強。雖然強度相對DES有所提高,但是對稱加密算法密鑰的保存就很難,3DES的3個密鑰更麻煩,所以3DES也沒有被廣泛使用。 - AES
高級密碼標(biāo)準,加密強度非常高,被廣泛使用,美國安全局和蘋果鑰匙串訪問都是用了AES加密算法。
常用的兩種加密模式
- ECB(Electronic Code Book):電子密碼本模式(每一塊數(shù)據(jù)獨立加密)
最基本的加密模式,也就是通常理解的加密,相同的明文將永遠加密成相同的密文,無初始向量,容易受到密碼本重放攻擊,一般情況下很少用。 - CBC(Cipher Block Chaining):密碼分組鏈接模式(使用一個密鑰和一個初始化向量[IV]對數(shù)據(jù)執(zhí)行加密。每一塊數(shù)據(jù)加密都依賴上一塊數(shù)據(jù),有效的保證數(shù)據(jù)的完整性)
明文被加密前要與前面的密文進行異或運算后再加密,因此只要選擇不同的初始向量,相同的密文加密后會形成不同的密文,這是目前應(yīng)用最廣泛的模式。CBC加密后的密文是上下文相關(guān)的,但明文的錯誤不會傳遞到后續(xù)分組,但如果一個分組丟失,后面的分組將全部作廢(同步錯誤)。CBC可以有效的保證密文的完整性,如果一個數(shù)據(jù)塊在傳遞時丟失或改變,后面的數(shù)據(jù)將無法正常解密。
當(dāng)然了,除了對稱加密和非對稱加密外,我們肯定還聽說過Hash
Hash概述
Hash:一般翻譯做“散列”,也有直接音譯為“哈?!钡?#xff0c;就是把任意長度的輸入通過散列算法變換成固定長度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)
之前介紹了RSA加密算法,在RSA算法之后也衍生出很多加密算法,典型的算法就有HASH函數(shù)(也稱之為散列函數(shù),嚴格意義上不算是加密算法,只不過是和加密一起用),還有在RSA出現(xiàn)之前的對稱加密算法,這些算法都是公開的。
Hash特點
算法是公開的
相同的數(shù)據(jù)加密結(jié)果不變
不同的數(shù)據(jù)加密結(jié)果定長(MD5得到的結(jié)果默認是128位二進制,一般用16進制的32個字符來標(biāo)識)
不可逆
信息摘要,信息“指紋”,用來做數(shù)據(jù)識別的
HASH用途
密碼加密:服務(wù)器不需要知道用戶真實密碼,只需要匹配HASH值
搜索引擎
版權(quán)
數(shù)字簽名
OpenSSL演示ECB和CBC的區(qū)別
- OpenSSL演示ECB模式加密
這時在文件夾內(nèi)會多出一個加密過后的二進制文件msg.bin,修改message.txt文件的內(nèi)容,再次進行加密
// 先修改message.txt的內(nèi)容,vincent->Vincent $ vi message.txt $ cat message.txtHello Vincent!!! // 再次對message.txt進行同樣的方式加密,輸出msg1.bin $ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg1.bin // 查看下msg.bin和msg1.bin有什么不同 $ xxd msg.bin 00000000: 6d87 4097 d383 0bda a5bc d168 de16 688d m.@........h..h. 00000010: b8db 0794 f9ed eca9 $ xxd msg1.bin 00000000: 20e2 8361 50a7 16a0 a5bc d168 de16 688d ..aP......h..h. 00000010: b8db 0794 f9ed eca9我們會發(fā)現(xiàn),修改message.txt內(nèi)容后ECB模式加密的結(jié)果只是修改部分不同,前后加密結(jié)果不變
- OpenSSL演示CBC模式加密
經(jīng)多次測試發(fā)現(xiàn),修改message.txt內(nèi)容后CBC模式加密的結(jié)果是修改部分不同以及后面的加密結(jié)果也會變化
- 終端測試指令
加密過程:先加密,再base64編碼
解密過程:先base64解碼,再解密
對稱加密算法代碼演示
// AES加密、ECB模式對“hello vincent!!!”進行加密NSString *ECBEncryptStr = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello vincent!!!" keyString:@"abc" iv:nil];NSLog(@"%@", ECBEncryptStr);// 解密NSString *ECBDecrypt = [[EncryptionTools sharedEncryptionTools] decryptString:ECBEncryptStr keyString:@"abc" iv:nil];NSLog(@"%@", ECBDecrypt);// 一個數(shù)組,和前面一樣有8個數(shù)據(jù)uint8_t iv[8] = {1, 2, 3, 4, 5, 6, 7, 8};// 把數(shù)組包裝才二進制NSdata 把數(shù)組的指針和長度傳進去NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];// AES加密、CBC模式NSString *CBCEncryptStr = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello vincent!!!" keyString:@"abc" iv:ivData];NSLog(@"%@", CBCEncryptStr);// 解密NSString *CBCDecrypt = [[EncryptionTools sharedEncryptionTools] decryptString:CBCEncryptStr keyString:@"abc" iv:ivData];NSLog(@"%@", CBCDecrypt);打印結(jié)果:
LzWe4b6VMKHECZTg5GEoDvOJyUo3lvcCucS987KliFw= hello vincent!!! Vo04z90TAfQX07onyrvCie1SnRpsbHKMkYnaNhcEPP0= hello vincent!!!雖然將加密和解密封裝成了兩個方法,但是蘋果內(nèi)部加密和解密都是用的一個函數(shù)。先看下其中封裝的一個方法內(nèi)部實現(xiàn)
// 加密字符串并返回base64編碼字符串 - (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {// 設(shè)置秘鑰 將keyString轉(zhuǎn)成二進制NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];uint8_t cKey[self.keySize];bzero(cKey, sizeof(cKey));[keyData getBytes:cKey length:self.keySize];// 設(shè)置ivuint8_t cIv[self.blockSize];bzero(cIv, self.blockSize);int option = 0;if (iv) {[iv getBytes:cIv length:self.blockSize];option = kCCOptionPKCS7Padding; // CBC加密} else {option = kCCOptionPKCS7Padding | kCCOptionECBMode; // ECB加密}// 設(shè)置輸出緩沖區(qū) 將原始數(shù)據(jù)轉(zhuǎn)成二進制,并根據(jù)所使用的加密方式設(shè)置緩沖區(qū)NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];size_t bufferSize = [data length] + self.blockSize;void *buffer = malloc(bufferSize);// 開始加密size_t encryptedSize = 0;//加密解密都是它 -- CCCryptCCCryptorStatus 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(@"[錯誤] 加密失敗|狀態(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è)置ivuint8_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(@"[錯誤] 解密失敗|狀態(tài)編碼: %d", cryptStatus);}return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; }代碼已加入相應(yīng)的注釋,就不解釋代碼了。我們會發(fā)現(xiàn)蘋果內(nèi)部加密和解密都是用CCCryptorStatus 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),這個函數(shù)是對稱加密算法的核心函數(shù)。
WTF!!!11個參數(shù),這么多,這都是干嘛的?
參數(shù)意義
op:kCCEncrypt(加密)/ kCCDecrypt(解密)
alg:加密算法 kCCAlgorithmAES、kCCAlgorithmDES、kCCAlgorithmBlowfish等等
options:加密方式 kCCOptionPKCS7Padding(CBC方式)/kCCOptionECBMode(ECB方式)
key:加密密鑰
keyLength:密鑰長度
iv:初始化向量 ECB不需要指定(CBC多了這個參數(shù)就相當(dāng)于加鹽,加密強度更高了)
dataIn:加密的數(shù)據(jù)
dataInLength:加密數(shù)據(jù)的長度
dataOut:緩沖區(qū)(地址),存放密文
dataOutAvailable:緩沖區(qū)的大小
dataOutMoved:加密結(jié)果的大小
搞清楚每個參數(shù)的意義也就明白了,蘋果這樣設(shè)計還是挺人性化的。對稱加密和解密所用的參數(shù)密鑰都是一樣的,所以加密和解密都是用同一個函數(shù)。蘋果的加密算法也都在CommonCrypto.h這個庫里面,這個庫并不在macho中,是在系統(tǒng)中,所以我們大多數(shù)會認為這個加密會很安全,但是事實上并不是這樣。
CCCrypt函數(shù)安全隱患
現(xiàn)在我們已經(jīng)使用CCCrypt對數(shù)據(jù)進行加密和解密了,接下來看下我們用CCCrypt加密的數(shù)據(jù)是否真的安全。下面的內(nèi)容涉及到逆向開發(fā),可能有點跑偏,如果感興趣的小伙伴也可以進一步研究一下。
我們加密數(shù)據(jù)就是為了防止中間人攻擊,假設(shè)如果別人拿到我們的APP,別人肯定不會知道我們的源碼,也不知道在數(shù)據(jù)核心加密的地方是不是用的CCCrypt,這時別人會進行符號斷點,當(dāng)然這個只要是沒有去符號,或者系統(tǒng)的都是可以攔截到的。
前方高能!!!
下了斷點后,我們繼續(xù)運行剛才的demo,程序果斷進入斷點,接下來要讀寄存器了!!!
剛剛說過,CCCrypt第7個參數(shù)是我們加密的數(shù)據(jù),所以在寄存器中X6(從X0開始)就是我們的加密數(shù)據(jù),我們在lldb中讀取X6的地址值,也就是指針,拿到X6的地址值是0x00000001c403ee00,再p (char *)0x00000001c403ee00查看X6的值,回車!!!我們剛剛加密的數(shù)據(jù)顯示出來了,我們原以為很安全的手段就這樣被別人拿到了!所以我們有很多核心的加密算法不能直接用。
那怎么防御呢?先想到去符號,前面也說了,這個庫是系統(tǒng)的,所以沒辦法去符號,當(dāng)然自己實現(xiàn)或者三方庫,比如支付寶就是直接用的OpenSSL,可以去符號來避免被直接破解。最好的方式是加密之前不能直接使用關(guān)鍵數(shù)據(jù),我們可以自己對關(guān)鍵數(shù)據(jù)處理一下比如異或,方法肯定不止一個,如果各位有什么好的解決辦法歡迎交流。
后面可能會介紹下怎么隱藏函數(shù)調(diào)用,怎樣保護核心數(shù)據(jù),當(dāng)然逆向大神還是很多的,這也僅僅是讓逆向變的更難而已。該文章為記錄本人的學(xué)習(xí)路程,希望能夠幫助大家,也歡迎大家點贊留言交流!!!https://www.jianshu.com/p/a6fca79eb89c
總結(jié)
以上是生活随笔為你收集整理的对称加密算法原理--OpenSSL演示、iOS代码运用及CCCrypt安全隐患的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 本地进行证书签名
- 下一篇: macOS 10.14 mojave安装