原文網址:加密和簽名的區別及應用場景_IT利刃出鞘的博客-CSDN博客
簡介
本文介紹加密和簽名的區別及應用場景。
RSA是一種非對稱加密算法,?可生成一對密鑰(私鑰和公鑰)。(RSA可以同時支持加密和簽名)。
加密和簽名的區別
加密
用公鑰對明文加密,用對應的私鑰才能解密,防止明文被人看到。
簽名
用私鑰對明文簽名,用對應的公鑰驗簽(驗證簽名),防止數據被篡改。
加密流程
(友情提醒,以下場景僅為說明基本的加密流程,不符合真實應用)。
自從潘金蓮放窗簾打到西門慶的頭之后,他們就開始秘密交往,潘金蓮的丈夫武大郎總是懷疑他們倆在偷情,苦于沒有證據,在暗地里觀察。
一天,潘金蓮想寫情書撩西門慶,但是情書內容不想被武大郎知道,于是潘金蓮就告訴西門慶,采用 RSA 加密的方式來傳遞書信。
于是,西門慶就用 RSA 生成了一對密鑰(一個公鑰,一個私鑰),將公鑰的內容寫成一封信,然后寄出去送給潘金蓮。
武大郎觀察到了西門慶發出的信件,偷偷地將這封信件攔截了下來并復制了一份自己藏著,然后又將信件原路寄給潘金蓮,以免打草驚蛇,以為這樣就可以神不知鬼不覺地拿到他們之間偷情的證據。武大郎打開信封,發現里面寫的只是公鑰內容。
信封(公鑰)傳達到潘金蓮手上后,潘金蓮就開始寫情書了:“巴拉巴拉各種虎狼之詞”(明文)。寫好后裝入信封想直接寄回給西門慶,但是馬上停住了,心想,這封信如果這樣直接寄出去,中途被武大郎攔截的話,不就什么都被看到了嗎?于是潘金蓮用西門慶發過來的公鑰對自己寫的情書進行加密,生成了一份完全看不懂的信息“eSYJztu3RqGZBcRPvINyg2Hpmu…”(密文)。然后這封信可以放心的寄給西門慶了。
果然,武大郎偷偷觀察到了潘金蓮發出的信件,又進行同樣的操作:攔截,復制,原路寄回給西門慶。當武大郎打開復制回來的信件(密文)后,發現又是一堆看不懂的信息,然后嘗試用之前從西門慶那封信復制下來的公鑰進行各種 RSA 操作(用公鑰加密,解密),結果發現無論怎么操作,得到的都是看不懂的信息。單憑這封全是亂碼的信件并不能坐實潘金蓮與西門慶偷情。
信封(密文)最終傳達到西門慶手上,西門慶拿著自己的密鑰(密鑰只有自己知道,其他人都不知道),對信封進行解密,于是看到了信封原來的內容:“巴拉巴拉各種虎狼之詞,…”西門慶被撩得心花怒放。
結論
以上是使用 RSA 進行加密解密的一個虛擬場景。可見,加密后消息的傳遞是單向的,只有潘金蓮發加密消息給西門慶,西門慶沒法直接發有效的加密消息給潘金蓮(因為潘金蓮沒有私鑰)。除非雙方都各自生成自己得 RSA 公鑰私鑰,并且互相發送各自的公鑰給對方,這樣雙方就可以加密通訊了。
整個通訊流程(單向)
- A 明文告訴 B,我現在要發送消息給你,請使用 RSA 進行加解密(這條消息會被 C 截獲,C 知道了 AB 之間要通訊并使用 RSA 加密)。
- B 生成一對密鑰(公鑰,私鑰),然后將公鑰發送給 A(這個公鑰會被 C 截獲,但是 C 拿不到私鑰)。
- A 把要發送的消息用公鑰進行 RSA 加密,得到密文,然后發送給 B(這個密文被 C 截獲,但 C 無法知道密文所對應的明文的內容,因為 C 只截獲到公鑰,沒有私鑰,用公鑰對密文怎么操作都得不到明文)。
- B 拿到密文后,使用自己的私鑰解密,得到明文。
B如果想發加密的消息給A,則將以上流程反著來走一遍就行了,只不過就需要由A來生成密鑰(公鑰,私鑰)。
也就是說:
- A想給B發加密消息,由B來生成密鑰對(公鑰B,私鑰B),對外公布公鑰B。
- B想給A發加密消息,由A來生成密鑰對(公鑰A,私鑰A),對外公布公鑰A。
簽名流程
西門慶想給潘金蓮寫信,告訴她"午時去王婆家做衣服"。潘金蓮要如何才能確信這條消息真的是西門慶發給她的呢?萬一這條消息是哪個潑皮亂發的,那潘金蓮豈不是白跑一趟?
RSA 算法有一組對稱操作:用公鑰加密的密文,用私鑰解密可以得到明文;反過來,用私鑰加密的密文,用公鑰解密也可以得到明文。
潘金蓮手上是有西門慶的公鑰的(延續上一場景的公鑰),如果西門慶用私鑰對消息進行加密,潘金蓮用公鑰進行解密,如果解密后能得到明文,那就能說明:發送者確實是西門慶本人。因為除了西門慶外,沒有人擁有私鑰,能用這個公鑰解密的密文一定是密鑰的持有者(即西門慶)所發出的。
于是,西門慶寫了一條消息“午時去王婆家做衣服”(明文),然后用私鑰將這條消息加密生成了“PvINeSYJuZBcRygztu3Gpm2HRq…”(密文)一共兩條消息(一條明文一條密文)合并寫在一封信里寄給了潘金蓮。
潘金蓮收到信后,用公鑰對信件的密文部分“PvINeSYJuZBcRygztu3Gpm2HRq…”進行 RSA 解密,得到“午時去王婆家做衣服”。然后和信件前面部分里對比,發現內容一模一樣,這就確認了消息確實是西門慶發的。
說明
西門慶用私鑰對前面明文內容加密,然后追加到明文后面的這種做法,就是簽名。
潘金蓮用公鑰對簽名解密,并與前面明文部分進行比對,這個做法就叫做驗簽。
為什么可以這么做?不怕被武大郎中途截獲修改嗎?不怕。因為如果武大郎中途截獲了這封信,并修改成“申時去王婆家喝茶”但由于武大郎沒有私鑰,無法對明文加密,因此無法修改后面的簽名部分。當潘金蓮收到信件后,用公鑰解密簽名部分得到的內容,跟被篡改的明文內容一對比,發現不一致,就說明消息被篡改了,發送者并不是西門慶。
又或者武大郎用自己的私鑰對篡改后的明文進行加密簽名,再發送給潘金蓮,潘金蓮用手上西門慶的公鑰根本無法解密武大郎篡改后的加密部分,這種情況也可以確定發送者不是西門慶。
從這里可以看出,加密和簽名,這兩種場景是不一樣的。
- 加密,是為了確保通訊內容不被第三方知道。
- 簽名,是為了確保發送者確實是本人,并且消息沒有被篡改過。
在加密場景下,并不關心消息是否被篡改過。可能武大郎第一次截獲西門慶公鑰時,偷偷換成了自己生成的公鑰,并發給潘金蓮。潘金蓮用公鑰加密后發出的情書被武大郎截獲之后,武大郎用自己的私鑰也是可以解密出來那些虎狼之詞的(中間人攻擊),但是加密場景并沒有解決這些問題,加密僅是為了不讓私鑰持有者以外的第三方知道消息的內容。
在簽名場景下,只關心消息沒有被篡改,并不關心內容是否保密。比如“午時去王婆家做衣服”就是明文傳輸,任何人都知道這個信息。簽名場景并不負責保密內容,僅僅是為了說明這條消息是西門慶本人發出的,并且沒有被篡改過。
項目場景
公鑰之所以叫公鑰,意思是可以公開給任何人。任何人拿到一把鎖都是沒有意義,所以對鎖的定義就是不能打開鑰匙,即不能用私鑰加密,公鑰解密(切記,我說的是加密場景不能用私鑰加密,公鑰解密,加簽的場景正好相反,恰恰是私鑰加密,公鑰解密,不過我們通常會說成私鑰加簽,公鑰驗簽)。
驗簽
實際項目中,一般使用明文的哈希值來進行驗簽。
數字簽名屬于非對稱加密,非對稱加密依賴于復雜的數學運算,包括大數乘法、大數模等等,如果數據量大,那么計算數字簽名將會比較耗時。所以先將原數據進行 Hash 運算,得到的 Hash 值就叫做摘要,然后對摘要計算簽名。不同的內容計算出的摘要是不同的。
摘要最好是不可逆轉的,這樣即使第三方使用公鑰解簽出摘要,也無法根據摘要反推出原本的數據。一般使用 MD5 作為 Hash 函數,MD5 輸出的結果固定為?128 位。
流程
發送者A用私鑰對摘要計算簽名,將明文和摘要的簽名發給B。接受者 B 收到后,拿簽名部分,用 B 的公鑰解密,可以解密成功(得到摘要1),就能證明確實是 B 發的。再對郵件內容(明文)使用相同的散列函數計算出摘要2,與之前得到的摘要1進行對比,兩者一致就說明信息未被篡改。
Java和Python不同
java的小伙伴可能會這么說:服務端保存私鑰,客戶端保存公鑰:
- 客戶端請求接口時,用公鑰加密,服務端收到信息用私鑰解密
- 服務端返回的內容用私鑰加密,客戶端收到后,用公鑰解密
這樣用一對非對稱密鑰就可以完成整個交互的加密過程了,并不像你說的公鑰可以公開給任何人,我們的公鑰也是保密的,只給到指定的人或客戶端。這里的第2步,其實是把公鑰當私鑰用了,來個了公私鑰角色互換。也沒有人說這么做不可以,反正只要保證“私鑰”不泄漏就可以。
為了保證靈活性,所以java允許這么做,而python就要嚴格一點。
項目應用
電子郵件
這里不是指的落款,而是對電子郵件進行數字簽名,以保證電子郵件傳輸中的機密性、完整性和不可否認性,確保電子郵件通信各方身份的真實性。
軟件下載
在網絡上下載軟件,我們如何判斷所下載的為原軟件,而不是被篡改后的軟件呢?這里就可以利用到數字簽名,軟件作者可以對軟件加上數字簽名,用戶在軟件下載之后驗證數字簽名,看簽名是否一致,就可以識別出軟件是否遭到篡改。
SSL/TLS
SSL/TLS:客戶端在認證服務器身份是否合法時,會使用服務器證書,它就是加上了數字簽名的服務器公鑰。相對地,服務器為了對客戶端(用戶)進行認證也會使用客戶端證書。