HASH概述:
Hash,一般翻譯做“散列”劫笙,也有直接音譯為“哈宪皆”的,就是把任意長度的輸入通過散列算法變換成固定長度的輸出填大,該輸出就是散列值戒洼。這種轉(zhuǎn)換是一種壓縮映射,也就是允华,散列值的空間通常遠小于輸入的空間圈浇,不同的輸入可能會散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值靴寂。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)汉额。
MD5信息摘要算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼散列函數(shù)榨汤,可以產(chǎn)生出一個128位(16字節(jié))的散列值(hash value)蠕搜,用于確保信息傳輸完整一致。2004年收壕,證實MD5算法無法防止碰撞(collision)(如網(wǎng)站:CMD5)妓灌,因此不適用于安全性認證,如SSL公開密鑰認證或是數(shù)字簽名等用途蜜宪。
MD5是哈希算法的一種虫埂。
Hash的特點:
- 算法是公開的
- 對相同數(shù)據(jù)運算,得到的結(jié)果是一樣的
- 對不同數(shù)據(jù)運算,如MD5得到的結(jié)果默認是128位(二進制),32個字符(16進制標識)。
- 沒法逆運算
- 信息摘要圃验,信息“指紋”掉伏,是用來做數(shù)據(jù)識別的。
Hash的用途:
用戶密碼的加密:服務(wù)器沒有必要保存用戶的真實密碼,只是保存密碼的哈希值斧散,防止用戶密碼被泄露供常,業(yè)務(wù)上一般也只有重置密碼功能,沒有找回密碼功能
搜索引擎:是將關(guān)鍵字的哈希值相加鸡捐,進行匹配的栈暇,因為分別都是128位的二進制,不管怎么排列組合箍镜,相加過后的結(jié)果都是一樣的源祈。這樣搜索
的時候,哪怕關(guān)鍵字順序不一樣色迂,搜索的結(jié)果也是一樣的香缺。版權(quán):正版的哈希值和盜版的哈希值是不一樣的。因為哈希值是根據(jù)二進制數(shù)據(jù)來哈希的歇僧,只有二進制改變图张,如壓縮,哈希值才能改變馏慨,復(fù)制并不會改變哈希值埂淮。
百度云:有秒傳功能,是因為傳遞的時候写隶,他會在云上匹配哈希值倔撞,如果有哈希值一樣,并且后綴名那些也一樣的話慕趴,就不用再傳了痪蝇。
數(shù)字簽名:客戶端將原始數(shù)據(jù)和原始數(shù)據(jù)哈希值過后RSA加密過后的密文一起傳給服務(wù)器,服務(wù)器將密文解密過后得到哈希值冕房,并與傳過來的原始數(shù)據(jù)哈希過后的哈希值進行匹配躏啰,如果匹配原始數(shù)據(jù)就是沒有被篡改過。如果不匹配就是被篡改過了耙册。用RSA包裝的原始數(shù)據(jù)哈希值的過程给僵,叫做數(shù)字簽名
密碼加密
密碼加密常見的有以下幾種方式:
- 直接使用MD5:不安全,直接使用MD5可以通過MD5碰撞详拙,破解出密碼
- MD5加鹽:當鹽泄露過后帝际,也就不安全了
- HMAC加密方案:比較好的加密方案,簡單來說是使用一個密鑰加密饶辙,并且做了兩次散列蹲诀,在實際開發(fā)中,密鑰來自于服務(wù)器弃揽,并且每個賬號匹配一個
- HMAC加密方案并添點東西(如時間戳等):當使用HMAC加密方案過后脯爪,再添點東西進行哈希
HMAC是密鑰相關(guān)的哈希運算消息認證碼(Hash-based Message Authentication Code)的縮寫则北,并在IPSec和其他網(wǎng)絡(luò)協(xié)議(如SSL)中得以廣泛應(yīng)用,現(xiàn)在已經(jīng)成為事實上的Internet安全標準痕慢。它可以與任何迭代散列函數(shù)捆綁使用尚揣。
HMAC的應(yīng)用
如上圖中,共有兩個流程:
授權(quán)設(shè)備登錄流程:
1守屉、輸入賬號過后惑艇,就把賬號作為參數(shù)向服務(wù)器發(fā)送請求
2蒿辙、服務(wù)器根據(jù)賬號生成對應(yīng)的key拇泛,并傳遞給客戶端
3、客戶端拿到key思灌,進行HMAC運算俺叭,并將運算結(jié)果的哈希值傳給服務(wù)器
其他設(shè)備登錄流程:
1、輸入賬號過后泰偿,在本地緩存中找服務(wù)器傳過來的key熄守,有就登錄,沒有就把賬號作為參數(shù)向服務(wù)器發(fā)送請求
2耗跛、服務(wù)器要先看這個賬號是否開啟了設(shè)備鎖裕照,沒有開啟就不允許登錄,開啟了调塌,就向授權(quán)設(shè)備發(fā)送請求晋南,是否授權(quán),如果授權(quán)羔砾,就將這個賬號的key傳給其他客戶端
3负间、客戶端拿到key,進行HMAC運算姜凄,并將運算結(jié)果的哈希值傳給服務(wù)器
但是在這之中有一個潛在的安全隱患問題:當別人拿到賬號和傳遞的哈希值過后政溃,也就能拿到登錄權(quán)限,從而不安全态秧。
所以這個時候不僅需要HMAC加密董虱,還需要添點東西了,如下:
image.png
為了防止上面的問題申鱼,注冊流程不變愤诱,服務(wù)器還是保存的有加了key的HMAC哈希值。
1润讥、只是登錄的時候转锈,客戶端將哈希值與時間戳拼接過后,進行MD5加密楚殿,再傳給服務(wù)器撮慨。
2竿痰、服務(wù)器將注冊保存的賬號對應(yīng)的HMAC哈希值,分別與當前時間砌溺,和前一分鐘拼接再MD5加密影涉,再和客戶端傳過來的進行匹配,匹配成功則登錄成功规伐,否則不成功蟹倾。
3、注意這里的時間戳是服務(wù)器給的時間戳猖闪。
注意:
關(guān)于密碼安全還需注意的是密碼和指紋鲜棠,人臉的關(guān)系:
密碼:你是這個賬號的主人!
人臉培慌、指紋:你是這個手機的主人豁陆!
支付寶那些是登錄成功過后,開通指紋識別
對稱加密
常見的加密算法:
- DES 數(shù)據(jù)加密標準(用得少吵护,因為強度不夠)
- 3DES 使用3個密鑰盒音,對相同的數(shù)據(jù)執(zhí)行3次加密,強度增強
- AES 高級密碼標準(一般都用這個馅而,蘋果的鑰匙串訪問等)AES 加密算法的原理詳解祥诽。
應(yīng)用模式:
-
ECB(Electronic Code Book):電子密碼本模式。每一塊數(shù)據(jù)瓮恭,獨立加密雄坪。
- 最基本的加密模式,也就是通常理解的加密偎血,相同的明文將永遠加密成相同的密文诸衔,無初始向量,容易受到密碼本重放攻擊颇玷,一般情況下很少用笨农。
-
CBC(Cipher Block Chaining):密碼分組鏈接模式。使用一個密鑰和一個初始化向量[IV]對數(shù)據(jù)執(zhí)行加密帖渠。
明文被加密前要與前面的密文進行異或運算后再加密谒亦,因此只要選擇不同的初始向量,相同的密文加密后會形成不同的密文空郊,這是目前應(yīng)用最廣泛的模式份招。CBC加密后的密文是上下文相關(guān)的,但明文的錯誤不會傳遞到后續(xù)分組狞甚,但如果一個分組丟失锁摔,后面的分組將全部作廢(同步錯誤)。
CBC可以有效的保證密文的完整性哼审,如果一個數(shù)據(jù)塊在傳遞是丟失或改變谐腰,后面的數(shù)據(jù)將無法正常解密孕豹。
加密的終端命令:
DES加密的ECB模式下,將message.txt加密十气,輸出為msg1.bin
$ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg1.bin
DES加密的CBC模式下励背,將message.txt加密,輸出為msg3.bin
$ openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out msg3.bin
AES(ECB)加密“hello”字符串
$ echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
AES(ECB)解密
$ echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt -d
AES(CBC)加密“hello”字符串
$ echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
AES(CBC)解密
$ echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
加密過程是先加密砸西,再base64編碼
解密過程是先base64解碼叶眉,再解密
CCCrypt函數(shù)
AES加密解密都是用到的CCCrypt函數(shù),并且需要導入CommonCrypto
框架芹枷。
/**
1衅疙、kCCEncrypt 加密/kCCDecrypt 解密
2、加密算法杖狼。
3炼蛤、加密選項:ECB/CBC
4妖爷、加密的密鑰
5蝶涩、密鑰的長度
6、iv 初始化向量
7絮识、加密的數(shù)據(jù)
8绿聘、加密的數(shù)據(jù)長度
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);
```