Python 提供多種加密工具,secrets
模組尤為重要,它能生成安全隨機數,適用於密碼學應用,例如產生金鑰、密碼短語等。相較之下,random
模組則不適用於安全場景。HMAC 函式根據雜湊演算法,結合金鑰確保訊息驗證碼的完整性,防止資料竄改。Fernet 則提供對稱加密機制,簡化加密解密流程,並內建金鑰輪替機制,提升安全性。
在資訊安全領域,保護敏感資料至關重要。本文介紹 Python 中常用的加密技術,包含 secrets
、hmac
和 Fernet
等模組,並探討如何應用這些技術來保護資料安全。secrets
模組提供安全隨機數生成器,適用於生成密碼、金鑰等敏感資料。hmac
模組則提供根據雜湊的訊息驗證碼(HMAC)功能,可用於驗證資料完整性,防止資料被篡改。Fernet
則是一種對稱加密演算法,可以對資料進行加密和解密,保護資料的機密性。
使用 secrets
模組
secrets
模組是 Python 中的一個安全模組,提供了生成安全隨機數的功能。它使用作業系統的安全隨機數生成器來生成隨機數。
import secrets
# 生成 16 個隨機位元組
random_bytes = secrets.token_bytes(16)
print(random_bytes)
# 生成 16 個隨機位元組的十六進位制文字
random_hex = secrets.token_hex(16)
print(random_hex)
# 生成 16 個隨機位元組的 URL 安全文字
random_urlsafe = secrets.token_urlsafe(16)
print(random_urlsafe)
使用 random
模組
random
模組是 Python 中的一個基本模組,提供了生成隨機數的功能。然而,它不適合用於安全相關的應用,因為它使用了一個預設的隨機數生成器。
import random
# 生成 16 個隨機位元組
random_bytes = random.getrandbits(128).to_bytes(16, 'big')
print(random_bytes)
生成密碼短語
密碼短語是一個由多個隨機單片語成的序列。可以使用 secrets
模組來生成密碼短語。
import secrets
# 載入單詞列表
with open('/usr/share/dict/words', 'r') as f:
words = f.read().splitlines()
# 生成 4 個隨機單詞
passphrase = ' '.join(secrets.choice(words) for _ in range(4))
print(passphrase)
安全注意事項
在進行安全相關的開發時,必須注意以下幾點:
- 不要使用
random
模組來生成安全隨機數。 - 使用
secrets
模組來生成安全隨機數。 - 使用安全的密碼短語生成方法。
- 不要使用預設的隨機數生成器。
圖表翻譯:
flowchart TD A[開始] --> B[生成安全隨機數] B --> C[使用 secrets 模組] C --> D[生成密碼短語] D --> E[使用安全的密碼短語生成方法] E --> F[完成]
內容解密:
上述程式碼展示瞭如何使用 secrets
模組來生成安全隨機數和密碼短語。同時,也強調了在進行安全相關的開發時,必須注意安全問題。
生成安全密碼和密語的重要性
在現代電腦系統中,安全密碼和密語是保護資料和系統的重要手段。密碼可以是隨機生成的數字和字母的組合,也可以是易於記憶的密語。選擇合適的密碼或密語對於保護系統和資料的安全至關重要。
隨機密碼的生成
隨機密碼可以使用電腦的隨機數生成器生成。Python 的 secrets
模組提供了一個安全的方式來生成隨機密碼。以下是一個生成四個隨機單詞的密語的例子:
import secrets
from pathlib import Path
words = Path('/usr/share/dict/words').read_text().splitlines()
passphrase = ' '.join(secrets.choice(words) for i in range(4))
print(passphrase)
這個例子使用 secrets.choice
函式從一個單詞列表中選擇四個隨機單詞,並將它們組合成一個密語。
密語的優勢
密語比隨機密碼更容易記憶,因為它們是由單片語成的。密語的長度和複雜度可以使其更加安全。例如,密語 “whereat isostatic custom insupportableness” 就是一個長度為 42 個位元組的密語,其破解時間約為 163,274,072,817,384 個世紀。
密碼和密語的選擇
密碼和密語的選擇取決於具體的應用情景。隨機密碼適合於短期使用的密碼,例如多因素驗證(MFA)令牌或臨時密碼重置值。密語則適合於長期使用的密碼,例如登入憑證或安全 Shell(SSH)會話。
安全密碼和密語的重要性
安全密碼和密語是保護系統和資料的重要手段。選擇合適的密碼或密語可以防止未經授權的存取和資料洩露。同時,密碼和密語的安全儲存也是非常重要的,應該使用安全的金鑰管理服務來儲存和管理密碼和密語。
圖表翻譯:
graph LR A[密碼生成] --> B[隨機密碼] A --> C[密語生成] B --> D[短期使用] C --> E[長期使用] D --> F[多因素驗證] E --> G[登入憑證]
這個圖表展示了密碼和密語的生成和使用情景。隨機密碼適合於短期使用的密碼,例如多因素驗證令牌或臨時密碼重置值。密語則適合於長期使用的密碼,例如登入憑證或安全 Shell 會話。
金鑰雜湊(Keyed Hashing)
金鑰雜湊是一種特殊的雜湊函式,它接受一個額外的金鑰作為輸入。這個金鑰與訊息一起被輸入到雜湊函式中,產生出一個雜湊值。金鑰對於雜湊值的生成至關重要,不同的金鑰會產生不同的雜湊值,即使訊息相同。
金鑰雜湊的特性
金鑰雜湊函式的輸出對金鑰值非常敏感。當使用不同的金鑰時,對相同的訊息進行雜湊會產生不同的雜湊值。相反,當使用相同的金鑰時,對相同的訊息進行雜湊會產生相同的雜湊值。
實作金鑰雜湊
以下是一個使用BLAKE2b雜湊函式的金鑰雜湊示例。BLAKE2b是一種接受可選金鑰的雜湊函式。
from hashlib import blake2b
# 定義訊息和金鑰
m = b'相同的訊息'
x = b'金鑰 x'
y = b'金鑰 y'
# 使用相同的金鑰進行雜湊
print(blake2b(m, key=x).digest() == blake2b(m, key=x).digest()) # True
# 使用不同的金鑰進行雜湊
print(blake2b(m, key=x).digest() == blake2b(m, key=y).digest()) # False
金鑰雜湊在實際應用的例子
在檔案管理系統中,Alice可以使用金鑰雜湊來保護檔案免受Mallory的篡改。透過儲存檔案的雜湊值和檔案本身,Alice可以檢查檔案是否被篡改過。
以下是Alice的程式碼示例:
import hashlib
from pathlib import Path
def store(path, data, key):
data_path = Path(path)
hash_path = data_path.with_suffix('.hash')
hash_value = hashlib.blake2b(data, key=key).hexdigest()
with data_path.open(mode='x'), hash_path.open(mode='x'):
data_path.write_bytes(data)
hash_path.write_text(hash_value)
def is_modified(path, key):
data_path = Path(path)
hash_path = data_path.with_suffix('.hash')
data = data_path.read_bytes()
original_hash_value = hash_path.read_text()
hash_value = hashlib.blake2b(data, key=key).hexdigest()
return hash_value != original_hash_value
這個程式碼示例展示瞭如何使用金鑰雜湊來保護檔案免受篡改。透過儲存檔案的雜湊值和檔案本身,Alice可以檢查檔案是否被篡改過。
HMAC 函式:根據 Hash 的訊息驗證碼
HMAC(Hash-based Message Authentication Code)函式是一種使用普通的 Hash 函式來模擬金鑰 Hash 函式的方法。它接受三個輸入:訊息、金鑰和一個普通的密碼學 Hash 函式。HMAC 函式的輸出是一個根據 Hash 的訊息驗證碼(MAC),可以視為是一種特殊的 Hash 值。
HMAC 函式的工作原理
HMAC 函式的工作原理是先將訊息和金鑰結合,然後使用指定的 Hash 函式計算出一個 Hash 值。這個 Hash 值就是 HMAC 值。HMAC 函式可以使用任何普通的 Hash 函式,例如 SHA-256。
Python 中的 HMAC 函式
Python 的 hmac
模組提供了 HMAC 函式的實作。可以使用 hmac.new()
函式初始化一個 HMAC 函式,指定訊息、金鑰和底層 Hash 函式。例如:
import hmac
import hashlib
hmac_sha256 = hmac.new(b'key', msg=b'message', digestmod=hashlib.sha256)
HMAC 函式的方法
HMAC 函式例項提供了幾個方法,包括:
digest()
: 傳回 HMAC 值的二進製表示。hexdigest()
: 傳回 HMAC 值的十六進製表示。digest_size
: 傳回 HMAC 值的大小(以位元組為單位)。
例如:
print(hmac_sha256.digest()) # b"n\x9e\xf2\x9bu\xff\xfc[z\xba\xe5'\xd5\x8f\xda\xdb/\xe4.r\x19\x01\x19v\x91sC\x06_X\xedJ"
print(hmac_sha256.hexdigest()) # '6e9ef29b75fffc5b7abae527d58fdadb2fe42e7219011976917343065f58ed4a'
print(hmac_sha256.digest_size) # 32
HMAC 函式在資料驗證中的應用
HMAC(Keyed-Hashing for Message Authentication)是一種常用的資料驗證技術,廣泛應用於各種安全通訊協定中。其基本原理是利用分享的金鑰和雜湊函式對資料進行驗證,以確保資料的完整性和真實性。
HMAC 函式的特點
- 根據雜湊函式:HMAC 函式是根據雜湊函式(如 SHA-256)實作的,利用雜湊函式的特點對資料進行驗證。
- 分享金鑰:HMAC 函式需要分享金鑰,該金鑰由通訊雙方分享,以確保只有授權方能夠驗證資料。
- 資料驗證:HMAC 函式對資料進行驗證,確保資料在傳輸過程中未被篡改或竄改。
HMAC 函式的工作流程
- 分享金鑰:通訊雙方分享一個金鑰。
- 資料雜湊:傳送方利用 HMAC 函式和分享金鑰對資料進行雜湊,得到雜湊值。
- 資料傳輸:傳送方將資料和雜湊值一起傳輸給接收方。
- 資料驗證:接收方利用 HMAC 函式和分享金鑰對收到的資料進行雜湊,得到新的雜湊值。
- 雜湊值比較:接收方比較新的雜湊值和收到的雜湊值,如果兩者相同,則資料驗證成功,否則驗證失敗。
Python 實作 HMAC 函式
以下是 Python 中利用 hmac
和 hashlib
模組實作 HMAC 函式的範例:
import hmac
import hashlib
import json
# 分享金鑰
shared_key = b'shared_key'
# 資料
message = b'from Bob to Alice'
# 建立 HMAC 物件
hmac_sha256 = hmac.new(shared_key, digestmod=hashlib.sha256)
# 更新 HMAC 物件
hmac_sha256.update(message)
# 取得雜湊值
hash_value = hmac_sha256.hexdigest()
# 封裝資料和雜湊值
authenticated_msg = {
'message': list(message),
'hash_value': hash_value
}
# 將封裝資料轉換為 JSON 格式
outbound_msg_to_alice = json.dumps(authenticated_msg)
print(outbound_msg_to_alice)
資料驗證
接收方可以利用以下 Python 程式碼進行資料驗證:
import hmac
import hashlib
import json
# 分享金鑰
shared_key = b'shared_key'
# 收到的資料
inbound_msg_from_bob = json.loads(outbound_msg_to_alice)
# 收到的雜湊值
received_hash_value = inbound_msg_from_bob['hash_value']
# 收到的資料
received_message = bytes(inbound_msg_from_bob['message'])
# 建立 HMAC 物件
hmac_sha256 = hmac.new(shared_key, digestmod=hashlib.sha256)
# 更新 HMAC 物件
hmac_sha256.update(received_message)
# 取得新的雜湊值
new_hash_value = hmac_sha256.hexdigest()
# 比較雜湊值
if new_hash_value == received_hash_value:
print("資料驗證成功")
else:
print("資料驗證失敗")
安全性考量:防禦時間攻擊
時間攻擊是一種利用系統的時間差異來推測敏感資訊的攻擊方式。在上述範例中,Mallory 利用了 Alice 對兩個雜湊值的比較時間差異來推測雜湊值的第一個字元。這種攻擊方式是因為 ==
運算子在比較兩個字串時,會在找到第一個不同字元時立即傳回 False
,從而導致比較時間的差異。
時間攻擊的原理
時間攻擊的原理是根據系統的時間差異來推測敏感資訊。攻擊者可以透過測量系統的回應時間來推測敏感資訊。例如,在上述範例中,Mallory 可以透過測量 Alice 對不同雜湊值的比較時間來推測雜湊值的第一個字元。
防禦時間攻擊的方法
防禦時間攻擊的方法是使用長度恆定的時間比較函式。這種函式會始終比較所有字元,而不是在找到第一個不同字元時立即傳回。這樣可以防止攻擊者透過測量回應時間來推測敏感資訊。
Python 中的長度恆定時間比較函式
在 Python 中,hmac
模組提供了一個名為 compare_digest
的長度恆定時間比較函式。這個函式會始終比較所有字元,而不是在找到第一個不同字元時立即傳回。這樣可以防止時間攻擊。
from hmac import compare_digest
# 安全的雜湊值比較
hash_value1 = "1234567890abcdef"
hash_value2 = "1234567890abcdef"
if compare_digest(hash_value1, hash_value2):
print("雜湊值相同")
else:
print("雜湊值不同")
加密技術入門
什麼是加密?
加密是一種將明文(plaintext)轉換為密鑰(ciphertext)的過程,目的是保護資訊不被未經授權的第三方存取。明文是可以被人們直接理解的資訊,例如文字、圖片或程式碼。加密的結果是產生一串看似亂碼的密鑰,需要有相應的解密金鑰才能還原為原來的明文。
加密和解密
加密和解密是兩個相反的過程。加密是將明文轉換為密鑰,而解密則是將密鑰轉換回明文。這兩個過程都需要使用一套加密演算法(cipher),而這套演算法需要一個金鑰(key)來進行加密和解密。
金鑰的重要性
金鑰是加密和解密過程中最重要的部分。金鑰需要被保密,因為任何人只要擁有金鑰,就可以解密密鑰得到原來的明文。因此,選擇一個安全的金鑰是非常重要的。在實踐中,通常使用一個隨機生成的金鑰來進行加密和解密。
對稱式加密
對稱式加密(symmetric encryption)是一種使用相同金鑰進行加密和解密的加密方式。這種加密方式的優點是速度快、效率高,但其缺點是金鑰需要被保密,如果金鑰被洩露,則加密的資訊就不再安全。
非對稱式加密
非對稱式加密(asymmetric encryption)則使用一對金鑰:公鑰(public key)和私鑰(private key)。公鑰用於加密,私鑰用於解密。這種加密方式的優點是可以在不交換金鑰的情況下進行加密和解密,但其缺點是速度較慢。
加密演算法的選擇
選擇一個合適的加密演算法是非常重要的。不同的加密演算法有不同的安全性和效率。例如,AES(Advanced Encryption Standard)是一種廣泛使用的對稱式加密演算法,具有高安全性和效率。
金鑰輪換
金鑰輪換(key rotation)是指定期更換加密金鑰的過程。這是為了提高加密的安全性,因為如果金鑰被洩露或被攻擊者猜測出來,則加密的資訊就不再安全。金鑰輪換可以幫助減少這種風險。
加密技術與保密性
在資訊安全中,保密性是指確保只有授權的實體才能存取加密資訊。圖 4.1 顯示了明文(plaintext)和密鑰(ciphertext)的概念,明文是加密的輸入和解密的輸出,而密鑰是加密的輸出和解密的輸入。
保密性的重要性
保密性是安全系統設計中的基本組成部分,與資料完整性和資料身份驗證一同構成了安全的基礎。保密性簡單來說就是保證私隱,我們可以將其分為兩種形式:個體私隱和群體私隱。
個體私隱
個體私隱是指個體對自己的敏感資料進行保護,例如,Alice 想要寫入和讀取敏感資料,但不想讓任何人知道,她可以透過加密技術來保證個體私隱。
群體私隱
群體私隱是指多個個體之間分享敏感資料的保護,例如,Alice 和 Bob 想要交換敏感資料,他們可以透過加密技術來保證群體私隱。
安裝加密套件
在本章中,我們將學習如何實作靜態加密(at rest)和傳輸中加密(in transit)。首先,我們需要安裝一個安全的套件管理器,例如 Pipenv。
套件管理
Pipenv 是一個具有多種安全功能的套件管理器,我們可以使用它來管理專案依賴關係。要安裝 Pipenv,可以使用以下命令:
$ sudo apt install pipenv # 在 Debian Buster+ 上
$ sudo dnf install pipenv # 在 Fedora 上
$ pkg install py36-pipenv # 在 FreeBSD 上
$ pip install --user pipenv # 在其他作業系統上
接下來,執行以下命令建立 Pipfile
和 Pipfile.lock
檔案:
$ pipenv install
這些檔案用於管理專案依賴關係。然後,啟用虛擬環境:
$ pipenv shell
安裝加密函式庫
在虛擬環境中,我們可以安裝 cryptography
套件,這是 Python 中唯一需要的加密函式庫。
$ pipenv install cryptography
在接下來的章節中,我們將學習如何使用這個套件實作加密和解密。同時,我們也會探討如何使用 Mermaid 圖表來視覺化加密過程。
flowchart TD A[明文] --> B[加密] B --> C[密鑰] C --> D[解密] D --> E[明文]
圖表翻譯:
上述 Mermaid 圖表展示了加密和解密的過程。首先,明文作為輸入被加密成密鑰,然後密鑰被解密回明文。這個過程保證了只有授權的實體才能存取敏感資訊。
密碼學套件
Python 與其他程式語言不同,沒有內建的加密 API。為了填補這個空白,開源框架應運而生。Python 中最受歡迎的加密套件是 cryptography
和 pycryptodome
。在本章中,我將專注於使用 cryptography
套件。我的理由是這個套件具有更安全的 API。在本節中,我將涵蓋這個 API 中最重要的部分。
首先,讓我們安裝 cryptography
套件到您的虛擬環境中:
pipenv install cryptography
cryptography
套件的預設後端是 OpenSSL。OpenSSL 是一個開源函式庫,包含了網路安全協定和通用加密函式的實作。這個函式庫主要是用 C 語言編寫的。OpenSSL 被 cryptography
套件封裝,像其他主要程式語言一樣,提供給 Python 使用。
cryptography
套件的作者將 API 分為兩個層次:
- 危險物料層(Hazardous Materials Layer):複雜的低階 API
- 食譜層(Recipes Layer):簡單的高階 API
危險物料層
複雜的低階 API 位於 cryptography.hazmat
下,稱為危險物料層。使用這個 API 前請三思,因為它只適合於特定的情況。根據檔案的描述,這個模組充滿了陷阱,需要深入的加密知識才能安全使用。一個小小的錯誤就可能使系統變得脆弱。
只有少數幾種情況需要使用危險物料層,例如:
- 對於太大而無法放入記憶體的檔案進行加密
- 處理需要罕見加密演算法的資料
- 為了教學目的而使用
食譜層
簡單的高階 API 稱為食譜層。檔案建議盡可能使用食譜層,只有在必要時才回退到危險物料層。這個 API 應該能滿足大多數 Python 程式設計師的加密需求。
食譜層實作了一種稱為 Fernet 的對稱加密方法。Fernet 是一個設計用於以可互操作的方式抵禦篡改的加密協定。這個協定被封裝在 cryptography.fernet
下。
Fernet
類別設計為您的一般用途加密工具。Fernet.generate_key()
方法生成 32 個隨機位元組。Fernet
初始化方法接受這個金鑰,如下所示:
from cryptography.fernet import Fernet
key = Fernet.generate_key()
內容解密:
在上述程式碼中,我們首先從 cryptography.fernet
中匯入 Fernet
類別。然後,我們使用 Fernet.generate_key()
方法生成了一個金鑰,這個金鑰是用於加密和解密的。金鑰的生成是根據隨機數生成器,保證了金鑰的安全性。
圖表翻譯:
flowchart TD A[開始] --> B[生成金鑰] B --> C[初始化 Fernet] C --> D[加密資料] D --> E[解密資料]
在這個流程圖中,我們展示了使用 Fernet
類別進行加密和解密的基本流程。首先,我們生成一個金鑰,然後使用這個金鑰初始化 Fernet
物件。接下來,我們可以使用這個物件來加密和解密資料。
圖表翻譯:
上述流程圖展示了使用 Fernet
類別進行加密和解密的步驟。首先,我們生成一個金鑰,這個金鑰是用於加密和解密的。然後,我們使用這個金鑰初始化 Fernet
物件。接下來,我們可以使用這個物件來加密和解密資料。這個流程保證了資料的安全性和完整性。
程式碼範例:
from cryptography.fernet import Fernet
# 生成金鑰
key = Fernet.generate_key()
# 初始化 Fernet
cipher_suite = Fernet(key)
# 加密資料
cipher_text = cipher_suite.encrypt(b"Hello, World!")
# 解密資料
plain_text = cipher_suite.decrypt(cipher_text)
print(plain_text)
在這個範例中,我們首先生成一個金鑰,然後使用這個金鑰初始化 Fernet
物件。接下來,我們使用這個物件來加密和解密資料。最後,我們印出解密後的資料。
內容解密:
在上述程式碼中,我們展示瞭如何使用 Fernet
類別進行加密和解密。首先,我們生成一個金鑰,然後使用這個金鑰初始化 Fernet
物件。接下來,我們使用這個物件來加密和解密資料。最後,我們印出解密後的資料。
圖表翻譯:
flowchart TD A[開始] --> B[生成金鑰] B --> C[初始化 Fernet] C --> D[加密資料] D --> E[解密資料] E --> F[印出結果]
在這個流程圖中,我們展示了使用 Fernet
類別進行加密和解密的基本流程。首先,我們生成一個金鑰,然後使用這個金鑰初始化 Fernet
物件。接下來,我們可以使用這個物件來加密和解密資料。最後,我們印出解密後的資料。
未來發展方向:
未來,cryptography
套件將繼續演進,以提供更好的安全性和效能。我們可以期待新的功能和改進,如更快的加密演算法和更強大的安全功能。
安全性考量:
在使用 cryptography
套件時,安全性是最重要的考量。我們必須確保金鑰的安全性和完整性,並且正確地使用加密和解密功能,以避免任何安全漏洞。
效能最佳化:
在某些情況下,效能是另一個重要的考量。我們可以使用不同的加密演算法和最佳化技術來提高效能,但是必須確保安全性不會受到影響。
加密技術:Fernet 和金鑰輪替
在密碼學中,Fernet是一種高階別的加密API,提供了簡單且安全的加密和解密方法。它使用了一個128位元的金鑰,分成兩部分:一部分用於加密,另一部分用於資料驗證。這樣可以確保資料不僅被加密,也被驗證,以防止未經授權的存取。
從系統安全形度分析,妥善管理金鑰和應用加密技術是保障資料安全的基本。本文深入探討了 Python 中的 secrets
和 random
模組,比較了它們在生成安全隨機數方面的差異,並闡述了使用 secrets
模組生成密碼短語的最佳實踐。同時,文章也詳細介紹了金鑰雜湊(Keyed Hashing)和 HMAC 函式,以及它們在資料驗證和完整性保護中的應用,並以 Alice 和 Mallory 的案例清晰地展示瞭如何利用金鑰雜湊來防止資料篡改。更進一步,文章還介紹了加密技術的基本概念,包括對稱式和非對稱式加密,以及如何使用 cryptography
套件中的 Fernet 實作資料加密和解密。最後,文章強調了時間攻擊的風險以及如何利用長度恆定時間比較函式來防禦此類攻擊。
技術架構視角來看,cryptography
套件的雙層 API 設計,將底層複雜的「危險物料層」與高層簡潔的「食譜層」分離,兼顧了靈活性和安全性。對於大多數開發者而言,「食譜層」的 Fernet 協定足以滿足日常加密需求,而「危險物料層」則為高階使用者提供了更精細的控制。然而,即使使用 Fernet,也需注意金鑰管理和輪替策略,避免單點失效。目前,Fernet 僅支援對稱加密,未來可考慮整合非對稱加密功能,以進一步提升安全性。
展望未來,隨著量子計算的發展,現有的加密演算法可能面臨挑戰。因此,持續關注後量子密碼學的發展,並探索新的加密技術將至關重要。同時,硬體安全模組(HSM)的應用也將日益普及,為金鑰管理和加密運算提供更強的保障。對於開發者而言,深入理解密碼學原理,並選擇合適的工具和技術,才能構建真正安全的應用系統。玄貓認為,安全意識的提升和最佳實踐的推廣,比任何單一技術都更為重要。