前言:
在互聯(lián)網(wǎng)中,由于它聯(lián)結(jié)的是全世界范圍的企業(yè)和個(gè)人瞒瘸,所以會(huì)面臨很多需要對(duì)數(shù)據(jù)進(jìn)行加密處理的情況坷备。舉例來(lái)說(shuō),在網(wǎng)店購(gòu)物時(shí)用戶輸入的信用卡卡號(hào)情臭,就是應(yīng)該被加密傳輸?shù)拇硇詳?shù)據(jù)省撑。假設(shè)卡號(hào)未經(jīng)加密就被發(fā)送出去,那么就會(huì)面臨卡號(hào)被同樣接入互聯(lián)網(wǎng)的某人盜取俯在,信用卡被其用來(lái)肆意購(gòu)物的危險(xiǎn)丁侄。因此像這種網(wǎng)店頁(yè)面的 URL,通常都是以 https:// 開(kāi)頭朝巫,表示數(shù)據(jù)正在使用加密的方式進(jìn)行傳輸。
一石景、先來(lái)明確一下什么是加密
在作為加密對(duì)象的數(shù)據(jù)中劈猿,蘊(yùn)含著文本拙吉、圖像等各種形式的信息。但是揪荣,由于計(jì)算機(jī)會(huì)把所有的數(shù)據(jù)都用數(shù)字表示筷黔,所以即便數(shù)據(jù)有各種展現(xiàn)形式,對(duì)其加密的技術(shù)卻是基本相同的仗颈。因此我們就假設(shè)加密的對(duì)象僅限于文本數(shù)據(jù)佛舱。
文本數(shù)據(jù)可以由各種各樣的字符構(gòu)成。其中每個(gè)字符都被分配了一個(gè)數(shù)字挨决,我們稱之為“字符編碼”请祖。定義了應(yīng)該把哪個(gè)編碼分配給哪個(gè)字符的字符編碼體系叫作字符集。字符集分為 ASCII 字符集脖祈、JIS 字 符集肆捕、Shift-JIS 字符集,EUC 字符集盖高、Unicode 字符集等若干種慎陵。
在圖1中,以十進(jìn)制數(shù)字列出了大寫拉丁字母(A 至 Z)的 ASCII 編碼喻奥。計(jì)算機(jī)會(huì)把文本數(shù)據(jù)處理成數(shù)字序列席纽,例如在使用了 ASCII 編碼的計(jì)算機(jī)中,就會(huì)把 NIKKEI 處理成“78 73 75 75 69 73”撞蚕∪筇荩可是只要把這一串?dāng)?shù)字轉(zhuǎn)換為對(duì)應(yīng)的字符顯示在屏幕上,就又變成了人們 所認(rèn)識(shí)的 NIKKEI 了诈豌。通常把這種未經(jīng)加密的文本數(shù)據(jù)稱為“明文”仆救。
數(shù)據(jù)一旦以明文的方式在網(wǎng)絡(luò)中傳輸,就會(huì)有被盜取濫用的危險(xiǎn)矫渔, 因此要對(duì)明文進(jìn)行加密彤蔽,將它轉(zhuǎn)換成為“密文”。當(dāng)然密文也僅僅是一串?dāng)?shù)字庙洼,但是如果是把密文顯示在屏幕上顿痪,那么在人類看來(lái)顯示的也只不過(guò)是讀不懂、沒(méi)有意義的字符序列罷了油够。
雖然存在各種各樣的加密技術(shù)蚁袭,但是其中的基本手段無(wú)外乎還是字符編碼的變換,即將構(gòu)成明文的每個(gè)字符的編碼分別變換成其他的數(shù)值石咬。通過(guò)反轉(zhuǎn)這種變換過(guò)程揩悄,加密后的文本數(shù)據(jù)就可以還原。通常把密文還原成明文的過(guò)程(即解讀密碼的過(guò)程)稱為“解密”鬼悠。
二删性、錯(cuò)開(kāi)字符編碼的加密方式
代碼清單1 中亏娜,列出了一段用于加密的示例程序。在該程序中蹬挺,使用了如下加密方法:將文本數(shù)據(jù)中每個(gè)字符所對(duì) 應(yīng)的字符編碼一律向后錯(cuò)三個(gè)维贺,即給原字符編碼的值加上 3。運(yùn)行這段程序巴帮,在最初彈出的窗口中輸入要加密的文本數(shù)據(jù)(明文)溯泣,例如就輸入 NIKKEI,然后單擊 OK 按鈕榕茧。在接下來(lái)彈出的窗口中會(huì)顯示出加密后的文本數(shù)據(jù)(密文)垃沦。因?yàn)槊總€(gè)字符的編碼都向后錯(cuò)了三個(gè),所以得到的是 QLNNHL雪猪。這樣的話栏尚,即便是被人偷偷地看到了,那個(gè)人也無(wú)法理解這個(gè)字符串的意義只恨。
// 代碼清單1 用給字符編碼加上 3 的方法加密
plaintext = InputBox("請(qǐng)輸入明文译仗。")
cipher = ""
For i = 1 To Len(plaintext)
letter = Mid(plaintext, i, 1)
cipher = cipher & Chr(Asc(letter) + 3)
Next
MsgBox cipher
因?yàn)榧用軙r(shí)使用的是將字符編碼向后錯(cuò)三個(gè)的方法,所以只要再將字符編碼向前挪三個(gè)就可以實(shí)現(xiàn)解密官觅。代碼清單 10.2 中就是解密程序纵菌。與進(jìn)行加密的程序相反,解密使用的是從字符編碼中減去 3 的方 法休涤。在最初彈出的窗口中輸入密文咱圆,我們就輸入剛剛得到的 QLNNHL,然后單擊 OK 按鈕功氨。在接下來(lái)彈出的窗口中就會(huì)顯示出解密后的明文 NIKKEI序苏。
// 代碼清單2 用把字符編碼減去 3 的方法解密
cipher = InputBox("請(qǐng)輸入密文。")
plaintext = ""
For i = 1 To Len(cipher)
letter = Mid(cipher, i, 1)
plaintext = plaintext & Chr(Asc(letter) - 3)
Next
MsgBox plaintext
也就是說(shuō)捷凄,加上 3 就是加密忱详,減去 3 就是解密。因此通常把像 3 這樣用于加密和解密的數(shù)字稱為“密鑰”跺涤。如果事先就把 3 這個(gè)密鑰作 為只有數(shù)據(jù)的發(fā)送者和接受者才知道的秘密匈睁,那么不知道這個(gè)密鑰的 人,就無(wú)法對(duì)加密過(guò)的數(shù)據(jù)進(jìn)行解密桶错。
下面再試著編寫一個(gè)加密程序吧航唆。這次讓密鑰的值也可以由用戶指定吧。該程序通過(guò)把每一個(gè)字符的編碼與密鑰做 XOR 運(yùn)算 (eXclusive OR院刁,邏輯異或運(yùn)算)糯钙,將明文轉(zhuǎn)換成密文(如代碼清單3 所示)。XOR 運(yùn)算的有趣之處在于,用 XOR 運(yùn)算加密后的密文超营,可以通過(guò)相同的 XOR 運(yùn)算解密鸳玩。也就是說(shuō),一個(gè)程序既可用于加密又可用于解密演闭,很方便。
// 代碼清單3 通過(guò) XOR 運(yùn)算進(jìn)行加密和解密
k = InputBox("請(qǐng)輸入密鑰颓帝。")
key = CInt(k)
text1 = InputBox("請(qǐng)輸入明文或密文米碰。")
text2 = ""
For i = 1 To Len(text1)
letter = Mid(text1, i, 1)
text2 = text2 & Chr(Asc(letter) Xor key)
Next
MsgBox text2
XOR 運(yùn)算的法則是把兩個(gè)數(shù)據(jù)先分別用二進(jìn)制表示,然后當(dāng)一個(gè) 數(shù)據(jù)中的某一位與另一個(gè)數(shù)據(jù)中的 1 相對(duì)時(shí)购城,就將這一位反轉(zhuǎn)(若這一位是 0 就變成 1吕座,是 1 就變成 0)。因?yàn)槭强糠D(zhuǎn)數(shù)字實(shí)現(xiàn)的加密瘪板,所以只要再翻轉(zhuǎn)一次就可以解密吴趴。下圖中展示了密鑰 3(用二進(jìn)制表 示是 00000011)和字母 N(其字符編碼用二進(jìn)制表示是 01001110)做 XOR 運(yùn)算的結(jié)果,請(qǐng)諸位確認(rèn)通過(guò)翻轉(zhuǎn)和再翻轉(zhuǎn)還原出字母 N 的過(guò) 程:N 的字符編碼先和 3 做 XOR 運(yùn)算侮攀,結(jié)果是字母 M 的字符編碼锣枝。M 的字符編碼再和 3 做 XOR 運(yùn)算,結(jié)果就又回到了 N 的字符編碼兰英。
三撇叁、密鑰越長(zhǎng),解密越困難
在互聯(lián)網(wǎng)等環(huán)境中畦贸,會(huì)有很多不固定的人群相互收發(fā)經(jīng)過(guò)加密處理的數(shù)據(jù)陨闹。一般情況下,會(huì)將所使用的加密方式公開(kāi)薄坏,而只對(duì)密鑰的值保密趋厉。但是令人感到遺憾的是,這個(gè)世界上還是有壞人的胶坠。有些人會(huì)盜取那些并不是發(fā)送給他們的加密數(shù)據(jù)君账,企圖破解后用于不可告人的目的。盡管這些人并不知道密鑰的值涵但,但是他們會(huì)利用計(jì)算機(jī)強(qiáng)大的計(jì)算能力杈绸,用密鑰所有可能的取值去試著破解。例如矮瘟,要想破解用 XOR 運(yùn)算加密得到的密文 MJHHFJ瞳脓,程序只要把 0 到 9 這幾個(gè)值分別作為密鑰都嘗試一遍就能做到(如代碼清單4所示)。
// 代碼清單4 通過(guò) XOR 運(yùn)算破解密文的程序
cipher = InputBox("請(qǐng)輸入密文澈侠。")
plaintext = ""
For key = 0 To 9
plaintext = plaintext & "密鑰" & CStr(key) & ":"
For i = 1 To Len(cipher)
letter = Mid(cipher, i, 1)
plaintext = plaintext & Chr(Asc(letter) Xor key)
Next
plaintext = plaintext & Chr(&HD)
Next
MsgBox plaintext
在互聯(lián)網(wǎng)上經(jīng)過(guò)加密的數(shù)據(jù)也難免被盜劫侧,因此就要先設(shè)法做到即使數(shù)據(jù)被盜了,其內(nèi)容也難以被破解。為此可以把密鑰設(shè)成多位數(shù)而不僅僅是一位數(shù)烧栋。下面写妥,我們就丟棄一位數(shù)的 3,試著以三位數(shù)的 345 為密鑰审姓,通過(guò) XOR 運(yùn)算來(lái)試著進(jìn)行加密(如代碼清單5 所示)珍特。將 明文中的第一個(gè)字母與 3 做 XOR 運(yùn)算、第二個(gè)字母與 4 做 XOR 運(yùn)算魔吐、第三個(gè)字母與 5 做 XOR 運(yùn)算扎筒。從第四個(gè)字母開(kāi)始,還是以三個(gè)字母為一組依次與 3酬姆、4嗜桌、5 做 XOR 運(yùn)算,依此類推辞色。
// 代碼清單5 通過(guò)與三位數(shù)的密鑰進(jìn)行 XOR 運(yùn)算實(shí)現(xiàn)加密和解密
Dim key(2)
key(0) = 3
key(1) = 4
key(2) = 5
text1 = InputBox("請(qǐng)輸入明文或密文骨宠。")
text2 = ""
For i = 1 To Len(text1)
letter = Mid(text1, i, 1)
text2 = text2 & Chr(Asc(letter) Xor key((i - 1) Mod 3))
Next
MsgBox text2
如果僅用一位數(shù)作為密鑰,那么只需要從 0 到 9 嘗試十次就能破 解密文相满。但是如果是用三位數(shù)的密鑰层亿,那么就有從 000 到 999 的 1000 種可能。如果更進(jìn)一步把密鑰的位數(shù)增長(zhǎng)到十位雳灵,結(jié)果會(huì)怎樣呢?那樣的話棕所,破解者就需要嘗試 10 的 10 次方 = 100 億次。就算使用了一秒鐘可以進(jìn)行 100 萬(wàn)次嘗試的計(jì)算機(jī)悯辙,破解密文也還是需要花費(fèi) 100 億 ÷100 萬(wàn)次 / 秒 = 10000 秒 ≈ 2.78 小時(shí)琳省,壞人說(shuō)不定就會(huì)因此放棄破解。 密鑰每增長(zhǎng)一位躲撰,破解所花費(fèi)的時(shí)間就會(huì)翻 10 倍针贬。密鑰再進(jìn)一步增長(zhǎng)到 16 位的話,破解時(shí)間就是 2.78 小時(shí) ×1000000 ≈ 317 年拢蛋,從所需的時(shí)間上來(lái)看桦他,可以說(shuō)破解是不可能的。
四谆棱、適用于互聯(lián)網(wǎng)的公開(kāi)密鑰加密技術(shù)
前面所講解的加密技術(shù)都屬于“對(duì)稱密鑰加密技術(shù)”快压,也稱作 “秘密密鑰加密技術(shù)” (如下圖)。這種加密技術(shù)的特征是在加密和解密的過(guò)程中使用數(shù)值相同的密鑰垃瞧。因此蔫劣,要使用這種技術(shù),就必須事先把密鑰的值作為只有發(fā)送者和接收者才知道的秘密保護(hù)好个从。雖然隨著密鑰位數(shù)的增加脉幢,破解難度也會(huì)增大歪沃,但是 事先仍不得不考慮一個(gè)問(wèn)題:發(fā)送者如何才能把密鑰悄悄地告訴接收者呢?用掛號(hào)信嗎?要是那樣的話,假設(shè)有 100 名接收者嫌松,那么發(fā)送者 就要寄出 100 封掛號(hào)信沪曙,非常麻煩,而且這樣也無(wú)法防止通信雙方以外的其他人知道密鑰萎羔。再說(shuō)寄送密鑰也要花費(fèi)時(shí)間液走。互聯(lián)網(wǎng)的存在應(yīng)該意味著用戶可以實(shí)時(shí)地與世界各地的人們交換信息贾陷。因此對(duì)稱密鑰加密技術(shù)不適合在互聯(lián)網(wǎng)中使用育灸。
但是世界上不乏善于解決問(wèn)題的能人。他們想到只要讓解密時(shí)的 密鑰不同于加密時(shí)的密鑰昵宇,就可以克服對(duì)稱密鑰加密技術(shù)的缺點(diǎn)。(“會(huì)有這樣的技術(shù)嗎?”也許諸位不禁會(huì)發(fā)出這樣的疑問(wèn)儿子,稍后筆者將展示具體的例子)瓦哎。而這種加密技術(shù)就被稱為“公開(kāi)密鑰加密技術(shù)”。
在公開(kāi)密鑰加密技術(shù)中柔逼,用于加密的密鑰可以公開(kāi)給全世界蒋譬,因此稱為“公鑰”,而用于解密的密鑰是只有自己才知道的秘密愉适,因此稱 為“私鑰”犯助。舉例來(lái)說(shuō),假設(shè)筆者的公鑰是 3维咸,私鑰是 5(實(shí)際中會(huì)把位數(shù)更多的兩個(gè)數(shù)作為一對(duì)兒密鑰使用)剂买。筆者會(huì)通過(guò)互聯(lián)網(wǎng)向全世界宣布“我的公鑰是 3 哦”。這之后當(dāng)諸位要向筆者發(fā)送數(shù)據(jù)的時(shí)候癌蓖,就可以用這個(gè)公鑰 3 加密數(shù)據(jù)了瞬哼。這樣就算加密后的密文被人盜取了,只要他還不知道筆者的私鑰就不可能對(duì)其解密租副,從而保證了數(shù)據(jù)的安全性坐慰。而收到了密文的筆者,則可以使用只有筆者自己才知道的私鑰 5 對(duì)其解密用僧。
可用于實(shí)現(xiàn)公開(kāi)密鑰加密技術(shù)的算法有若干種结胀,這里筆者將介紹目前廣泛應(yīng)用于互聯(lián)網(wǎng)中的 RSA 算法。RSA 這個(gè)名字是由三位發(fā)明者 Ronald Rivest责循、Adi Shamir 和 Leonard Adleman 姓氏的首字母拼在一起 組成的糟港。美國(guó)的 RSA 信息安全公司對(duì) RSA 的專利權(quán)一直持有到 2000 年 9 月 20 日。使用 RSA 創(chuàng)建公鑰和私鑰的步驟如下圖所示沼死。無(wú)論是公鑰還是私鑰都包含著兩個(gè)數(shù)值着逐,兩個(gè)數(shù)值組成的數(shù)對(duì)兒才是一個(gè)完整的密鑰。
上圖的步驟可以得出: 323 和 11 是公鑰,323 和 131 是私鑰耸别,的確是兩個(gè)值都不相同的密鑰。在使用這對(duì)兒密鑰進(jìn)行加密和解密時(shí)秀姐,需要對(duì)每個(gè)字符執(zhí)行如下圖所示的運(yùn)算慈迈。這里參與運(yùn)算的對(duì)象是字母 N(字符編碼為 78)。用公鑰對(duì) N 進(jìn)行加密得到 224痒留,用私鑰對(duì) 224 進(jìn)行解密可使其還原為 78。
乍一看會(huì)以為只要了解了 RSA 算法恤磷,就可以通過(guò)公鑰 c = 323、 e = 11 推算出私鑰 c = 323河胎,f = 131 了。但是為了求解私鑰中的 f虎敦,就不得不對(duì) c 進(jìn)行因子分解游岳,分解為兩個(gè)素?cái)?shù) a、b原茅。在本例中 c 的位數(shù)很短吭历,而在實(shí)際應(yīng)用公開(kāi)密鑰加密時(shí),建議將 c 的位數(shù)(用二進(jìn)制數(shù)表示時(shí))擴(kuò)充為 1024 位(相當(dāng)于 128 字節(jié))擂橘。要把這樣的天文數(shù)字分解為兩個(gè)素?cái)?shù)晌区,就算計(jì)算機(jī)的速度再快,也還是要花費(fèi)不可估量的時(shí)間通贞,時(shí)間可能長(zhǎng)到不得不放棄解密的程度朗若。
五昌罩、數(shù)字簽名可以證明數(shù)據(jù)的發(fā)送者是誰(shuí)
接下來(lái)介紹一種公開(kāi)密鑰加密技術(shù)的實(shí)際應(yīng)用 —— 數(shù)字簽名哭懈。在商界有蓋章和簽字的習(xí)慣。印章和簽名都可以證明一個(gè)事實(shí)茎用,那就是某個(gè)人承認(rèn)了文件的內(nèi)容是完整有效的遣总。而在通過(guò)網(wǎng)絡(luò)傳輸?shù)奈募胁锹蓿瑪?shù)字簽名可以發(fā)揮出與印章和簽名同樣的證明效果。通承癯猓可以按照下面的步驟生成數(shù)據(jù)簽名容达。步驟中所提及的“信息摘要”(Message Digest)可以理解為就是一個(gè)數(shù)值,通過(guò)對(duì)構(gòu)成明文的所有字符的編碼進(jìn)行某種運(yùn)算就能得出該數(shù)值垂券。
【文本數(shù)據(jù)的發(fā)送者】
(1)選取一段明文 例:NIKKEI
(2)計(jì)算出明文內(nèi)容的信息摘要 例:(78+73+75+75+69+73)÷100 的余數(shù) = 43
(3)用私鑰對(duì)計(jì)算出的信息摘要進(jìn)行加密 例:43 → 66(字母 B 的編碼)
(4)把步驟(3)得出的值附加到明文后面再發(fā)送給接收者 例:NIKKEIB
【文本數(shù)據(jù)的接收者】
(1)用發(fā)送者的公鑰對(duì)信息摘要進(jìn)行解密 例 :B = 6 6 → 4 3
(2)計(jì)算出明文部分的信息摘要 例:(78+73+75+75+69+73)÷100 的余數(shù) = 43
(3)比較在步驟(1)和(2)中求得的值花盐,二者相同則證明接收的 信息有效
例:因?yàn)閮蛇叾际?43,所以信息有效
請(qǐng)諸位注意菇爪,這里是使用私鑰進(jìn)行加密算芯、使用公鑰進(jìn)行解密,這與之前的用法剛好相反(如下圖所示)凳宙。而且這里所使用的是信息發(fā)送者(圖中的 A 小姐)的密鑰對(duì)兒熙揍,而之前所使用的則是信息接收者(B 先生)的密鑰對(duì)兒。
本例中信息摘要的算法是把明文中所有字母的編碼加起來(lái)氏涩,然后取總和的最后兩位诈嘿。而在實(shí)際中計(jì)算數(shù)字簽名時(shí),使用的是通過(guò)更加復(fù)雜的公式計(jì)算得出的削葱、被稱作 MD5(Message Digest5)的信息摘要。由于 MD5 經(jīng)過(guò)了精心的設(shè)計(jì)淳梦,所以使得兩段明文即使只有略微的差異析砸,計(jì)算后也能得出不同的信息摘要。
也許諸位會(huì)認(rèn)為把文件發(fā)送者的名字爆袍,比如“張三”這個(gè)字符串用私鑰加密首繁,然后讓對(duì)方用公鑰解密也能代替印章或簽字。但是如果這樣做就不算是數(shù)字簽名了陨囊,因?yàn)橛≌禄蚝炞钟袃蓪蛹s束弦疮。其一是 發(fā)送者承認(rèn)文件的內(nèi)容是完整有效的;其二是文件確實(shí)是由發(fā)送者本人發(fā)送的。發(fā)送者用構(gòu)成文件的所有字符的編碼生成了信息摘要蜘醋,就證明發(fā)送者從頭到尾檢查了文件并承認(rèn)其內(nèi)容完整有效胁塞。如果接收者重新算出的信息摘要和經(jīng)過(guò)發(fā)送者加密的信息摘要匹配,就證明文件在傳輸過(guò)程中沒(méi)有被篡改压语,并且的確是發(fā)送者本人發(fā)送的啸罢。正因?yàn)閿?shù)據(jù)是用發(fā)送者的私鑰加密的,接收者才能用發(fā)送者的公鑰進(jìn)行解密胎食。
總結(jié)
其實(shí)扰才,絕對(duì)無(wú)法破解的加密技術(shù)也是存在的。首先密鑰的位數(shù)要與文件數(shù)據(jù)中的字符個(gè)數(shù)相同厕怜,其次每次發(fā)送文件時(shí)都需要先更換密鑰衩匣,最后為了防止密鑰被盜蕾总,發(fā)送者還要親手把密鑰交給接收者。諸位明白為什么說(shuō)這樣做就絕對(duì)無(wú)法破解了嗎?原因在于這樣做等同于發(fā)送完全隨機(jī)并且沒(méi)有任何意義的數(shù)據(jù)琅捏∩伲可是這種加密技術(shù)是不切實(shí)際的。合理的密鑰應(yīng)該滿足如下條件:長(zhǎng)短適中午绳、可以反復(fù)使用置侍、可以通過(guò)某種通信手段交給接收者,并且通信雙方以外的其他人難以用它來(lái)解密拦焚。
本文摘自《計(jì)算機(jī)是怎樣跑起來(lái)的》第10章