Hash
定義
散列函數(shù)(英語(yǔ):Hash function)又稱散列算法、哈希函數(shù),是一種從任何一種數(shù)據(jù)中創(chuàng)建小的數(shù)字“指紋”的方法。散列函數(shù)把消息或數(shù)據(jù)壓縮成摘要,使得數(shù)據(jù)量變小,將數(shù)據(jù)的格式固定下來(lái)。該函數(shù)將數(shù)據(jù)打亂混合,重新創(chuàng)建一個(gè)叫做散列值(hash values,hash codes,hash sums,或hashes)的指紋。散列值通常用一個(gè)短的隨機(jī)字母和數(shù)字組成的字符串來(lái)代表。好的散列函數(shù)在輸入域中很少出現(xiàn)散列沖突。在散列表和數(shù)據(jù)處理中,不抑制沖突來(lái)區(qū)別數(shù)據(jù),會(huì)使得數(shù)據(jù)庫(kù)記錄更難找到。 —— Wikipedia-Hash
簡(jiǎn)單來(lái)說(shuō)就是 Hash 這種算法可以把任意數(shù)據(jù)轉(zhuǎn)換成指定的大小范圍(通常在256字節(jié)以內(nèi))的數(shù)據(jù)。
作用
Hash 把數(shù)據(jù)壓縮成摘要,因此最主要用途是數(shù)字指紋。
實(shí)際用途
- 唯一性驗(yàn)證:Java 中的 hashCode() 方法。
- 數(shù)據(jù)完整性驗(yàn)證:從網(wǎng)絡(luò)下載文件時(shí),為防止文件傳輸中丟失,文件提供方都會(huì)給出完整文件的 hash 值,用于完整性校驗(yàn)
- 快速查找:HashMap
- 隱私保護(hù):當(dāng)重要數(shù)據(jù)必須暴露時(shí),可以選擇暴露它的 Hash 值(MD5、SHA2等),例如網(wǎng)站登錄時(shí),可以只保存用戶密碼的 Hash 值,每次登錄時(shí)只需將密碼的 Hash 值和數(shù)據(jù)庫(kù)中的 Hash 值作比較,網(wǎng)站無(wú)需存儲(chǔ)用戶密碼,這樣在網(wǎng)站數(shù)據(jù)被盜時(shí)可以有效防止撞庫(kù)等風(fēng)險(xiǎn)
Hash 是編碼嗎?
不是。Hash 是單向過(guò)程,Hash 值不可逆向成數(shù)據(jù)(4GB 大小的一個(gè) mkv 文件,Hash 值也只是一個(gè)字符串而已,不可能從這個(gè)字符串恢復(fù)成原文件),因此 Hash 不屬于編碼。
Hash 是加密嗎?
不是。加密和解密是對(duì)應(yīng)的,Hash 是單向過(guò)程,無(wú)法進(jìn)行逆向操作,因此 Hash 不屬于加密。
加密
對(duì)稱加密
- 原理:使用密鑰和加密算法對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換,得到無(wú)意義的數(shù)據(jù)即密文;使用密鑰和解密算法對(duì)密文進(jìn)行逆向轉(zhuǎn)換,得到原數(shù)據(jù)。

非對(duì)稱加密
非對(duì)稱加密可以說(shuō)是現(xiàn)代計(jì)算機(jī)網(wǎng)路通訊的安全基石,無(wú)論你是否了解或者聽(tīng)說(shuō)過(guò)它,只要你使用聯(lián)網(wǎng)的電子設(shè)備,就會(huì)用到它。
- 原理:使用公鑰對(duì)數(shù)據(jù)進(jìn)行加密得到密文;使用私鑰對(duì)數(shù)據(jù)進(jìn)行解密得到原數(shù)據(jù)。

用一個(gè)簡(jiǎn)單的例子來(lái)解釋一下非對(duì)稱加密:A 要發(fā)送一個(gè)消息110給 B,B 自己先生成一對(duì)密鑰(公鑰p 和 私鑰q),這對(duì)密鑰有一個(gè)對(duì)應(yīng)關(guān)系,那就是 p+q=10,這里假設(shè)(p=4;q=6),B 把公鑰 4 發(fā)給 A,A 再把110每位加 4 變成密文554發(fā)給 B,然后 B 拿到密文554之后使用私鑰每位加 6 變成111110然后把每一位的結(jié)果 -10 得到110,這樣 B 就拿到了原文。

