Hash
定義
散列函數(shù)(英語:Hash function)又稱散列算法、哈希函數(shù)逝撬,是一種從任何一種數(shù)據(jù)中創(chuàng)建小的數(shù)字“指紋”的方法浴骂。散列函數(shù)把消息或數(shù)據(jù)壓縮成摘要,使得數(shù)據(jù)量變小宪潮,將數(shù)據(jù)的格式固定下來溯警。該函數(shù)將數(shù)據(jù)打亂混合趣苏,重新創(chuàng)建一個叫做散列值(hash values梯轻,hash codes食磕,hash sums,或hashes)的指紋彬伦。散列值通常用一個短的隨機(jī)字母和數(shù)字組成的字符串來代表。好的散列函數(shù)在輸入域中很少出現(xiàn)散列沖突搂橙。在散列表和數(shù)據(jù)處理中,不抑制沖突來區(qū)別數(shù)據(jù)蜗帜,會使得數(shù)據(jù)庫記錄更難找到。 —— Wikipedia-Hash
簡單來說就是 Hash 這種算法可以把任意數(shù)據(jù)轉(zhuǎn)換成指定的大小范圍(通常在256字節(jié)以內(nèi))的數(shù)據(jù)资厉。
作用
Hash 把數(shù)據(jù)壓縮成摘要厅缺,因此最主要用途是數(shù)字指紋。
實際用途
- 唯一性驗證:Java 中的 hashCode() 方法宴偿。
- 數(shù)據(jù)完整性驗證:從網(wǎng)絡(luò)下載文件時湘捎,為防止文件傳輸中丟失,文件提供方都會給出完整文件的 hash 值窄刘,用于完整性校驗
- 快速查找:HashMap
- 隱私保護(hù):當(dāng)重要數(shù)據(jù)必須暴露時窥妇,可以選擇暴露它的 Hash 值(MD5、SHA2等)娩践,例如網(wǎng)站登錄時活翩,可以只保存用戶密碼的 Hash 值,每次登錄時只需將密碼的 Hash 值和數(shù)據(jù)庫中的 Hash 值作比較翻伺,網(wǎng)站無需存儲用戶密碼材泄,這樣在網(wǎng)站數(shù)據(jù)被盜時可以有效防止撞庫等風(fēng)險
Hash 是編碼嗎?
不是吨岭。Hash 是單向過程拉宗,Hash 值不可逆向成數(shù)據(jù)(4GB 大小的一個 mkv 文件,Hash 值也只是一個字符串而已,不可能從這個字符串恢復(fù)成原文件)旦事,因此 Hash 不屬于編碼魁巩。
Hash 是加密嗎?
不是姐浮。加密和解密是對應(yīng)的谷遂,Hash 是單向過程,無法進(jìn)行逆向操作单料,因此 Hash 不屬于加密埋凯。
加密
對稱加密
- 原理:使用密鑰和加密算法對數(shù)據(jù)進(jìn)行轉(zhuǎn)換,得到無意義的數(shù)據(jù)即密文扫尖;使用密鑰和解密算法對密文進(jìn)行逆向轉(zhuǎn)換白对,得到原數(shù)據(jù)。
非對稱加密
非對稱加密可以說是現(xiàn)代計算機(jī)網(wǎng)路通訊的安全基石甩恼,無論你是否了解或者聽說過它,只要你使用聯(lián)網(wǎng)的電子設(shè)備沉颂,就會用到它条摸。
- 原理:使用公鑰對數(shù)據(jù)進(jìn)行加密得到密文;使用私鑰對數(shù)據(jù)進(jìn)行解密得到原數(shù)據(jù)铸屉。
用一個簡單的例子來解釋一下非對稱加密:A 要發(fā)送一個消息110
給 B,B 自己先生成一對密鑰(公鑰p 和 私鑰q)彻坛,這對密鑰有一個對應(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 再用自己的私鑰解密消息就好了屹篓,所以非對稱加密的安全關(guān)鍵就是私鑰不對外公開并且只有自己的私鑰才能解自己的公鑰疙渣,這樣就解決了對稱加密通訊中密鑰傳輸丟失的風(fēng)險,因為 A 根本不需要把私鑰發(fā)送給 B抱虐,而發(fā)送出去的公鑰不能用來解密消息。以上示例的整個通訊過程就是非對稱加密通訊的核心思想饥脑。
上圖的模型中加密算法就是加法恳邀,公鑰就是 4懦冰,私鑰就是 6,其中加密算法和公鑰是公開的谣沸,示例模型中拿到公鑰和密文是可以推導(dǎo)出原數(shù)據(jù)的刷钢,而實際應(yīng)用中的加密算法十分復(fù)雜并且通過公鑰和密文無法推導(dǎo)出原數(shù)據(jù),具體可以參考非對稱加密算法 RSA 的算法原理乳附。
簽名和驗證
通過了解非對稱加密我們可以知道同一對密鑰中私鑰是可以解公鑰的内地,那么思考一下公鑰是否可以解私鑰?
我們不妨仔細(xì)看一下非對稱加密解密過程:
如上圖所示赋除,A 通過公鑰+加密算法得到 B阱缓,B 通過私鑰+加密算法得到 C,因為 C = A举农,所以用公鑰再加密一下 C 就可以得到 B 而形成一個循環(huán)荆针,所以公鑰也可以解私鑰加密的數(shù)據(jù)。
于是颁糟,我們就可以用私鑰給數(shù)據(jù)做簽名航背,然后對方收到簽名數(shù)據(jù)用公鑰解密做校驗;在實際應(yīng)用中由于文件大小的不可控棱貌,給文件直接簽名效率很低玖媚,所以一般都是給文件的 hash 值做簽名,因為 hash 的最主要用途就是數(shù)字指紋婚脱,因此通過比對兩個文件的 hash 值是否相等來校驗兩個文件是否相等是普遍的文件校驗手段今魔。通過非對稱加密來簽名和校驗文件的過程如下:
從上圖中不難看出,我們給數(shù)據(jù)簽名的目的只有一個:保證接受方收到的數(shù)據(jù)就是我發(fā)出去的數(shù)據(jù)起惕,中途沒有丟失或被篡改涡贱。
我們從大部分網(wǎng)站上下載一些文件,為安全起見一般他們都會給出文件的 hash 值惹想,用來和你下載到本地的文件做完整性和一致性的校驗问词。
所以給文件簽名的邏輯就是:我要發(fā)送一個文件給對方,那我怎么保證我的文件不會被篡改或丟失嘀粱?把文件的 hash 也發(fā)過去激挪。那我怎么保證我的 hash 不會被篡改?把 hash 進(jìn)行簽名和文件一起發(fā)過去锋叨。
Base64
定義
Base64是一種基于64個可打印字符來表示二進(jìn)制數(shù)據(jù)的表示方法垄分。由于 {\displaystyle 2^{6}=64} {\displaystyle 2^{6}=64},所以每6個比特為一個單元娃磺,對應(yīng)某個可打印字符薄湿。3個字節(jié)有24個比特,對應(yīng)于4個Base64單元,即3個字節(jié)可由4個可打印字符來表示豺瘤。它可用來作為電子郵件的傳輸編碼吆倦。在Base64中的可打印字符包括字母A-Z、a-z坐求、數(shù)字0-9蚕泽,這樣共有62個字符,此外兩個可打印符號在不同的系統(tǒng)中而不同桥嗤。一些如uuencode的其他編碼方法须妻,和之后BinHex的版本使用不同的64字符集來代表6個二進(jìn)制數(shù)字,但是不被稱為Base64泛领。 —— Wikipedia-Base64
簡單理解就是 Base64 是一種能將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成有 64 個字符組成的字符串的編碼算法荒吏。
算法
將原數(shù)據(jù)每 6 位對應(yīng)成 Base 64 索引表中的一個字符并編排成一個字符串(每個字符 8 位)。
Base64 索引表:
編碼“Man”
末尾補(bǔ)齊
用途
- 將二進(jìn)制數(shù)據(jù)的存儲方式和傳輸途徑進(jìn)行了擴(kuò)充(例如可以把圖片經(jīng)過編碼保存到文本文件师逸、可以通過聊天對話框或短信形式發(fā)送司倚、可以在 URL 中加入簡單的二進(jìn)制數(shù)據(jù))
- 普通的字符串在經(jīng)過 Base64 編碼后結(jié)果會變得肉眼不可讀,因此適用于一定條件下的防偷窺
缺點(diǎn)
因為自身原理(6 位變 8 位)篓像,因此每次 Base64 編碼之后动知,數(shù)據(jù)都會增大約 1/3,所以會影響存儲和傳輸性能员辩。
變種:Base58
比特幣使用的編碼方式盒粮,去掉了 Base64 中的數(shù)字 “0”,大寫字母 “O”奠滑,大寫字母 “I”丹皱,和小寫字母 “l(fā)”,以及 “+” 和 “/” 符號宋税,用于比特幣地址的表示摊崭。
Base58 對于 Base64 的改動,主要目的在于用戶的便攜性杰赛。由于去掉了難以區(qū)分的字符呢簸,使得 Base58 對于“人工抄寫”更加友好。另外乏屯,去掉了“+”根时、“/”號后也讓大多數(shù)如軟件可以方便的雙擊選取。
壓縮與解壓縮
含義
- 壓縮:將數(shù)據(jù)使用更具有存儲優(yōu)勢的編碼算法進(jìn)行編碼辰晕。
- 解壓縮:將壓縮數(shù)據(jù)解碼還原成原來的形式蛤迎,以方便使用。
目的
減小數(shù)據(jù)占用的存儲空間含友。
示例
將下面的文本內(nèi)容壓縮:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
使用某種算法壓縮后結(jié)果為:
compress:a:1024;b:105
注:實際應(yīng)用場景中的壓縮算法非常復(fù)雜替裆,上面只是一種演示原型校辩。
壓縮是編碼嗎?
是辆童。所謂編碼召川,即把數(shù)據(jù)從一種形式轉(zhuǎn)換為另一種形式。壓縮過程屬于編碼過程胸遇,解壓縮過程屬于解碼過程。
常見的壓縮算法
JPEG汉形、MP3纸镊、MP4 等。
序列化
把數(shù)據(jù)對象(一般是內(nèi)存中的概疆,例如 JVM 中的對象)轉(zhuǎn)換成字節(jié)序列的過程逗威。對象在程序內(nèi)存里的存放形式是散亂的(存放在不同內(nèi)存區(qū)域、并且由引用進(jìn)行連接)岔冀,通過序列化可以把內(nèi)存中的對象轉(zhuǎn)換成一個字節(jié)序列凯旭,從而使用 byte[] 等形式進(jìn)行本地存儲或網(wǎng)絡(luò)傳輸,在需要的時候進(jìn)行重新組裝(反序列化)來使用使套。
目的
讓內(nèi)存中的對象可以被存儲和傳輸罐呼。
我的博客即將同步至騰訊云+社區(qū),邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=209dz85wu1og0