HASH概述
Hash
:一般翻譯做“散列”,也有直接音譯為“哈细撸”的密浑,就是把任意長度的輸入通過散列算法變換成固定長度的輸出,該輸出就是散列值粗井。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間浇衬,不同的輸入可能會(huì)散列成相同的輸出懒构,所以不可能從散列值來確定唯一的輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)
常用的
HASH
算法:
MD5
SHA1
SHA256
SHA512
Hash
的特點(diǎn):
- 算法是公開的
- 對相同數(shù)據(jù)運(yùn)算耘擂,得到的結(jié)果相同
- 對不同數(shù)據(jù)運(yùn)算胆剧,得到的長度相同(默認(rèn)
128位
,32
個(gè)字符)- 可重復(fù)
- 不可逆
- 信息摘要醉冤,信息“
指紋
”秩霍,是用來做數(shù)據(jù)識(shí)別的
HASH
算法不可逆的原因:
HASH
算法有兩個(gè)基本特點(diǎn),可重復(fù)和不可逆蚁阳。HASH
值為32
個(gè)字符組成铃绒,所表達(dá)的數(shù)據(jù)是有限的,即:16 ^ 32
螺捐。但生成HASH
值的原文是無限的颠悬,無限的內(nèi)容生成有限的表現(xiàn)形式,一定會(huì)產(chǎn)生多個(gè)原文得到相同的HASH
值定血,這種現(xiàn)象稱散列碰撞
赔癌。也正是因?yàn)槿绱耍瑥?code>HASH值反推出原文是不可能的
Hash
的用途:
- 密碼加密
- 搜索引擎
- 版權(quán)
- 數(shù)據(jù)識(shí)別
- 數(shù)字簽名
密碼加密
通過運(yùn)用HASH
算法澜沟,給用戶的密碼進(jìn)行加密灾票。
很多用戶多個(gè)
App
之間使用相同密碼,如果公司App
導(dǎo)致用戶密碼泄露茫虽,可能會(huì)造成用戶丟失很多數(shù)據(jù)铝条,公司會(huì)背負(fù)相應(yīng)的法律責(zé)任
:
所以在網(wǎng)絡(luò)傳輸、服務(wù)器保存隱私數(shù)據(jù)席噩,例如:用戶的密碼班缰,應(yīng)該傳遞和保存的是加密后的數(shù)據(jù),以免泄露密碼加密悼枢,應(yīng)使用不可逆算法埠忘。如果密文可被解密,依然存在安全隱患馒索。假設(shè):使用
RSA
加密莹妒,密碼長度有限,無需擔(dān)心大數(shù)據(jù)加密和效率問題绰上,安全性也沒問題旨怠,但如果私鑰泄露,密碼還是相當(dāng)于明文存儲(chǔ)蜈块。對于密鑰的更換也非常困難鉴腻,無法讓平臺(tái)所有用戶全部更換一次密碼
密碼加密方式:
- 使用
MD5
MD5
加鹽HMAC
加密HASH + 時(shí)間戳
案例1:
使用
MD5
加密數(shù)據(jù)使用
NSString+Hash
庫迷扇,提供以下方法:#import <Foundation/Foundation.h> @interface NSString (Hash) //計(jì)算MD5散列結(jié)果 - (NSString *)md5String; //計(jì)算SHA1散列結(jié)果 - (NSString *)sha1String; //計(jì)算SHA256散列結(jié)果 - (NSString *)sha256String; //計(jì)算SHA 512散列結(jié)果 - (NSString *)sha512String; //計(jì)算HMAC MD5散列結(jié)果 - (NSString *)hmacMD5StringWithKey:(NSString *)key; //計(jì)算HMAC SHA1散列結(jié)果 - (NSString *)hmacSHA1StringWithKey:(NSString *)key; //計(jì)算HMAC SHA256散列結(jié)果 - (NSString *)hmacSHA256StringWithKey:(NSString *)key; //計(jì)算HMAC SHA512散列結(jié)果 - (NSString *)hmacSHA512StringWithKey:(NSString *)key; //計(jì)算文件的MD5散列結(jié)果 - (NSString *)fileMD5Hash; //計(jì)算文件的SHA1散列結(jié)果 - (NSString *)fileSHA1Hash; //計(jì)算文件的SHA256散列結(jié)果 - (NSString *)fileSHA256Hash; //計(jì)算文件的SHA512散列結(jié)果 - (NSString *)fileSHA512Hash; @end
打開
ViewController.m
文件,寫入以下代碼:#import "ViewController.h" #import "NSString+Hash.h" @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSString * pwd = @"123456"; NSLog(@"密碼:%@",pwd.md5String); } @end
運(yùn)行項(xiàng)目爽哎,點(diǎn)擊屏幕蜓席,輸出以下內(nèi)容:
密碼:e10adc3949ba59abbe56e057f20f883e
MD5
生成的密文無法還原成原文,但它依然可以被破解课锌,而它的破解指的是碰撞厨内。如果計(jì)算出來的MD5
值和已知的MD5
值一樣,即找到了它的原文渺贤。已知的MD5
值越多雏胃,破解的成功率越高對于專業(yè)網(wǎng)站來說,
MD5
值的反向查詢成功率還是很高的
案例2:
對用戶密碼加鹽
打開
ViewController.m
文件志鞍,寫入以下代碼:static NSString * salt = @"LKSJDFLKJ&^&@@"; -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSString * pwd = @"123456"; pwd = [pwd stringByAppendingString:salt].md5String; NSLog(@"密碼:%@",pwd.md5String); }
運(yùn)行項(xiàng)目瞭亮,點(diǎn)擊屏幕,輸出以下內(nèi)容:
密碼:2359298f49af5695a4b846e95bdea467
鹽
和密鑰
很相似述雾,如果鹽
被泄露街州,也會(huì)造成很大的安全隱患
鹽的更換同樣困難,需要平臺(tái)所有用戶更換密碼玻孟。而且加鹽的方式對于開發(fā)者依賴太高唆缴,如果開發(fā)者帶鹽跑路,對公司來說也是一件痛苦的事情
案例3:
使用
HMAC
加密方式打開
ViewController.m
文件黍翎,寫入以下代碼:-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSString * pwd = @"123456"; pwd = [pwd hmacMD5StringWithKey:@"Zang"]; NSLog(@"密碼:%@",pwd); }
運(yùn)行項(xiàng)目面徽,點(diǎn)擊屏幕,輸出以下內(nèi)容:
密碼:f0538e52ec3f5b0a27660cd321b1cb97
HMAC
加密的特點(diǎn):
- 使用一個(gè)
密鑰
加密數(shù)據(jù)做兩次散列密鑰
由服務(wù)端提供匣掸,服務(wù)端為每個(gè)賬號(hào)生成一個(gè)密鑰
趟紊,再傳遞給客戶端- 單一
密鑰
的泄漏,只影響一個(gè)用戶- 單一
密鑰
的更換碰酝,只需要對應(yīng)用戶重新輸入密碼即可使用
HMAC
加密的流程注冊:
- 將賬號(hào)傳遞給服務(wù)端
- 服務(wù)端針對賬號(hào)隨機(jī)生成一個(gè)
密鑰
霎匈,返回給客戶端- 客戶端將
密鑰
存儲(chǔ)在本地,例如:鑰匙串- 注冊時(shí)送爸,明文密碼使用
HMAC
加密铛嘱,將密文傳遞服務(wù)端登錄:
- 如果本地沒有
密鑰
,先請求服務(wù)端獲取密鑰
- 登錄時(shí)袭厂,明文密碼使用
HMAC
加密墨吓,將密文傳遞服務(wù)端當(dāng)設(shè)備登錄時(shí)沒有
密鑰
,可視為未授權(quán)設(shè)備纹磺,可增加新設(shè)備授權(quán)流程例如:服務(wù)端向老設(shè)備發(fā)送請求帖烘,是否同意新設(shè)備登錄,用戶點(diǎn)擊同意橄杨,服務(wù)端再給新設(shè)備發(fā)送
密鑰
使用
HMAC
加密秘症,密碼相對安全照卦,但無法防止重放攻擊。攻擊者利用網(wǎng)絡(luò)監(jiān)聽或者其他方式盜取密文密碼历极,之后再把它重新發(fā)給認(rèn)證服務(wù)器窄瘟,可以輕松的欺騙系統(tǒng)進(jìn)行身份認(rèn)證
案例4
對請求增加時(shí)效性
防止重放攻擊最有效的辦法就是對密文增加時(shí)效性衷佃,在
HMAC
加密方式不變的情況下趟卸,增加時(shí)間戳例如:
(密碼.HMAC + 時(shí)間戳).md5
打開
ViewController.m
文件,寫入以下代碼:-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSString * pwd = @"123456"; pwd = [pwd hmacMD5StringWithKey:@"Zang"]; pwd = [pwd stringByAppendingString:@"202104151608"].md5String; NSLog(@"密碼:%@",pwd); }
運(yùn)行項(xiàng)目氏义,點(diǎn)擊屏幕锄列,輸出以下內(nèi)容:
密碼:d3a8cc619a27e21077ebc7baa03f5e8f
上述案例中,客戶端使用的時(shí)間戳惯悠,必須是服務(wù)器時(shí)間邻邮。服務(wù)端進(jìn)行驗(yàn)證時(shí),使用相同方式加密克婶,然后和客戶端傳遞的密文對比一致性
如果客戶端網(wǎng)絡(luò)延遲筒严,導(dǎo)致請求時(shí)間較長,服務(wù)端時(shí)間變成了下一分鐘情萤,驗(yàn)證將無法通過鸭蛙。故此對于時(shí)效性的驗(yàn)證,還應(yīng)增加容錯(cuò)處理
服務(wù)端驗(yàn)證當(dāng)前時(shí)間戳筋岛,如果失敗娶视,還應(yīng)該使用前一分鐘的時(shí)間戳再次驗(yàn)證
對于
HASH + 時(shí)間戳
的登錄方式,一次請求的有效時(shí)間睁宰,最長為1分59秒
肪获,這樣可以有效避免重放攻擊
數(shù)字簽名
為什么用簽名這個(gè)詞?因?yàn)槔贤庀矚g用支票柒傻,支票上面的簽名能夠證明這玩意是你的孝赫。那么數(shù)字簽名顧名思義,就是用于鑒別數(shù)字信息的方法红符。
數(shù)字簽名是只有信息的發(fā)送者才能產(chǎn)生的別人無法偽造的一段數(shù)字串青柄,這段數(shù)字串同時(shí)也是對信息的發(fā)送者發(fā)送信息真實(shí)性的一個(gè)有效證明
數(shù)字簽名的目的:
- 防偽造:私有密鑰只有簽名者自己知道,所以其他人不可能構(gòu)造出正確的
- 鑒別身份:由于傳統(tǒng)的手工簽名一般是雙方直接見面的违孝,身份自可一清二楚刹前。在網(wǎng)絡(luò)環(huán)境中,接收方必須能夠鑒別發(fā)送方所宣稱的身份
- 防篡改:對于數(shù)字簽名雌桑,簽名與原有文件已經(jīng)形成了一個(gè)混合的整體數(shù)據(jù)喇喉,不可能被篡改,從而保證了數(shù)據(jù)的完整性
- 防重放:對于數(shù)字簽名校坑,如果采用了對簽名報(bào)文添加流水號(hào)拣技、時(shí)間戳等技術(shù)千诬,可以防止重放攻擊
- 防抵賴:數(shù)字簽名可以鑒別身份,不可能冒充偽造膏斤,那么徐绑,只要保存好簽名的報(bào)文,也就是保留了證據(jù)莫辨,簽名者就無法抵賴
- 保密性:有了保密性傲茄,截收攻擊也就失效了。數(shù)字簽名可以加密要簽名的消息沮榜,當(dāng)然盘榨,如果簽名的報(bào)名不要求機(jī)密性,也可以不用加密
一套數(shù)字簽名通常定義兩種互補(bǔ)的運(yùn)算蟆融,一個(gè)用于簽名草巡,另一個(gè)用于驗(yàn)證。數(shù)字簽名是非對稱密鑰加密技術(shù)與
HASH
技術(shù)的應(yīng)用服務(wù)端下發(fā)數(shù)據(jù):
- 對將要傳遞的數(shù)據(jù)型酥,生成
HASH
值- 將
HASH
值使用RSA
加密山憨,生成簽名- 傳遞數(shù)據(jù)時(shí),同時(shí)傳遞簽名
客戶端驗(yàn)證數(shù)據(jù):
- 將密文
RSA
解密弥喉,獲取到服務(wù)端下發(fā)的HASH
值- 使用相同的算法郁竟,對數(shù)據(jù)生成本地
HASH
值- 將本地和服務(wù)端下發(fā)的
HASH
值進(jìn)行對比RSA
解密成功,HASH
值對比一致档桃,才能表示本次請求是合法的客戶端向服務(wù)端傳遞數(shù)據(jù)枪孩,邏輯一致
其他用途
搜索引擎
在搜索引擎中分詞搜索時(shí),幾個(gè)關(guān)鍵字無論順序如何藻肄,得到的搜索結(jié)果都是一致的
例如:
iOS & Swift
無論
iOS
和Swift
的順序如何蔑舞,只要iOS
和Swift
的HASH
值求和,結(jié)果是一樣的嘹屯,則視為相同的搜索詞攻询,搜索結(jié)果就是一致的即:
iOS.HASH + Swift.HASH ≡ SUM ≡ Swift.HASH + iOS.HASH
版權(quán)
由于數(shù)字文件的便捷性,拷貝傳播十分方便州弟,但是由于一些涉及利益的傳播性質(zhì)钧栖,往往會(huì)侵犯數(shù)字文件版權(quán)的歸屬問題
文件的
HASH
值,和文件名婆翔、后綴名無關(guān)拯杠,只取決于文件的二進(jìn)制數(shù)據(jù)。正版與盜版的區(qū)別也在于它們的HASH
值不同
數(shù)據(jù)識(shí)別
網(wǎng)盤的數(shù)據(jù)識(shí)別啃奴,例如秒傳功能潭陪,如果上傳文件的
HASH
值在服務(wù)器上存在,無需重復(fù)上傳還有對于一些違規(guī)的文件,修改文件名依溯、后綴名也會(huì)被識(shí)別出來老厌,這種情況只能修改文件的二進(jìn)制數(shù)據(jù)
對于文件計(jì)算
HASH
值,是不是也耗費(fèi)服務(wù)器資源呢黎炉?其實(shí)枝秤,
HASH
去重也是分粒度的,有文件去重慷嗜,塊去重淀弹,字節(jié)去重,粒度越細(xì)的準(zhǔn)確率越高洪添,相應(yīng)的耗費(fèi)服務(wù)器資源肯定也要多
終端命令
散列函數(shù)
計(jì)算
MD5
散列結(jié)果md5 -s "123456 ------------------------- MD5 ("123456") = e10adc3949ba59abbe56e057f20f883e
32
個(gè)字符的MD5
散列字符串
計(jì)算
SHA1
散列結(jié)果echo -n "123456" | openssl sha1 ------------------------- (stdin)= 7c4a8d09ca3762af61e59520943dc26494f8941b
40
個(gè)字符的SHA1
散列字符串
計(jì)算
SHA256
散列結(jié)果echo -n "123456" | openssl sha256 ------------------------- (stdin)= 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
64
個(gè)字符的SHA256
散列字符串
計(jì)算
SHA512
散列結(jié)果echo -n "123456" | openssl sha512 ------------------------- (stdin)= ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413
128
個(gè)字符的SHA512
散列字符串
HMAC散列函數(shù)
計(jì)算
HMAC MD5
散列結(jié)果echo -n "123456" | openssl dgst -md5 -hmac "key" ------------------------- (stdin)= 0abf6bacd23c55fa6ab14eb44a7f5720
32
個(gè)字符的HMAC MD5
散列字符串
計(jì)算
HMAC SHA1
散列結(jié)果echo -n "123456" | openssl sha1 -hmac "key" ------------------------- (stdin)= 4fc32f51f214211618a9598893823519b829ee74
40
個(gè)字符的HMAC SHA1
散列字符串
計(jì)算
HMAC SHA256
散列結(jié)果echo -n "123456" | openssl sha256 -hmac "key" ------------------------- (stdin)= 4df81f55d708ae1720d5f65ef42f3475dc168fa23fde424ac5944f87c309b05f
64
個(gè)字符的HMAC SHA256
散列字符串
計(jì)算
HMAC SHA512
散列結(jié)果echo -n "123456" | openssl sha512 -hmac "key" ------------------------- (stdin)= cc2f51259b61903f6b50ea2cc3653340f1e8c0ae780c927bc1c7f09dcd1d606f7cb3347117f75fa19d9f760f4d538709a969c11036d194b972bf3232f34f30a8
128
個(gè)字符的HMAC SHA512
散列字符串
文件散列函數(shù)
創(chuàng)建
file.txt
文件垦页,寫入以下內(nèi)容:123456
計(jì)算文件的
MD5
散列結(jié)果md5 file.txt ------------------------- MD5 (file.txt) = e10adc3949ba59abbe56e057f20f883e
32
個(gè)字符的MD5
散列字符串
計(jì)算文件的
SHA1
散列結(jié)果openssl sha1 file.txt ------------------------- SHA1(file.txt)= 7c4a8d09ca3762af61e59520943dc26494f8941b
40
個(gè)字符的SHA1
散列字符串
計(jì)算文件的
SHA256
散列結(jié)果openssl sha256 file.txt ------------------------- SHA256(file.txt)= 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
64
個(gè)字符的SHA256
散列字符串
計(jì)算文件的
SHA512
散列結(jié)果openssl sha512 file.txt ------------------------- SHA512(file.txt)= ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413
128
個(gè)字符的SHA512
散列字符串
總結(jié)
Hash
的特點(diǎn):
- 算法是公開的
- 對相同數(shù)據(jù)運(yùn)算雀费,得到的結(jié)果相同
- 對不同數(shù)據(jù)運(yùn)算干奢,得到的長度相同
- 可重復(fù)
- 不可逆
- 信息摘要,信息“
指紋
”盏袄,是用來做數(shù)據(jù)識(shí)別的
Hash
的用途:
- 密碼加密
- 搜索引擎
- 版權(quán)
- 數(shù)據(jù)識(shí)別
- 數(shù)字簽名
密碼加密方式:
- 使用
MD5
MD5
加鹽HMAC
加密(比較好的方案)HASH + 時(shí)間戳
(配合HMAC
加密忿峻,可防重放攻擊)數(shù)字簽名的算法
HASH + RSA
數(shù)字簽名的目的:
- 防偽造
- 鑒別身份
- 防篡改
- 防重放
- 防抵賴
- 保密性
數(shù)字簽名的邏輯
- 生成原始數(shù)據(jù)的
HASH
值- 將
HASH
值進(jìn)行RSA
加密