同理,B 如果要給 A 發(fā)送消息,那么 B 就用 A 的公鑰加密消息發(fā)給 A,然后 A 再用自己的私鑰解密消息就好了,所以非對(duì)稱加密的安全關(guān)鍵就是私鑰不對(duì)外公開(kāi)并且只有自己的私鑰才能解自己的公鑰,這樣就解決了對(duì)稱加密通訊中密鑰傳輸丟失的風(fēng)險(xiǎn),因?yàn)?A 根本不需要把私鑰發(fā)送給 B,而發(fā)送出去的公鑰不能用來(lái)解密消息。以上示例的整個(gè)通訊過(guò)程就是非對(duì)稱加密通訊的核心思想。
上圖的模型中加密算法就是加法,公鑰就是 4,私鑰就是 6,其中加密算法和公鑰是公開(kāi)的,示例模型中拿到公鑰和密文是可以推導(dǎo)出原數(shù)據(jù)的,而實(shí)際應(yīng)用中的加密算法十分復(fù)雜并且通過(guò)公鑰和密文無(wú)法推導(dǎo)出原數(shù)據(jù),具體可以參考非對(duì)稱加密算法 RSA 的算法原理。
簽名和驗(yàn)證
通過(guò)了解非對(duì)稱加密我們可以知道同一對(duì)密鑰中私鑰是可以解公鑰的,那么思考一下公鑰是否可以解私鑰?
我們不妨仔細(xì)看一下非對(duì)稱加密解密過(guò)程:

如上圖所示,A 通過(guò)公鑰+加密算法得到 B,B 通過(guò)私鑰+加密算法得到 C,因?yàn)?C = A,所以用公鑰再加密一下 C 就可以得到 B 而形成一個(gè)循環(huán),所以公鑰也可以解私鑰加密的數(shù)據(jù)。
于是,我們就可以用私鑰給數(shù)據(jù)做簽名,然后對(duì)方收到簽名數(shù)據(jù)用公鑰解密做校驗(yàn);在實(shí)際應(yīng)用中由于文件大小的不可控,給文件直接簽名效率很低,所以一般都是給文件的 hash 值做簽名,因?yàn)?hash 的最主要用途就是數(shù)字指紋,因此通過(guò)比對(duì)兩個(gè)文件的 hash 值是否相等來(lái)校驗(yàn)兩個(gè)文件是否相等是普遍的文件校驗(yàn)手段。通過(guò)非對(duì)稱加密來(lái)簽名和校驗(yàn)文件的過(guò)程如下:

從上圖中不難看出,我們給數(shù)據(jù)簽名的目的只有一個(gè):保證接受方收到的數(shù)據(jù)就是我發(fā)出去的數(shù)據(jù),中途沒(méi)有丟失或被篡改。
我們從大部分網(wǎng)站上下載一些文件,為安全起見(jiàn)一般他們都會(huì)給出文件的 hash 值,用來(lái)和你下載到本地的文件做完整性和一致性的校驗(yàn)。
所以給文件簽名的邏輯就是:我要發(fā)送一個(gè)文件給對(duì)方,那我怎么保證我的文件不會(huì)被篡改或丟失?把文件的 hash 也發(fā)過(guò)去。那我怎么保證我的 hash 不會(huì)被篡改?把 hash 進(jìn)行簽名和文件一起發(fā)過(guò)去。
Base64
定義
Base64是一種基于64個(gè)可打印字符來(lái)表示二進(jìn)制數(shù)據(jù)的表示方法。由于 {\displaystyle 2^{6}=64} {\displaystyle 2^{6}=64},所以每6個(gè)比特為一個(gè)單元,對(duì)應(yīng)某個(gè)可打印字符。3個(gè)字節(jié)有24個(gè)比特,對(duì)應(yīng)于4個(gè)Base64單元,即3個(gè)字節(jié)可由4個(gè)可打印字符來(lái)表示。它可用來(lái)作為電子郵件的傳輸編碼。在Base64中的可打印字符包括字母A-Z、a-z、數(shù)字0-9,這樣共有62個(gè)字符,此外兩個(gè)可打印符號(hào)在不同的系統(tǒng)中而不同。一些如uuencode的其他編碼方法,和之后BinHex的版本使用不同的64字符集來(lái)代表6個(gè)二進(jìn)制數(shù)字,但是不被稱為Base64。 —— Wikipedia-Base64
簡(jiǎn)單理解就是 Base64 是一種能將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成有 64 個(gè)字符組成的字符串的編碼算法。
算法
將原數(shù)據(jù)每 6 位對(duì)應(yīng)成 Base 64 索引表中的一個(gè)字符并編排成一個(gè)字符串(每個(gè)字符 8 位)。
Base64 索引表:

