安全系統的設計仰賴多個基礎構件,包含資料完整性、身份驗證、不可否認性、授權和保密性,這些構件彼此互補,共同組成完整的防禦體系。Python 因其易用性和豐富的生態系統,成為建構安全系統的理想選擇。本文將介紹如何結合 Python 和相關套件,例如 hashlib、cryptography 和 Django 等,開發安全的 Web 應用程式,並探討密碼學雜湊函式的特性、選擇和實作,以及如何應用於資料完整性驗證。同時,文章也將示範如何使用 Python 計算檔案的 SHA-256 雜湊值,確保資料的完整性和安全性。
資訊安全基礎構件與工具
在設計安全的系統時,我們需要了解並結合多個基本的安全構件(building blocks),這些構件共同構成了一個強壯的安全防禦體系。表1.1列出了這些基礎構件及其對應的解決方案。
安全基礎構件
| 構件 | 解決方案 |
|---|---|
| 資料完整性(Data integrity) | 安全的網路協定、版本控制、套件管理 |
| 身份驗證(Authentication) | 使用者身份驗證、系統身份驗證、資料身份驗證、使用者註冊、登入流程、密碼重置流程、使用者會話管理 |
| 不可否認性(Nonrepudiation) | 線上交易、數位簽章、信任第三方 |
| 授權(Authorization) | 使用者授權、系統間授權、檔案系統存取授權 |
| 保密性(Confidentiality) | 加密演算法、安全網路協定 |
這些安全基礎構件之間是互補的,每一個單獨使用時作用有限,但結合起來卻能發揮出強大的作用。例如,一個電子郵件系統如果只提供了資料身份驗證而沒有資料完整性驗證,那麼作為收件人,你可以驗證寄件人的身份,但無法確定郵件在傳輸過程中是否被篡改。另一個例子是,一個新的網路協定如果只保證了保密性而沒有進行身份驗證,那麼雖然竊聽者無法取得你傳輸的資訊,但你卻無法確定你正在與誰通訊。
Python與安全工具
本文中的範例均使用Python(版本3.8)撰寫。Python因其易學易用以及龐大的生態系統而廣受歡迎。Python的熱度持續上升,在2021年中期的PYPL指數中排名第一,市場佔有率達30%。Python的受歡迎程度得益於其簡單易學的語法以及豐富的套件資源。
本文將介紹多個與安全相關的Python模組和套件,包括:
hashlib模組:用於密碼學雜湊secrets模組:用於安全亂數生成hmac模組:用於根據雜湊的訊息認證os和subprocess模組:用於與作業系統互動argon2-cffi:用於密碼保護cryptography:用於常見的密碼學功能defusedxml:用於安全地解析XMLGunicorn:一個用Python撰寫的Web伺服器閘道介面Pipenv:一個具有多種安全功能的Python套件管理器requests:一個易用的HTTP函式庫requests-oauthlib:一個客戶端OAuth 2.0實作
在Web應用安全方面,本文選擇了Django框架進行示範,因為它內建了許多安全防護措施。並且,結合了多個第三方函式庫,如django-cors-headers、django-csp、Django OAuth Toolkit和django-registration,來進一步增強安全性。
Django與第三方函式庫的安全堆積疊
圖1.3展示了一個由這些工具組成的堆積疊。在這個堆積疊中,Gunicorn透過TLS與使用者進行通訊。Django的表單驗證、模型驗證和物件關聯對映(ORM)確保了使用者輸入的安全性,而HTML跳脫則用於清理系統輸出。django-cors-headers和django-csp分別確保每個輸出的回應都具有適當的CORS和CSP標頭。hashlib和hmac模組用於進行雜湊運算,而cryptography套件則負責加密。requests-oauthlib用於與OAuth資源伺服器介接。最後,Pipenv則用於防範套件儲存函式庫中的漏洞。
# 使用hashlib進行SHA-256雜湊運算的範例
import hashlib
def calculate_sha256(data):
sha256_hash = hashlib.sha256()
sha256_hash.update(data.encode('utf-8'))
return sha256_hash.hexdigest()
data = "Hello, World!"
print(calculate_sha256(data))
內容解密:
此範例展示瞭如何使用Python的hashlib模組來計算一段資料的SHA-256雜湊值。首先,我們匯入了hashlib模組,然後定義了一個名為calculate_sha256的函式,該函式接受一段資料作為輸入,並使用SHA-256演算法計算其雜湊值。我們使用hashlib.sha256()建立了一個SHA-256雜湊物件,接著使用update()方法將輸入資料更新到雜湊物件中,最後透過呼叫hexdigest()方法取得雜湊值的十六進製表示。這個範例說明瞭如何在Python中進行基本的密碼學雜湊運算。
2.1 雜湊函式的基礎知識
雜湊函式是一種將任意大小的資料對映到固定大小輸出的函式。在本章中,我們將探討雜湊函式的基本屬性、如何使用雜湊函式驗證資料完整性,以及如何選擇合適的加密雜湊函式。
什麼是雜湊函式?
每個雜湊函式都有輸入和輸出。輸入稱為訊息,可以是任何形式的資料,如文字、影像或 Python 包。輸出是一個非常大的數字,稱為雜湊值。雜湊值通常以字母數字字串的形式表示。
雜湊函式將一組訊息對映到一組雜湊值。圖 2.1 說明瞭訊息、雜湊函式和雜湊值之間的關係。
雜湊函式的屬性
雜湊函式具有以下基本屬性:
- 確定性行為:對於給定的輸入,雜湊函式始終產生相同的輸出。
- 固定長度的雜湊值:無論輸入的大小,雜湊值的大小始終保持一致。
- 雪崩效應:輸入的微小變化會導致輸出的顯著變化。
Python 中的雜湊函式示例
Python 有一個內建的 hash 函式,用於管理字典和集合。我們可以使用它來演示雜湊函式的基本屬性。
>>> message = 'message'
>>> hash(message)
2010551929503284934
在這個例子中,hash 函式接受一個引數(訊息),並傳回一個雜湊值。
確定性行為的演示
>>> hash('same message')
1116605938627321843
>>> hash('same message')
1116605938627321843
內容解密:
- 程式碼作用:展示了Python內建
hash函式的使用方式,演示了給定相同輸入時,hash函式會產生相同的輸出,體現了雜湊函式的確定性行為。 - 觀念說明:這段程式碼幫助讀者理解雜湊函式的基本特性之一——確定性,即對於相同的輸入,輸出始終相同。
- 邏輯解析:透過執行兩次相同的
hash('same message')呼叫並得到相同的結果,證明瞭hash函式的確定性行為。這對於理解雜湊函式的工作原理至關重要。
為什麼需要加密雜湊函式?
雖然內建的 hash 函式對於某些應用(如管理字典和集合)非常有用,但它並不適合用於加密目的。加密雜湊函式需要具備額外的安全性質,如抗碰撞性和不可逆性。在接下來的章節中,我們將探討如何使用 hashlib 模組進行加密雜湊,這對於確保資料完整性和安全性至關重要。
使用 hashlib 模組進行加密雜湊
import hashlib
# 示例:使用 SHA-256 進行加密雜湊
message = 'This is a secret message.'
hash_object = hashlib.sha256(message.encode())
print(hash_object.hexdigest())
內容解密:
- 程式碼作用:演示瞭如何使用Python的
hashlib模組中的SHA-256演算法對訊息進行加密雜湊處理。 - 觀念說明:這段程式碼展示瞭如何利用加密雜湊函式來確保資料的完整性。SHA-256是一種廣泛使用的加密雜湊演算法,能夠提供強大的資料完整性驗證。
- 邏輯解析:首先匯入
hashlib模組,然後建立一個訊息字串。接著,使用hashlib.sha256()建立一個SHA-256雜湊物件,並將訊息編碼後更新到該物件中。最後,透過呼叫hexdigest()方法取得該訊息的SHA-256雜湊值的十六進製表示。這種方法可用於驗證資料是否被篡改。
密碼學雜湊函式的特性與重要性
在探討密碼學雜湊函式之前,我們需要了解雜湊函式的基本特性。雜湊函式是一種將任意長度的輸入訊息對映為固定長度的輸出值的函式。這些輸出值通常被稱為雜湊值或摘要。
固定長度的雜湊值
雜湊函式的一個關鍵特性是其輸出具有固定長度,不論輸入訊息的長度如何。這意味著無論輸入訊息是短字串還是大型檔案,雜湊值的長度保持不變。
雪崩效應
一個良好的雜湊函式應該展現雪崩效應,即輸入訊息的微小變化會導致雜湊值的顯著變化。理想情況下,每個輸出位元都應該依賴於每個輸入位元。如果兩個訊息僅相差一個位元,那麼平均而言,只有大約一半的輸出位元應該相同。
程式碼範例:內建 hash 函式的表現
>>> bin(hash('a'))
'0b100100110110010110110010001110011110011111011101010000111100010'
>>> bin(hash('b'))
'0b101111011111110110110010100110000001010000011110100010111001110'
>>> bin(hash(0))
'0b0'
>>> bin(hash(1))
'0b1'
內容解密:
- 上述程式碼展示了 Python 內建
hash函式對不同輸入的雜湊值。 - 字串 ‘a’ 和 ‘b’ 的雜湊值具有明顯的不同,展現了雪崩效應。
- 然而,整數 0 和 1 的雜湊值分別為 0 和 1,並未展現雪崩效應。
- 這表明內建
hash函式對於某些型別的輸入可能不具備足夠的雪崩效應。
密碼學雜湊函式的必要特性
密碼學雜湊函式除了需要具備一般雜湊函式的特性外,還必須滿足以下三個額外的標準:
- 單向函式特性:難以根據輸出反推輸入。
- 弱碰撞阻抗:給定一個訊息,難以找到另一個不同的訊息具有相同的雜湊值。
- 強碰撞阻抗:難以找到任何兩個具有相同雜湊值的不同訊息。
為什麼需要單向函式?
單向函式使得攻擊者難以根據雜湊值反推出原始訊息。雖然理論上攻擊者可以透過暴力破解(嘗試大量可能的輸入並比較其雜湊值)來還原訊息,但這應該是計算上不可行的。
碰撞阻抗的重要性
碰撞是指兩個不同的輸入具有相同的雜湊值。密碼學雜湊函式需要具備碰撞阻抗,以防止攻擊者找到兩個具有相同雜湊值的不同訊息。弱碰撞阻抗關注於給定一個訊息後找到另一個具有相同雜湊值的訊息的難度,而強碰撞阻抗則關注於找到任何一對具有相同雜湊值的不同訊息的難度。
圖示:弱碰撞阻抗與強碰撞阻抗的比較
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 資訊安全基礎構件與Python工具
package "安全架構" {
package "網路安全" {
component [防火牆] as firewall
component [WAF] as waf
component [DDoS 防護] as ddos
}
package "身份認證" {
component [OAuth 2.0] as oauth
component [JWT Token] as jwt
component [MFA] as mfa
}
package "資料安全" {
component [加密傳輸 TLS] as tls
component [資料加密] as encrypt
component [金鑰管理] as kms
}
package "監控審計" {
component [日誌收集] as log
component [威脅偵測] as threat
component [合規審計] as audit
}
}
firewall --> waf : 過濾流量
waf --> oauth : 驗證身份
oauth --> jwt : 簽發憑證
jwt --> tls : 加密傳輸
tls --> encrypt : 資料保護
log --> threat : 異常分析
threat --> audit : 報告生成
@enduml此圖示說明瞭弱碰撞阻抗與強碰撞阻抗之間的區別。強碰撞阻抗意味著弱碰撞阻抗,但反之則不然。
雜湊函式與資料完整性
在資訊安全的領域中,雜湊函式扮演著至關重要的角色。雜湊函式是一種將任意長度的輸入訊息轉換為固定長度輸出(雜湊值)的演算法。理想的雜湊函式應該具備碰撞阻抗性,即找到兩個不同的輸入卻產生相同的輸出雜湊值是計算上不可行的。
為何碰撞阻抗性是重要的?
根據鴿巢原理,由於輸入訊息的長度可以是任意的,而輸出的雜湊值長度是固定的,這意味著輸入空間遠大於輸出空間。因此,理論上一定存在不同的輸入訊息對應到相同的雜湊值。問題在於,一個安全的雜湊函式應該使得找到這樣的碰撞在計算上是不可行的。
典型角色介紹
在本文中,我們將使用五個典型角色來說明資訊安全概念:
- 愛麗絲(Alice) 和 鮑伯(Bob) 是好角色,他們代表了想要安全地創造和分享資訊的使用者。
- 查理(Charlie) 偶爾會出現,也是好角色。
- 伊芙(Eve) 是被動攻擊者,代表了竊聽者,她傾向於攻擊網路層面。
- 馬洛裡(Mallory) 是主動攻擊者,比伊芙更為複雜,她傾向於利用系統或使用者作為攻擊入口。
資料完整性
資料完整性是指確保資料未被意外修改。愛麗絲在一個檔案管理系統中工作,該系統最初透過儲存每個檔案的兩個副本來驗證資料完整性。如果兩個副本不比對,則認為檔案已損壞。為了減少儲存空間的消耗,愛麗絲決定使用密碼學雜湊函式來驗證資料完整性。
驗證流程如下:
- 當檔案被建立時,計算並儲存其雜湊值。
- 要驗證檔案的完整性,重新計算其雜湊值。
- 將新的雜湊值與儲存的舊雜湊值進行比較。
- 如果兩個雜湊值不比對,則認為檔案已損壞。
import hashlib
def calculate_hash(file_path):
# 使用SHA-256計算檔案的雜湊值
sha256_hash = hashlib.sha256()
with open(file_path, "rb") as f:
# 讀取檔案內容並更新雜湊值
for byte_block in iter(lambda: f.read(4096), b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
# 示例用法
file_path = "example.txt"
hash_value = calculate_hash(file_path)
print(f"檔案 {file_path} 的SHA-256雜湊值是:{hash_value}")
內容解密:
- 使用Python的
hashlib模組來計算檔案的SHA-256雜湊值。 hashlib.sha256()建立了一個SHA-256雜湊物件。- 以二進位制模式讀取檔案,並以4096位元組為單位更新雜湊物件,以避免一次性載入整個檔案到記憶體中。
- 最終輸出雜湊值的十六進製表示。
選擇密碼學雜湊函式
Python內建了對密碼學雜湊的支援,透過hashlib模組提供。algorithms_guaranteed集合包含了所有保證在所有平台上都可用的雜湊函式。
import hashlib
# 列出所有保證可用的雜湊演算法
available_algorithms = sorted(hashlib.algorithms_guaranteed)
print("可用的雜湊演算法:", available_algorithms)
內容解密:
hashlib.algorithms_guaranteed傳回一個集合,包含了所有保證可用的雜湊演算法名稱。- 使用
sorted()對列表進行排序,以便於閱讀。
安全的雜湊函式
目前,安全的雜湊函式家族包括SHA-2、SHA-3和BLAKE2。
SHA-2家族
包括SHA-224、SHA-256、SHA-384和SHA-512,其中SHA-256和SHA-512是核心成員。建議使用SHA-256進行通用目地的密碼學雜湊。
SHA-3家族
包括SHA3-224、SHA3-256、SHA3-384、SHA3-512、SHAKE128和SHAKE256。SHA-3被認為是SHA-2的自然繼承者。
# 使用SHA-256計算字串的雜湊值
def sha256_hash(data):
return hashlib.sha256(data.encode()).hexdigest()
# 示例用法
data = "Hello, World!"
print(f"字串 '{data}' 的SHA-256雜湊值是:{sha256_hash(data)}")
內容解密:
- 使用
hashlib.sha256()建立一個SHA-256雜湊物件。 - 使用
.encode()將輸入字串轉換為位元組,因為hashlib需要位元組型別的輸入。 - 使用
.hexdigest()取得雜湊值的十六進製表示。
綜上所述,選擇適當的密碼學雜湊函式對於確保資料完整性至關重要。Python的hashlib模組提供了豐富的選擇和便捷的使用方式,使得在實際應用中實作資料完整性驗證變得簡單而有效。
密碼學雜湊函式的選擇與實作
在密碼學領域中,雜湊函式扮演著至關重要的角色,用於資料完整性驗證、數字簽名等安全應用。選擇適當的雜湊函式對於確保系統的安全性至關重要。
安全的雜湊函式
目前,安全的雜湊函式包括 SHA-256、SHA-3 以及 BLAKE2 等。
SHA-256
SHA-256 是廣泛使用的密碼學雜湊函式之一,提供 256 位元的雜湊值。它被認為是安全的,並且在多數密碼學應用中被推薦使用。
SHA-3
SHA-3 是另一種安全的雜湊函式,由美國國家標準與技術研究所(NIST)標準化。雖然 SHA-3 在高安全性環境中被推薦,但相較於 SHA-256,其支援度可能較低。
BLAKE2
BLAKE2 是一種高速的雜湊函式,針對現代 CPU 架構進行了最佳化。它提供了兩種版本:BLAKE2b 和 BLAKE2s,分別針對 64 位元和 8 至 32 位元平台進行了最佳化。對於需要處理大量資料的場景,BLAKE2 是一個理想的選擇。
不安全的雜湊函式
一些雜湊函式由於安全性問題而不應再被使用,例如 MD5 和 SHA-1。
MD5
MD5 是一種過時的 128 位元雜湊函式,早在 2004 年就已經被證實存在碰撞漏洞。目前,MD5 碰撞可以在普通硬體上於一小時內生成,因此不應再用於安全相關的應用。
SHA-1
SHA-1 也是一種過時的 160 位元雜湊函式,由美國國家安全域性(NSA)在 1990 年代中期開發。2017 年,研究人員成功製造了 SHA-1 的碰撞,證明瞭其不再安全。
Python 中的密碼學雜湊函式實作
Python 的 hashlib 模組提供了多種密碼學雜湊函式的實作,包括 SHA-256、SHA-3 和 BLAKE2 等。
import hashlib
# 使用命名建構子建立 SHA-256 例項
named = hashlib.sha256()
# 使用通用建構子建立 SHA-256 例項
generic = hashlib.new('sha256')
每個雜湊函式例項都具有相同的 API,包括 digest 和 hexdigest 方法,分別傳回位元組和十六進位文字形式的雜湊值。
>>> from hashlib import sha256
>>> message = b'message'
>>> hash_function = sha256(message)
>>> hash_function.digest()
b'\xabS\n\xe4Y\x14\x98+y\xf9\xb7\xe3\xfb\xa9\x94\xcf\xd1\xf3\xfb"\xf7\x1c\xea\x1a\xfb\xf0+F\x0cm\x1d'
>>> hash_function.hexdigest()
'ab530a13e45914982b79f9b7e3fba994cfd1f3fb22f71cea1afbf02b460c6d1d'
內容解密:
hashlib.sha256():建立一個 SHA-256 雜湊函式例項。hash_function.digest():傳回雜湊值的位元組表示。hash_function.hexdigest():傳回雜湊值的十六進位文字表示。
使用 update 方法進行逐步雜湊
update 方法允許逐步處理訊息並計算雜湊值,這對於處理大型訊息或無法一次性載入記憶體的資料非常有用。
>>> message = b'message'
>>> hash_function = hashlib.sha256()
>>> hash_function.update(message)
>>> hash_function.digest() == hashlib.sha256(message).digest()
True
內容解密:
hash_function.update(message):將訊息傳遞給雜湊函式進行處理。hash_function.digest() == hashlib.sha256(message).digest():驗證逐步處理與一次性處理的結果一致性。
分段處理大型訊息
對於大型訊息,可以分段處理並迭代呼叫 update 方法來計算雜湊值。
>>> from hashlib import sha256
>>> once = sha256()
>>> once.update(b'message')
>>> many = sha256()
>>> many.update(b'm')
>>> many.update(b'e')
>>> many.update(b's')
>>> many.update(b's')
>>> many.update(b'a')
>>> many.update(b'g')
>>> many.update(b'e')
>>> once.digest() == many.digest()
True
內容解密:
once.update(b'message'):一次性處理整個訊息。many.update(b'm')等:分段處理訊息,每次呼叫update方法更新雜湊值。once.digest() == many.digest():驗證分段處理與一次性處理的結果一致性。