事情尚未結束呢!咱們前面假設,你們公開公鑰的方式是「發佈在一個衆人可信的網站上」,這種假設是有緣由的。須要臨時交換雙方公鑰的通話協議是不安全的,這裏面存在一個戲劇性的漏洞。舉個例子,假如A和B認爲,任何網站都是不可靠的,他們從未而且從此也不會在網上公佈本身的公鑰。爲了加密通訊,A須要親自告訴B他的公鑰,B也須要親自告訴A本身的公鑰。收到公鑰後,雙方便用對方的公鑰加密進行數據傳輸。由於用這個公鑰加密後,只有對方纔能解開密碼,所以雙方都認爲這條通訊線路是安全的。其實,他倆的麻煩大了。這條線路並非安全的,第三者能夠用一種很搞笑的方式來竊聽消息。假設有一我的C知道A和B之間將有一次加密通話。C劫持了A和B之間的通信線路。如今,A把他的公鑰發給B,這個公鑰傳到一半時被C攔截下來,因而C得到了A的公鑰;C再把他本身的公鑰發給B,讓B把C的公鑰錯當成A的公鑰。一樣地,B把他本身的公鑰發給A,被C攔截下來。C把本身的公鑰發給A,讓A覺得那是B的公鑰。之後,每當A給B發加密消息時,A實際上是用C的公鑰在加密;C把A的消息解密後,再用B的公鑰加密後傳給B。相似地,一旦B給A發送消息,C均可以將消息解密,並用A的公鑰進行加密後傳過去。此時,A和B都覺得本身在用對方的公鑰加密,並都能用本身的私有鑰匙解開對方傳來的密文;卻不知,這中間有人僅僅用了一點雕蟲小技,無聲無息地竊走了全部的信息。C正是利用了公鑰加密術「誰均可以加密」的性質,結結實實地玩弄了A和B。這種攻擊方法叫作「中間人攻擊」。
這讓我想起了經典的國際象棋騙術。一個象棋白癡宣稱本身是個大牛。爲了證明這一點,他將要與兩位大師同時對弈。他說,我先下後下都能贏。因而,在與大師A的對弈中他爲白方,與大師B對戰則執黑。結果呢,兩盤比賽下來竟然都打成了平手。怎麼回事呢?其實那個象棋白癡耍了個小伎倆,他把大師A走的棋記了下來,跑到另外一邊去下給B看,又把B的應着原封不動地搬到了和A的棋局上。來來回回搞了半天,他本身只起了個傳遞信息的做用,真正在對弈的是兩個大師。算法
怎樣防止這種中間人攻擊呢?中間人之因此可以得逞,關鍵就是,不管是網絡通話仍是國際象棋,雙方老是一先一後地發送信息。不過,在網絡通信中,咱們有一種很特別的辦法,他能夠迫使中間人沒法再扮演「即時翻譯」的角色。首先,A把想說的話(最好是可以證實本身身份的話)進行加密,同時B也完成相同的工做。而後,A把他的加密消息的前面一半傳給B,B收到後也把他的密文的一半傳給A;A再把剩下的部份傳給B,以後B也把他的密文的另外一半回傳給A。此時,A和B分別用本身的私鑰進行解密,查看對方發來的消息。這帶給中間人C一個不可逾越的障礙:兩段密文要合在一塊兒才能解開,中間人拿着其中一半密文,那是一點辦法都沒有。此時,中間人陷入了一個很是窘迫的境地,他只有兩條路可選:要麼硬着頭皮把這半截密文發給B,當B獲得所有密文後會發現用他本身的私鑰根本解不開,從而意識到中間有人搗亂;要麼就忽略這半截密文,本身編幾句A想跟B說的話,用B的公鑰加密併發一半給B。如此一來,中間人須要編造全部A和B之間的對話,這須要至關厚的臉皮,風險異常之大,要不了多久便會露出馬腳。安全
RSA算法還有一個特別的應用。注意到公鑰和私鑰所對應的兩個函數是互逆的,所以若是我用私鑰來加密,用公鑰一樣能夠恢復原來的數據。可是,用我本身的密鑰加密,而後你們均可解密,這有什麼用處呢?不妨來看看這樣「加密」後的效果吧:第一,貌似是最荒謬的,你們均可以看到源文件;第二,很關鍵的,你們只可以看源文件,但不能改動它;第三,知足上述兩個要求的文件別人是作不出來的。
這些性質正好完美地描述出「簽名」的實質。爲了防止釣魚網站騙取你的帳戶和密碼,正牌的那個服務器須要發送一條消息,以證實本身確實是惟一的服務提供商。爲此,你能夠發送一個隨機字符串過去,要求服務器用它的私鑰加密。服務器傳回他加密過的字符串後,若你用他的公鑰解密能恢復出原來的字符串,則說明對方必定是正宗的服務提供商。只有擁有私鑰的人才能作到這一點,別人是沒法僞造這個「簽名」的。
數字簽名還有一些其它的特殊變化。考慮這樣一種狀況,我有一份祕密文件須要簽名,但我不但願簽名者看到這份文件的內容。這種看似很不合理的狀況確有發生。例如在證人保護計劃中,我是一個特工,我須要保護一個很是可愛的無辜小MM。爲了把她安置到一個偏遠的安全地,我須要讓上級簽署各類通行證實文件;但爲了安全起見,我不但願把安全地的位置泄露給任何人。爲此,我但願個人上級對文件進行簽名,但保證他們徹底不知道文件內容是什麼。知足這種要求的簽名協議叫作「盲簽名」。爲了獲得一種「盲簽名」算法,考慮用RSA進行簽名的本質:假設待簽名的文本爲(不超過模數n的)t,則咱們實質上但願獲得t^d mod n,其中n是模數,d是簽名者的私人鑰匙。咱們的目的是,對文本t進行干擾(例如在t上面加一個大數,或者乘一個大數,或者取t的倒數的正弦值的-π次方的天然對數),讓簽名者不知道t是什麼;但簽名者簽名以後,咱們還能除去剛纔的干擾因子,還原爲t^d mod n。所以,咱們須要想一個奇妙的辦法,讓被幹擾的文本簽名後,干擾因子頭上的「d」正好消失了。回憶以前講過的結論m^(ed)≡m (mod n),咱們當即想到了盲簽名算法:我把明文t乘上一個隨機數k的e次方(e是公開鑰匙),把t*(k^e)傳給簽名人。注意咱們選取的k必定要與n互質,不然k是大質數p或q的倍數,「干擾」的結果必然爲0。這下,簽名人固然不可能知道t是什麼,由於他不知道隨機數k是多少。他對t*(k^e)進行簽名,傳回來的結果即爲t^d * k^(ed) mod n。但k^(ed)模n就等於k,因而這個簽名結果實際上就是t^d * k mod n。如今,我只須要把該結果除以只有我才知道的k(即乘以它在模n剩餘類環中的逆元,這個逆元保證存在,由於k和n互質),即獲得了我須要的簽名文件t^d mod n。
盲簽名協議並非只有特工纔可能用到的東西,它的應用範圍其實至關廣。在生活中,咱們每一個人均可能用到過盲簽名。一個最經常使用的例子就是投票協議——中央機構須要肯定每張選票都來自合格的選舉人,而且每一個人最多投了一次票;但同時選舉人又不但願在投票過程當中泄露本身的選票內容。可是,爲了檢查選票的來源是否可靠,中央機構必然要鑑別每張選票所屬的投票人。怎麼辦呢?此時,盲簽名協議就派上用場了。每一個選舉人在本身的選票前面加上一個隨機字符串做爲前綴(防止之後被暴力破解),而後乘上隨機數k的e次方,再連同一份(未被幹擾的)身份證實,一同遞交給中央機構。中央機構檢查身份證實,確認這張(被幹擾過的)選票來自合格的選舉人。而後中央機構給這張選票簽名,回傳給選舉人。選舉人將簽名結果除以k,用中央機構的公鑰檢查看簽名是否有效,隨機字符串是否和本身當初設定的同樣。接着投票人匿名提交這份由中央機構簽過名的(且不帶干擾因子的)選票。中央機構收到選票,用公鑰解密看簽名是否有效。這樣,中央機構既能夠確信每張選票都來自合格的投票人,嚴格實行一人一票制度,又不能追查出任何一個投票者的選票內容。服務器
更復雜的盲簽名協議來源於這樣一種特殊狀況:恐怖分子答應供出炸彈的位置,前提條件是須要獲得一系列保證無罪逃脫的簽名文件,包括新身份、新護照,以及總統親自簽署的免起訴書和安全離境的通行證。同時,恐怖分子又須要確信政府不能知道他的新身份和潛逃地。這須要政府在不知道文件內容的狀況下籤署協議。這與剛纔所談的盲簽名有什麼區別呢?一個巨大的區別就是,要求盲簽名的不是特工,而是壞蛋,政府在沒有看到文件以前不能隨意簽名。萬一恐怖分子要求盲簽名的文件其實是一份要求政府保護全體恐怖分子的安全,保證全部人永不被通緝永不被起訴,並沒有償提供恐怖組織基地和鉅額資助等不平等條約該咋辦?所以,這裏須要一種比盲簽名要求更高的協議:簽名者不能看到文件內容,但要相信文件的內容是什麼。
看起來這彷佛是辦不到的,但事實上這是有可能的。咱們有一個很是簡單的辦法,它是一個基於機率的協議。恐怖分子能夠起草十份文件,每份文件裏都包含了一個不一樣的新身份和潛逃地。而後恐怖分子用十個不一樣的隨機數對這十份文件進行干擾,傳給政府。政府選取其中的九份文件,向恐怖分子索要干擾因子。恐怖分子把對應的那九個k值傳過去,政府對其進行解密,從而看到這九份文件都是符合要求的文件(只是文件中具體的身份名字和潛逃地點不同)。政府對最後一個文件進行簽名,並把簽名結果回遞給恐怖分子。恐怖分子除去幹擾因子,獲得他須要的簽名文件。這樣,恐怖分子能夠保證政府不知道他的新身份和潛逃地,同時政府也能保證恐怖分子不會耍詐。恐怖分子只有1/10的機率能夠騙到政府,顯然不值得恐怖分子去冒這個險。爲安全起見,「10」這個數字還能夠任意加大。網絡