編碼“Man”

末尾補(bǔ)齊

用途
- 將二進(jìn)制數(shù)據(jù)的存儲(chǔ)方式和傳輸途徑進(jìn)行了擴(kuò)充(例如可以把圖片經(jīng)過(guò)編碼保存到文本文件、可以通過(guò)聊天對(duì)話框或短信形式發(fā)送、可以在 URL 中加入簡(jiǎn)單的二進(jìn)制數(shù)據(jù))
- 普通的字符串在經(jīng)過(guò) Base64 編碼后結(jié)果會(huì)變得肉眼不可讀,因此適用于一定條件下的防偷窺
缺點(diǎn)
因?yàn)樽陨碓恚? 位變 8 位),因此每次 Base64 編碼之后,數(shù)據(jù)都會(huì)增大約 1/3,所以會(huì)影響存儲(chǔ)和傳輸性能。
變種:Base58
比特幣使用的編碼方式,去掉了 Base64 中的數(shù)字 “0”,大寫(xiě)字母 “O”,大寫(xiě)字母 “I”,和小寫(xiě)字母 “l(fā)”,以及 “+” 和 “/” 符號(hào),用于比特幣地址的表示。
Base58 對(duì)于 Base64 的改動(dòng),主要目的在于用戶的便攜性。由于去掉了難以區(qū)分的字符,使得 Base58 對(duì)于“人工抄寫(xiě)”更加友好。另外,去掉了“+”、“/”號(hào)后也讓大多數(shù)如軟件可以方便的雙擊選取。
壓縮與解壓縮
含義
- 壓縮:將數(shù)據(jù)使用更具有存儲(chǔ)優(yōu)勢(shì)的編碼算法進(jìn)行編碼。
- 解壓縮:將壓縮數(shù)據(jù)解碼還原成原來(lái)的形式,以方便使用。
目的
減小數(shù)據(jù)占用的存儲(chǔ)空間。
示例
將下面的文本內(nèi)容壓縮:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
使用某種算法壓縮后結(jié)果為:
compress:a:1024;b:105
注:實(shí)際應(yīng)用場(chǎng)景中的壓縮算法非常復(fù)雜,上面只是一種演示原型。
壓縮是編碼嗎?
是。所謂編碼,即把數(shù)據(jù)從一種形式轉(zhuǎn)換為另一種形式。壓縮過(guò)程屬于編碼過(guò)程,解壓縮過(guò)程屬于解碼過(guò)程。
常見(jiàn)的壓縮算法
JPEG、MP3、MP4 等。
序列化
把數(shù)據(jù)對(duì)象(一般是內(nèi)存中的,例如 JVM 中的對(duì)象)轉(zhuǎn)換成字節(jié)序列的過(guò)程。對(duì)象在程序內(nèi)存里的存放形式是散亂的(存放在不同內(nèi)存區(qū)域、并且由引用進(jìn)行連接),通過(guò)序列化可以把內(nèi)存中的對(duì)象轉(zhuǎn)換成一個(gè)字節(jié)序列,從而使用 byte[] 等形式進(jìn)行本地存儲(chǔ)或網(wǎng)絡(luò)傳輸,在需要的時(shí)候進(jìn)行重新組裝(反序列化)來(lái)使用。
目的
讓內(nèi)存中的對(duì)象可以被存儲(chǔ)和傳輸。
我的博客即將同步至騰訊云+社區(qū),邀請(qǐng)大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=209dz85wu1og0