安全與密碼學

去年的安全和隱私講座重點討論了如何以電腦 使用者 的身份提高安全性。 今年,我們將重點放在和本課程以前介紹的工具有關的,在安全性和密碼學概念方面的知識。 例如,在 Git 中使用 hash 函式或在 SSH 中使用密鑰派生函式和對稱/非對稱密碼系統。

此課程不可作為計算機系統安全(6.858) 或密碼學 (6.857 與 6.875)的替代。 不要在沒有接受良好教學的情況下從事安全相關工作。 除非你是專家,不要自創加密方法, 這在系統安全方面是同樣的。

這節課對基本密碼學概念有著非常簡略(但我們認為很有用)的介紹。 若你想 設計 安全系統或加密協議,僅僅學習本課是不夠的。 但我們希望此課可以讓你大致瞭解已經廣泛使用的程式與協議。

熵(Entropy)

是對隨機性的一種度量。 在測試密碼強度等環境下,熵有著重要作用。

XKCD 936: 密碼安全性

如同上面 XKCD 漫畫 描繪的,”correcthorsebatterystaple” 比 “Tr0ub4dor&3” 更為安全,我們該如何判斷安全性?

熵以 位元 度量,對於一個均勻分佈的隨機變數,熵等於 log_2(可能性總數)。 擲一次硬幣的熵爲 1 位元,擲一次(六面)骰子的熵約為 2.58 位元。

我們通常認為攻擊者瞭解密碼的 模型, 但是不知道密碼是如何隨機選出的(例如 擲骰子)。

多少位元的熵是足夠安全的?這通常取決於威脅模型。上面的 XKCD 漫畫指出,對於線上密碼攻擊,大約 40 位元的熵即可。對於線下攻擊,需要 80 位元或更強的密碼。

密碼雜湊函式

密碼雜湊函式 會將任意大小的資料對映至指定大小。一個粗略的雜湊函式規範大概是這樣的:

hash(value: array<byte>) -> vector<byte, N>  (N 是指定數目)

Git 使用的 SHA1 即是雜湊函式。它會將任意大小的輸入對映至 160 位元(即 40 個十六進位字元)中。我們可以使用 sha1sum 指令執行它:

$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'Hello' | sha1sum 
f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0

更通用的解釋是,雜湊函式可以被認為是不可逆且隨機(但是具有確定性)的函式(這是雜湊函式的理想模型)。 一個雜湊函式將會有如下性質:

注意:雖然對於一般用途還有效,SHA-1 已經不再被認為是強密碼雜湊函式了,你也許會對密碼雜湊函式的生命週期感興趣。對於特定需求推薦指定雜湊函式不在此課程的涵蓋範圍內,如果你有這些需求,需要學習安全學或密碼學。

運用

密鑰衍生函式

密鑰衍生函式 (KDFs) 作為密碼雜湊函式的相關概念,被運用於多個方面,包括生成可以在其他密碼演算法中使用的固定長度密鑰等。 為了對抗線下的窮舉攻擊,KDFs 通常故意被設計成緩慢執行。

運用

對稱加密

當你需要加密時,最先想到的應該是隱藏明文資訊,對稱加密使用以下幾種方法來實現此功能:

keygen() -> key  (這是一個隨機方法)

encrypt(plaintext: array<byte>, key) -> array<byte>  (獲得密文)
decrypt(ciphertext: array<byte>, key) -> array<byte>  (獲得明文)

透過加密方法獲得的輸出(密文)很難在不知道 key 的情況下解得其輸入(明文)。 解密方法具有明顯的正確性,即 decrypt(encrypt(m, k), k) = m 一定成立。

一個現在被廣泛使用的對稱加密例子是 AES

運用

非對稱加密

“非對稱”是指存在兩個持有不同職責的密鑰。 顧名思義,私鑰旨在保持私密,而公鑰可以公開共享,且不會影響安全性(與在對稱加密系統中共享密鑰不同)。 非對稱密碼系統提供以下功能,以進行加密/解密和簽章/檢驗:

keygen() -> (public key, private key)  (這是一個隨機方法)

encrypt(plaintext: array<byte>, public key) -> array<byte>  (獲得密文)
decrypt(ciphertext: array<byte>, private key) -> array<byte>  (獲得明文)

sign(message: array<byte>, private key) -> array<byte>  (獲得簽章)
verify(message: array<byte>, signature: array<byte>, public key) -> bool  (檢驗此簽章為有效的)

加密/解密功能類似於對稱加密系統的性質。 可以使用 公共 密鑰對訊息進行加密。 給定輸出(密文),沒有 私有 密鑰就很難確定輸入(明文)。 解密函式具有明顯的正確性,即 decrypt(encrypt(m,public key),private key)= m 一定成立。

對稱和非對稱加密與生活中的鎖類似。 對稱加密系統就像門鎖:任何擁有鑰匙的人都可以鎖定和解鎖。 非對稱加密就像帶鑰匙的掛鎖。 您可以將鎖本身(公鑰)提供給某人,他們可以在盒子內放入訊息,然後鎖上它。 只有你可以開啟該鎖,因為你持有鎖的鑰匙(私鑰)。

