iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 6
0
Security

安全地寫 Java 的「基本功」系列 第 6

安全地寫 Java 的 「基本功」- Day 5

加解密簡論(續)

前文與週末專案中,討論了一種傳統式的加密機制,也就是加密解密都使用同一把金鑰的機制。這個機制,專業術語稱為「對稱式加密」。然而,在有了電腦的 20 世紀裡,人們對數學的認知擴增,對質數與其應用的領域的認識更加深入。於是,在這個世紀,數學家找到了一件很驚人的發現:原來透過演算法,加密與解密可以用不同的金鑰!

加密與解密不同金鑰

試想一下,如果你去上班,需要帶兩張門卡,一張進門,一張出門。那你一定會下班在家痛罵老闆一頓,特別是忘了帶出門的那張。但如果有某些客人,從警衛、門禁處可以拿到進門的卡片,進了門,卻必須由公司裡的人控管才能出門。或許這樣能夠增加安全性,但也有可能從此再也沒有客戶敢拜訪這家公司。

但用在資訊類應用上,這是很有用的機制。一把加密用的金鑰,可以給任何人;另一把解密用的金鑰,只有自己存留。於是乎,這樣的機制,幫助了資訊產業建立起龐大的商機,因為這樣的機制,可以使用在涉及金融、法律、軍事等敏感領域中。

然而,這過程並不像安裝 Fedora 或 Ubuntu 那麼容易,它反而像安裝 Arch 或 Gentoo 那樣,仍然充滿細節裡的魔鬼。

非對稱式加密

我們還是給它一個名字,不是我給的,是資訊業界給的,叫做非對稱式加密。意即加密與解密的金鑰,不是相同的內容,雙方所擁有的資訊並非對稱。

速度的問題

面對這世上,沒有完美的方法,可以解決在時空的限制中的事物。有一好就沒兩好,這加解密機制也是。典型的非對稱加解密演算法,叫做 RSA,這演算法看似完美,但最大的問題,在於時間過久、效率不高。演算法的實作與細節,我就不多談,因為那實在不是我的專業。但若你要用 RSA,配上 2048 byte 長度的金鑰,去加密一首貝多芬第九號的音訊檔給你的好朋友。

相信我,你花在上面的時間,不如你直接買一張 CD 送給他,這樣還比較便宜。

金鑰的管理

只要牽涉到加解密,不要懷疑,最大的問題一定是金鑰管理的問題,其次才是能不能被破解的問題。George Hotz 破解 PS3 時,並不是用暴力演算法去算出 SONY DRM 的內容,而是去挖出深藏在 PS3 裡的 Master key。

在先前提到,對稱式加密金鑰的問題,然而,它真正的問題在於,若有 3 個人,要彼此傳訊,只要 3 把金鑰。但若有 100 個人要彼此傳訊呢?試想,平面上 100 個點,彼此相連,共會有幾條線?答案是 100 * (100 - 1) / 2。換句話說,如果你們公司有 1000 個人,內部信件必須用 AES 256 加密,那麼每個人的電腦裡頭,要儲存 1000 * (1000 - 1) / 2 把金鑰才夠。這種 n^2 複雜度的機制,增加了對稱式的難度。

然而,非對稱式的出現,解決了上一個問題,卻衍生出第二個問題。先前說到,我們可以把一把金鑰給任何人,這把這麼隨便的金鑰,就叫它公鑰吧;換言之,另一把只能自己保存的,就是私鑰了。使用了非對稱的機制後,減低了金鑰管理的複雜度。但關鍵的私鑰只有一把,那麼,當它不小心外洩時,就不是一件好笑的事了。

直接地說,你的 Server 上,用來進行 SSL 認證的憑證,若關鍵的私鑰被盜走了,攻擊者就能冒用你的服務,來騙取你們的客戶的連線。當然,現在憑證的內容沒有那麼簡單,但私鑰遺失,仍然是一件挺嚴重的事情。

金鑰的認證

其實若單純討論非對稱加解密,這點其實沒有什麼困難的。如果你的朋友,直接當著你的面,說「朋友,這是我的公鑰,記得發信給我時要加個密」,那就算了。但既然能面對面,有什麼事不能當面談,還要寫一封密書呢?然而,網路世界這麼危險,充滿著各種誘惑與欺騙,你能相信你朋友給你的那把公鑰,透過 email 寄來後,還是那把真正的公鑰嗎?

認證的目的,不是為了認證金鑰,金鑰只是一串數字。認證是為了確認金鑰的擁有者,他的資訊內容是不是正確,好連同可以信任這把金鑰。因此,為了進行認證,前人想出了一套機制,這個呢,留待後續文章來說明。

雞尾酒療法

既然非對稱式加密是有一好沒兩好,用起來很慢,卻很方便。我們乾脆結合對稱式加密的優點,就是速度比較快,跟非對稱式的優點,就是方便管理如何。

於是,你可以用同一個密碼,加密檔案。加完密之後,再用你的朋友的公鑰,加密那個密碼。這樣,我們取了對稱式的優點,卻又不必產生一大堆密碼,而只要進行兩次加密,就能確保資料的安全性。

本日實作

既然我們談到非對稱式的機制,我們今天先用 Java 的 keytool 來產生一組自己的金鑰試試。

產生金鑰 by keytool

指令:

keytool -genkey -alias $ALIAS -keyalg RSA -keystore $KEYSTORE.jks -keysize 2048

說明:

  1. 執行時,請給金鑰庫一個安全的密碼
  2. 接下來會依序輸入一些你的資訊,距離由近到遠,範圍由小到大
  3. 輸入金鑰密碼,若不輸入則與金鑰庫相同

執行完後,會得到一個 $KEYSTORE.jks 的金鑰。當然,大括號裡,請代換成你要用的字串。

產生金鑰 by openssl

ApplyKeyTool 另有 openssl 產生金鑰的指令,各位可以參考。

有用的參考網頁


上一篇
安全地寫 Java 的 「基本功」- Day 4
下一篇
安全地寫 Java 的 「基本功」- Day 6
系列文
安全地寫 Java 的「基本功」14

尚未有邦友留言

立即登入留言