對稱加密
我們要對壹段文字加密,過程可能是這樣的:
明文 "Hello World" ?算法
-------> ? 密文 "gsHgw832iSI"密鑰 "111222"
解密過程是這樣的:
密文 "gsHgw832iSI" ?算法
-------> ? 明文 "Hello World"密鑰 "111222"
這裏的關鍵是,加密和解密,密鑰相同,算法也相同(互逆),所以稱之為“對稱”。
最安全的對稱加密算法:壹次性板
有沒有絕對安全的加密算法呢?有!
如果明文中的每壹個字符,都通過密鑰中的壹個字符,映射成密文中的壹個字符,密鑰的長度等於文字的長度,且密鑰只用壹次,那麽這種密鑰被形象地稱作“壹次性板(one-time pad)”。
由於壹次性板的長度等於明文和密文的長度,而且用完就要放棄,所以密鑰不可能產生重復,因而相當安全,即使在理論上也不可能破解。試想壹下,即使妳猜對了密鑰,得出了明文,但是也有可能,密鑰是另壹個,能夠得出另壹種明文,妳怎能確定明文是前壹個而不是後壹個呢?事實上,在密文確定的情況下,任意指定壹個明文,都有相應的密鑰和它對應!所以試圖破解它完全沒有意義。
但是,我們通常需要加密的信息量都很大,如果要加密1GB的文件,密鑰也得有1GB,那傳輸和保存密鑰就太過恐怖。所以,壹次性板不現實。
妥協:密鑰長度固定的對稱加密
對於密鑰長度小於明文和密文長度的算法,理論上是可以破解的,因為在密文確定的情況下,並不是任意指定壹個明文,都有相應的密鑰和它對應(因為同壹個密鑰要加密不同的塊,如果明文不是原文,則不可能求出壹個密鑰,使之能夠適用於所有的塊)。
但如果密鑰長度足夠,可近似認為不可破解。專家們認為,112位密鑰已足夠安全,因為要破解它所花的時間是天文數字。為了湊整,通常使用128位。AES算法是當今對稱加密算法的標準。
大問題:密鑰如何發送
A要向B發送壹份機密文件,他壹定會用密鑰K來加密。他先把密文發給了B,這沒有問題。但問題是,如何把密鑰K告訴B,以便他解密?
如果直接發送密鑰,那麽任何人都可以窺知該密鑰。只要該人曾截獲過他發送的文件,就可以解密。
把密鑰K再用壹個新密鑰加密,行嗎?當然不行,因為,妳如何傳輸這個新密鑰?
這時A終於想出了壹個辦法,把密鑰保存在USB盤裏,親手交給B。這是個好方法,確實“解決”了密鑰發送的問題。但是仔細想想,他完全可以把文件直接放在USB盤裏給B,又何必加密,弄得那麽麻煩?不過最重要的是,如果在當今世界,傳輸信息居然還要見面,這豈不是回到了原始時代了嗎?
這是個著名的問題:密鑰交換(key exchange)問題。看來,沒有壹個辦法可以解決這個問題。
直到,出現了非對稱加密算法。
非對稱加密
如果有壹種算法,用於加密和解密的密鑰是不同的(即:非對稱),它能否解決密鑰交換問題?
答案是:可以。B可以先把加密密鑰發送給A,然後A對文件加密,接著A把密文發送給B,最後B用解密密鑰來解密。整個過程,極其完美。因為加密密鑰只能用來加密,所以即使該密鑰被截獲,也並不會導致文件被解密。於是我們就可以把加密密鑰叫做“公鑰”,把解密密鑰叫做“私鑰”。
但是仔細想想,這種機制對算法有著極高的要求:
公鑰和私鑰必須通過確定的函數壹壹對應。
但通過公鑰直接求得私鑰必須極難。
利用質數的算法,就是最簡單的滿足此要求的算法。它基於這樣的數學原理:給出兩個很大的質數,要求出它們的乘積很容易;但知道它們的乘積,要求出是哪兩個質數相乘卻極難(人類並沒有找到快速的辦法,只能壹個個試)。舉個例子,讓計算機分解壹下這個大合數:
1522605027922533360535618378132637429718068114961380688657908494580122963258952897654000350692006139=37975227936943673922808872755445627854565536638199×40094690950920881030683735292761468389214899724061通過質數求得乘積,任何計算機都可以在不到1微秒的時間內完成,但分解的話就得花很長時間。這還只是330位(十進制100位)的合數,RSA算法中實際應用的大合數高達2048位,分解的話幾百億年也完不成,所以非常安全。
試想壹下,如果我們把兩個大質數當作私鑰,把它們的乘積當作公鑰,只要有相應的加密和解密算法,就可以解決密鑰交換問題。RSA的原理即是基於這壹理論,具體實現稍微復雜些(公鑰和私鑰並不是直接通過這個方法得出,要經過壹些變換,這裏就不做討論了)。
但是,這樣的密鑰交換真的壹點問題也沒有了嗎?不!
數字簽名
有壹個極其重要的問題還未解決,即:誰能證明向A發送公鑰的是B?如果隨便哪個人都能冒充B,那麽A就很容易上當了。A可能會用別人的公鑰來加密,然後發送給B,發送的過程中又被別人截獲。結果,B不能讀取這個文件,不懷好意的人倒解密了這個文件。
看來,有必要模仿在生活中有著悠久歷史的“簽名”。
我們先看看傳統簽名的特點:
只有簽名者自己才能簽出這個名字(圖案)。
外人雖無法模仿,但可以檢查。模仿很難,但檢查很容易。
您是否由此聯想到了非對稱加密?“正向容易、反向很難”不正是非對稱加密的特點嗎?傳統的非對稱加密是“公鑰加密、私鑰解密”。如果反壹反,變成“私鑰加密、公鑰解密”,我們驚訝地發現這簡直是天作之合:
只有簽名者自己可以通過用私鑰加密信息來對該信息進行簽名。
外人可以通過用公鑰解密來檢查,如解密成功,即證實,否則即證偽。
這就是數字簽名。
到了這裏,只剩最後壹個環節了,那就是:誰來證明該公鑰代表B?看來,只有引入權威機構,告訴大家每個公鑰代表的分別是誰,檢查才有意義。
這是密碼學中最復雜的難題,促使人們提出了“數字證書”和“公鑰基礎設施”的光輝思想。
數字證書、公鑰基礎設施
這樣的權威機構稱為CA (Certificate Authority,證書機構),它們的職責就是頒發證書,證明每個公鑰代表的分別是誰。這裏的“誰”可以是個人,可以是組織,也可以是另壹個CA。這樣,就可以組成壹個龐大的“公鑰基礎設施(PKI)”。
?根CA ? |?-------------------
?| |
二級CA 二級CA ?| |
---------- ? 個人 | |三級CA ? 三級CA ? |? ----------
? | |
?個人 個人
試想,我們讓每個證書含有如下內容:
主體(頒發者的公鑰和被頒發者的公鑰)
頒發者用私鑰對主體所做的數字簽名
這樣,只要根CA確定,壹個龐大的信任鏈就建成了。
根CA,所對應的證書稱為根證書,是操作系統生產商人為設定的。Windows、macOS、Linux中,默認信任的根CA有幾十個至數百個不等。
我們開發軟件的時候,也可以自己建壹個根CA,方法是讓頒發者的公鑰和被頒發者的公鑰相同,這樣的證書(即“自簽名證書”)會被操作系統識別為根證書,然後,妳需要讓操作系統“信任該證書”。但註意,絕對不要把這種證書發送給陌生人,然後叫他點擊信任該證書,因為這對別人有風險,畢竟我們不能強迫別人信任。
HTTPS
最後我們終於可以回到HTTPS了。要了解HTTPS的詳情對程序員來說意義不大,重要的是,通過以上章節,我們終於可以相信,HTTPS的安全性是有技術保障的。人們可以確信,訪問的網站的確是這個網站,而不是黑客冒充的。也可以確信,傳輸的所有數據都經過加密,外人無法讀取。
CA如何給網站頒發證書?首先妳在自己的電腦中生成私鑰和公鑰,把公鑰發給CA,然後CA驗證妳是否是網站的所有者,有數種方法:
發壹封郵件給webmaster@該域名.com或postmaster@該域名.com,如果妳能收到,就證明妳是網站的所有者。
讓妳在網站的某個目錄加入壹個文件,如果妳能,就證明妳是網站的所有者。
讓妳在域名的DNS中加入壹個項目,如果妳能,就證明妳是網站的所有者。
驗證後,CA會把證書發給妳。
性能優化
非對稱加密比對稱加密慢100倍(軟件實現)或1000倍(硬件實現)。如果純粹使用上述加密、解密和簽名手段,性能是很差的。這時要用到密碼學中的另壹個工具:哈希(hash)。
Hash有很多同義詞:指紋、摘要、雜湊、校驗和、散列,指的是壹種數學方法,用很少的信息來使它“等價於”大量信息。這聽起來有些不可思議,但想想,指紋不正是具有這個特征嗎?通過壹個指紋,可以確定壹個人;反過來,通過壹個人,也可以確定他的指紋。其妙處在於,指紋所含的信息量遠比壹個人所含的信息量要少(但仍然是天文數字,所以仍然不會重復)。
例如,我們計算這段文字的hash:
A hash function is any function that can be used to map data of arbitrary size to data of fixed size. The values returned by a hash function are called hash values, hash codes, digests, or simply hashes. One use is a data structure called a hash table, widely used in computer software for rapid data lookup. Hash functions accelerate table or database lookup by detecting duplicated records in a large file. An example is finding similar stretches in DNA sequences. They are also useful in cryptography. A cryptographic hash function allows one to easily verify that some input data maps to a given hash value, but if the input data is unknown, it is deliberately difficult to reconstruct it (or equivalent alternatives) by knowing the stored hash value. This is used for assuring integrity of transmitted data, and is the building block for HMACs, which provide message authentication.采用SHA-256哈希算法,得出的hash是:
4da07b60cb90742026d7fd9ece673bfad677422e8261c1cc29ff00d0d6be4b7a無論輸入的數據有多大,哪怕100GB,其SHA-256值也始終是256位(十六進制64位)。Hash算法的速度比非對稱加密快得多,所以在實際應用中,都是先把信息hash壹下,再給hash簽名,而不是給整個信息簽名。這樣做大大加快了速度,又不失安全。