簽章/檢驗功能與書面簽名類似,即難以偽造。 在不知道 私鑰 的情況下,很難得出一個可以通過 verify(message, signature, public key) 檢驗的簽章。 對於使用私鑰簽章的資料,verify(message, sign(message, private key), public key) = true 這種檢驗方式在提供正確資料時一定成立。

運用

密鑰分配

非對稱加密很棒,但是在分配公鑰/將公鑰對應至現實中的個體時面臨著很大的挑戰。有許多解決此問題的方法。 Signal 提供了簡單地解決方案:使用者第一次使用時信任其身份,並支援線下的公鑰交換(你需要親自驗證朋友是否安全)。 PGP有另一種解決方案,即信任網。 Keybase 主要使用社交證明,與一些其他精妙方法。每一種模型都有其優勢,我們(講師)喜愛 Keybase 的模型。

案例

密碼管理器

任何人都應該試一試密碼管理器(例如 KeePassXC)。 密碼管理器會幫助你對每個網站生成隨機且高熵的密碼。它會將你的所有密碼儲存至一處,且透過 KDF 利用你的主密碼生成的密鑰進行對稱加密。

密碼管理器會讓你避免復用密碼(所以當網站資料洩漏時你受到影響較少),且使用高熵密碼(使你的密碼更難被竊取)。 密碼管理器只需要你記住一個高熵的主密碼。

雙重驗證

雙重驗證 (2FA) 要求你同時使用密碼(“你知道的資料”)和一個 2FA 驗證器(比如YubiKey,“你擁有的東西”)來對抗密碼洩漏與釣魚攻擊

全磁碟加密

將筆電全磁碟加密是在其被盜時保護資料的簡單辦法。 Linux 系統下使用 cryptsetup + LUKS, Windows 下使用 BitLocker, macOS 下使用 FileVault。 它們會通過對稱加密來保護整個硬碟。

私密通訊

使用 SignalKeybase。 非對稱密鑰加密會提升端到端安全性。獲取聯絡人的公鑰是此處的關鍵步驟。 如果想要良好的安全性,需要線下(通過 Signal 或 Keybase )對公鑰進行身份驗證,或者信任社交證明(透過 Keybase)。

SSH

之前的講座涉及了 SSH 與 SSH 密鑰的使用,讓我們從密碼學方面看看他們。

當你執行 ssh-keygen時候,它會給出一組非對稱密鑰,即public_key, private_key。 這使用作業系統(從硬體事件擷取的)熵隨機生成。公鑰會被明文儲存(它是公開的,所以保密性不重要),不過私鑰必須加密。 ssh-keygen 程式會要求使用者輸入一個密碼,並透過密鑰生成函式來使用該密碼生成一個密鑰,ssh-keygen 會來利用此密鑰透過對稱加密方式加密私鑰。

在現實場景中,當伺服器已知使用者的公鑰(儲存在 .ssh/authorized_keys), 與其連結的客戶端可以透過非對稱簽章證明其身份。這個過程由質詢-應答機制完成。 通常來說,伺服器選擇一個隨機數字,並傳送至客戶端。客戶端對此數字簽章後將其返回伺服器。伺服器隨後使用公鑰驗證此返回資訊是否由對應的私鑰簽章。這個過程可以證明伺服器中 .ssh/authorized_keys 裏儲存的公鑰與該客戶端的私鑰是對應的,伺服器便可放行客戶端登入。

資源

課後練習

    1. 假定一個密碼是由 5 個小寫的常規詞拼接組成,每個詞都是從含有 100,000 詞的字典內隨機選取,且每個詞選中概率相同, 例如 correcthorsebatterystaple。這個密碼的熵是多少位元?
    2. 假定一個密碼由 8 個隨機字母數字組成(包括大小寫),例如 rg8Ql34g,它的熵是多少位元?
    3. 以上兩個密碼誰更強?
    4. 假定一個入侵者可以每秒嘗試 10,000 個密碼,平均來說,他需要多久來攻破上面兩個密碼?
  1. 密碼雜湊函式Debian 映象站下載一個 Debian 映象 (比如這個阿根廷映象站)。 檢查 hash 值(例如使用 sha256sum 指令),與域名為 debian.org 的 Debian 官方站點提供的值(例如這個檔案)進行對比。
  2. 對稱加密 透過 OpenSSL 使用 AES 加密一個檔案: openssl aes-256-cbc -salt -in {input filename} -out {output filename}。 使用 cathexdump 檢視其內容。再使用 openssl aes-256-cbc -d -in {input filename} -out {output filename} 來解密,並且使用 cmp 驗證解密內容與元檔案相同。
  3. 非對稱加密
    1. 在你擁有的電腦上(不要使用 Athena,因為 Kerberos 與 SSH 密鑰的互動十分詭異)設定一個 SSH 密鑰。使用更安全的 ED25519 密鑰來替代 RSA 密鑰會更好。確保你使用了密碼來加密私鑰。
    2. 設定 GPG
    3. 給 Anish 傳送一封加密電郵 ( Anish 的公鑰)。
    4. 使用 git commit -S 簽署一個提交,或使用 git tag -s 建立一個帶有簽章的 Git tag。 使用git show --show-signature 來檢查提交的簽章,或使用 git tag -v 檢查 tag。

Edit this page.

Licensed under CC BY-NC-SA.