算法簡介
非對稱加密(如:RSA)
- 公鑰加密數(shù)據(jù)用私鑰解密
- 私鑰加密數(shù)據(jù)用公鑰解密
- 密鑰不需要傳遞
- 數(shù)學(xué)運算效率低,適合加密小字符串
對稱加密(如:AES)
- 加密和解密的密鑰是相同的
- 效率高
蘋果的鑰匙串訪問
HSAH
- 算法是公開的
- 相同數(shù)據(jù)運算得到的結(jié)果是一樣的
- 不同的數(shù)據(jù)運算,如MD5的導(dǎo)的結(jié)果是32個字符串長度的字符串
為什么是32位:MD5運算后得到的是128位的二進制字符串,32位是二進制的十六進制表現(xiàn)形式
散列碰撞:極小概率發(fā)生重合 - 無法逆運算
- 如指紋識別技術(shù)
只能加密不能解密,嚴格意義上不算加密
加密算法應(yīng)用-注冊/登錄
方式
- 直接將密碼明文,傳遞給服務(wù)端。
密碼容易被攔截竊取(×)
- 將密碼通過密鑰加密,傳遞給服務(wù)端。
密鑰及數(shù)據(jù)一旦泄露,用戶的密碼也將隨之被泄露(×)
- 將密碼通過HASH運算之后,傳遞給服務(wù)端。
即使數(shù)據(jù)被泄露,被竊取的是hash之后的字符串,且不可逆,用戶的明文密碼也不會被泄露(√)
規(guī)則:客戶端及服務(wù)不能保存用戶明文密碼
如何使用HASH算法進行一次安全的注冊登錄
- 注冊時客戶端將用戶的密碼進行hash運算傳遞給服務(wù)端進行保存,登錄時再以同樣的的方式傳遞給服務(wù)端由服務(wù)端進行驗證。

思考:由于相同數(shù)據(jù)對應(yīng)的hash運算結(jié)果是一樣的且不可逆,如果以hash運算結(jié)果為key去保存對應(yīng)的數(shù)據(jù),那么我們也可能通過hash運算結(jié)果得到原始數(shù)據(jù)
如:CMD5就保存了一些hash數(shù)據(jù)
- 加鹽
客戶端先將一個字符串(鹽)拼接到用戶的明文密碼中再進行hash運算傳遞給服務(wù)端。如用戶明文密碼是12345后面拼接@##¥%得到12345@##¥%再進行md5加密后得到54efcc63b50c2cd13fcb65f857de7d65再將hash運算后的結(jié)果當做密碼傳遞給服務(wù)端。
思考:但是需要保證Android、iOS、web等客戶端的
鹽是一致的且保存在了客戶端,存在一些將鹽泄漏的隱患,且鹽不能更換。
- HMAC
以oc代碼為例,通過傳入一個key對數(shù)據(jù)進行加密得到一個hash運算結(jié)果
/**
* 計算HMAC MD5散列結(jié)果
*
* 終端測試命令:
* @code
* echo -n "string" | openssl dgst -md5 -hmac "key"
* @endcode
*
* @return 32個字符的HMAC MD5散列字符串
*/
- (NSString *)hmacMD5StringWithKey:(NSString *)key {
const char *keyData = key.UTF8String;
const char *strData = self.UTF8String;
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *)hmacSHA1StringWithKey:(NSString *)key;
- (NSString *)hmacSHA256StringWithKey:(NSString *)key;
- (NSString *)hmacSHA512StringWithKey:(NSString *)key;
由服務(wù)端生成key,發(fā)送給客戶端,客戶端再通過key對密碼進行加密發(fā)送給服務(wù)端,即使key被泄露服務(wù)端也可以通過更換key進行補救。

衍生業(yè)務(wù)
- 服務(wù)端可以通過定時更換key來保證安全性(如某些網(wǎng)站過段時間會讓用戶再次登錄)
- 設(shè)備認證:客戶端可以通過查看本地是否保存key,來判斷當前設(shè)備是否是可信任的設(shè)備,如果不是需要用戶手動認證。只有認證設(shè)備服務(wù)端才會將key發(fā)送給客戶端。(iOS端可以將key保存到鑰匙串中)
思考:前面的加密流程看似很安全了,但是如果黑客通過WiFi等工具竊取了客戶端發(fā)送給服務(wù)端的加密密碼,再通過加密密碼直接模擬一次用戶登錄,那么我們前面無論做了什么方式的加密也將無濟于事。
我們也可以制定自己的規(guī)則,如:對key進行rsa加密
- 時間戳
- 客戶端在登錄時將(
HMAC密碼+當前時間戳)進行一次hash運算生成密碼,再發(fā)送給服務(wù)端。 - 由于在注冊時服務(wù)端已經(jīng)保存了用戶的HMAC密碼,服務(wù)端再以同樣的方式對
HMAC密碼進行加密,再將結(jié)果與客戶端發(fā)送過來的密碼進行對比。 - 如果不一致,服務(wù)端可將時間戳向前調(diào)一分鐘再進行加密對比。

這樣及時被黑客竊取到了加密密碼,也是當時時間戳下的密碼,最多1分59秒后,這個加密密碼也將失效,除非黑客能在1分59秒內(nèi)竊取到密碼,并且向前調(diào)一分鐘的規(guī)則是由服務(wù)端決定的,服務(wù)端也可將時長調(diào)更短。
時間戳是由用服務(wù)端發(fā)送給客戶端,防止客戶端本地時間被更改
加密算法應(yīng)用-拓展
AES+RSA
- 如果直接用對稱加密對數(shù)據(jù)進行加密,客戶端和服務(wù)端需要統(tǒng)一密鑰并保存到本地,由于加密和解密的密鑰是相同的一旦一端被泄露數(shù)據(jù)將存在隱患。
- 如果直接通過網(wǎng)絡(luò)發(fā)送密鑰,依然存在被截獲的風(fēng)險。
- 如果使用RSA對數(shù)據(jù)進行加密,由于數(shù)據(jù)量龐大效率將會降低。
- 由于密鑰只是一個簡單的數(shù)據(jù),所以可以使用RSA對AES的密鑰進行加密,然后傳輸。

和https的網(wǎng)絡(luò)安全協(xié)議類似
RSA+HASH(數(shù)字簽名)
如:客戶端生成了一個訂單信息要發(fā)送給服務(wù)端進行驗證和扣款。

- 客戶端將訂單信息通過hash算法進行加密,然后又將得到的hash值通過rsa進行加密,最后連同原始數(shù)據(jù)一起發(fā)送給服務(wù)端。
- 服務(wù)端收到訂單信息后,為了驗證訂單信息是否被篡改,先將加密后的數(shù)據(jù)通過rsa進行解密得到hash值,同時將原始數(shù)據(jù)用客戶端同樣的hash算法進行加密,再將得到的hash值與解密后的hash值進行比較,如果相等則訂單數(shù)據(jù)未被篡改。
訂單數(shù)據(jù)屬于龐大數(shù)據(jù)不能直接使用rsa。
由于hash算法是公開的,如果只用hash加密,被黑客攔截到數(shù)據(jù)后黑客也可能會將篡改后的訂單信息使用同樣的hash算法進行加密。
引申
逆向:有時客戶端的原始數(shù)據(jù)是可以通過逆向匯編等操作調(diào)試出來的