在資訊安全領域,保護敏感資料至關重要。本文介紹如何使用 Python 的 cryptography 模組實作對稱加密,例如 AES 和 Fernet,以及如何使用 PBKDF2HMAC 函式從密碼派生金鑰,確保資料機密性。同時,我們也將探討隱寫術,特別是 LSB 技術,如何將資訊隱藏於影像中,並介紹 Stegano 和 Stepic 等實用工具。最後,我們將強調使用 secrets 模組生成安全金鑰和密碼的最佳實踐,以提升整體安全性。
使用密碼學進行資訊加密與解密
在前面的章節中,我們已經探討了使用 pycryptodome 模組進行加密與解密的方法。本章節將著重介紹另一個強大的密碼學模組——cryptography,以及如何利用它來進行資料的加密與解密,包括使用 AES 等演算法。
cryptography 模組簡介
cryptography 是一個在 PyPI 倉函式庫中可用的模組,可以透過以下命令進行安裝:
$ pip3 install cryptography
相較於其他密碼學模組,如 pycryptodome,cryptography 的主要優勢在於其在執行密碼學操作時提供了卓越的效能。該模組同時包含了高階和低階介面,以支援常見的密碼學演算法,例如對稱加密、訊息摘要和金鑰派生函式。
使用 fernet 套件進行對稱加密
Fernet 是對稱加密的一種實作方式,能夠確保加密後的訊息不會被竄改或讀取,除非擁有正確的金鑰。
產生金鑰
要產生金鑰,可以使用 Fernet 介面中的 generate_key() 方法。以下是一個範例程式碼(位於 cryptography 資料夾中的 encrypt_decrypt_message.py 檔案):
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher_suite = Fernet(key)
print("Key " + str(cipher_suite))
message = "Secret message".encode("utf8")
cipher_text = cipher_suite.encrypt(message)
plain_text = cipher_suite.decrypt(cipher_text)
print("Cipher text: " + str(cipher_text.decode()))
print("Plain text: " + str(plain_text.decode()))
程式碼解析:
- 首先,從
cryptography.fernet模組匯入Fernet類別。 - 使用
Fernet.generate_key()方法產生一個用於對稱加密的金鑰。 - 建立一個
Fernet物件cipher_suite,並將產生的金鑰傳入。 - 將待加密的訊息編碼為 bytes 型別。
- 使用
cipher_suite.encrypt()方法對訊息進行加密,得到密鑰。 - 使用
cipher_suite.decrypt()方法對密鑰進行解密,得到原始訊息。 - 列印出密鑰和解密後的原始訊息。
執行上述程式碼後,可以看到以下輸出:
$ python3 encrypt_decrypt_message.py
Key <cryptography.fernet.Fernet object at 0x7f29a2bf37b8>
Cipher text: gAAAAABfcglbXHiFG4VIGuH7tnI4dwXBMTi22TmF7Kpp9lcPyvqjbvhQNVa2EF8GDrothluhwp3M8nBB6kd4MBXD7aUeJuFtwA==
Plain text: Secret message
將金鑰儲存於檔案中
為了提高實用性,可以將金鑰儲存於檔案中,以便在加密和解密時使用。以下是一個改進的範例程式碼(位於 cryptography 資料夾中的 encrypt_decrypt_message_secret_key.py 檔案):
from cryptography.fernet import Fernet
def generate_key():
key = Fernet.generate_key()
with open("secret.key", "wb") as key_file:
key_file.write(key)
def load_key():
return open("secret.key", "rb").read()
def encrypt_message(message):
key = load_key()
encoded_message = message.encode()
fernet = Fernet(key)
encrypted_message = fernet.encrypt(encoded_message)
return encrypted_message
def decrypt_message(encrypted_message):
key = load_key()
fernet = Fernet(key)
decrypted_message = fernet.decrypt(encrypted_message)
return decrypted_message.decode()
if __name__ == "__main__":
generate_key()
message_encrypted = encrypt_message("encrypt this message")
print('Message encrypted:', message_encrypted)
print('Message decrypted:', decrypt_message(message_encrypted))
程式碼解析:
- 定義
generate_key()函式,用於產生金鑰並將其儲存於secret.key檔案中。 - 定義
load_key()函式,用於從secret.key檔案中讀取金鑰。 - 定義
encrypt_message()函式,用於對訊息進行加密。 - 定義
decrypt_message()函式,用於對加密後的訊息進行解密。 - 在主程式中,呼叫上述函式以測試加密和解密的功能。
使用 PBKDF2HMAC 子模組進行加密
PBKDF2(Password-Based Key Derivation Function 2)是一種常見的金鑰派生函式,可以從密碼中派生出金鑰。以下是一個範例程式碼(位於 cryptography 資料夾中的 encrypt_decrypt_PBKDF2HMAC.py 檔案):
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64
import os
password = "password".encode("utf8")
salt = os.urandom(16)
pbkdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = pbkdf.derive(password)
pbkdf.verify(password, key)
key = base64.urlsafe_b64encode(key)
fernet = Fernet(key)
token = fernet.encrypt("Secret message".encode("utf8"))
print("Token: " + str(token))
print("Message: " + str(fernet.decrypt(token).decode()))
程式碼解析:
- 從相關模組中匯入必要的類別和函式。
- 設定密碼並產生一個隨機的 salt 值。
- 使用
PBKDF2HMAC類別從密碼和 salt 值中派生出金鑰。 - 使用
verify()方法驗證派生出的金鑰是否正確。 - 將金鑰進行 base64 編碼,以符合
Fernet的要求。 - 建立一個
Fernet物件,並使用其進行加密和解密操作。
本章節介紹瞭如何使用 cryptography 模組進行對稱加密和解密,包括使用 Fernet 套件和 PBKDF2HMAC 子模組。這些技術可以用於保護敏感資料的安全。
資訊安全中的密碼學與隱寫術技術探討
前言
在現代資訊安全領域中,密碼學(Cryptography)與隱寫術(Steganography)扮演著至關重要的角色。本文將探討這兩種技術的原理、實作方法以及相關的Python模組應用。
使用密碼學進行資訊加密與解密
密碼學是研究如何保護資訊安全的科學,其核心技術包括加密(Encryption)與解密(Decryption)。在Python中,cryptography模組提供了豐富的密碼學功能。
使用PBKDF2HMAC進行金鑰派生
PBKDF2HMAC是一種常見的金鑰派生函式,能夠從密碼中產生安全的金鑰。以下是一個使用cryptography模組實作PBKDF2HMAC的範例:
import os
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
# 產生隨機鹽值
salt = os.urandom(16)
# 定義金鑰派生函式
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
# 從密碼中產生金鑰
password = "mysecretpassword".encode("utf-8")
key = kdf.derive(password)
#### 內容解密:
1. `os.urandom(16)`用於產生隨機鹽值,增加金鑰的安全性。
2. `PBKDF2HMAC`類別用於定義金鑰派生函式,採用SHA256演算法,產生的金鑰長度為32位元組。
3. `derive`方法根據輸入的密碼產生金鑰。
#### 使用AES進行對稱加密
AES(Advanced Encryption Standard)是一種廣泛使用的對稱加密演算法。以下是一個使用`cryptography`模組實作AES加密與解密的範例:
```python
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
# 產生隨機金鑰與初始向量
key = os.urandom(32)
iv = os.urandom(16)
# 建立AES加密器
cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
encryptor = cipher.encryptor()
# 加密訊息
message = "a secret message".encode("utf-8")
cipher_text = encryptor.update(message) + encryptor.finalize()
#### 內容解密:
1. `os.urandom(32)`與`os.urandom(16)`分別用於產生隨機金鑰與初始向量。
2. `Cipher`類別用於建立AES加密器,採用CBC模式。
3. `encryptor.update(message)`方法用於加密輸入的訊息。
### 隱寫術技術
隱寫術是一種將秘密訊息隱藏在公開資訊中的技術,例如影像、音訊或影片。
#### LSB隱寫術
LSB(Least Significant Bit)隱寫術是一種常見的影像隱寫術技術,透過修改畫素值的最低位來隱藏訊息。以下是一個使用Python實作LSB隱寫術的範例:
```python
from PIL import Image
def set_LSB(value, bit):
if bit == '0':
value = value & 254
else:
value = value | 1
return value
def get_LSB(value):
if value & 1 == 0:
return '0'
else:
return '1'
# 定義函式以讀取影像並提取隱藏訊息
def extract_message(image_path):
image = Image.open(image_path)
pixel_list = list(image.getdata())
message = ""
for pix1, pix2 in get_pixel_pairs(pixel_list):
message_byte = "0b"
for p in pix1:
message_byte += get_LSB(p)
#### 內容解密:
1. `set_LSB`函式用於設定畫素值的最低位。
2. `get_LSB`函式用於取得畫素值的最低位。
3. `extract_message`函式用於讀取影像並提取隱藏訊息。
## 使用最低有效位(LSB)技術進行隱寫術
隱寫術是一種將秘密資訊隱藏在非秘密資訊中的技術。在本章節中,我們將探討如何使用Python實作LSB隱寫術,以將文字資訊隱藏在影像中。
### LSB隱寫術原理
LSB隱寫術的基本原理是利用影像畫素值的最低有效位來隱藏資訊。由於人眼對影像的細微變化不敏感,因此可以透過修改畫素值的最低有效位來隱藏資訊,而不會對影像的視覺效果產生明顯影響。
### 使用Python實作LSB隱寫術
首先,我們需要匯入必要的模組,包括`PIL`(Python Imaging Library)用於影像處理。
#### 隱藏資訊
要將資訊隱藏在影像中,我們需要將資訊轉換為二進位制格式,然後將每個二進位制位替換到影像畫素值的最低有效位中。
```python
from PIL import Image
def hide_message(image, message, outfile):
message += chr(0)
c_image = Image.open(image)
c_image = c_image.convert('RGBA')
out = Image.new(c_image.mode, c_image.size)
width, height = c_image.size
pixList = list(c_image.getdata())
newArray = []
for i in range(len(message)):
charInt = ord(message[i])
cb = str(bin(charInt))[2:].zfill(8)
pix1 = pixList[i*2]
pix2 = pixList[(i*2)+1]
newpix1 = []
newpix2 = []
for j in range(0,4):
newpix1.append(set_LSB(pix1[j], cb[j]))
newpix2.append(set_LSB(pix2[j], cb[j+4]))
newArray.append(tuple(newpix1))
newArray.append(tuple(newpix2))
newArray.extend(pixList[len(message)*2:])
out.putdata(newArray)
out.save(outfile)
return outfile
#### 內容解密:
此函式首先開啟輸入影像並將其轉換為RGBA模式。然後,它建立一個新的影像,並將原始影像的畫素資料複製到新的影像中。接下來,它遍歷要隱藏的資訊的每個字元,將其轉換為二進位制格式,並將每個二進位制位替換到影像畫素值的最低有效位中。最後,它儲存新的影像。
### 提取隱藏資訊
要提取隱藏的資訊,我們需要讀取影像的畫素值,並從最低有效位中還原二進位制資訊。
```python
def extract_message(image_path):
c_image = Image.open(image_path)
pix = c_image.getdata()
message = ""
message_byte = "0b"
for p in pix:
message_byte += get_LSB(p)
if len(message_byte) == 9:
if message_byte == "0b000000000":
break
message += chr(int(message_byte,2))
message_byte = "0b"
return message
#### 內容解密:
此函式開啟影像並讀取其畫素值。然後,它遍歷每個畫素值,提取最低有效位,並將其組合成二進位制位元組。當遇到一個全零位元組時,它停止讀取,並傳回提取的資訊。
### 使用Stegano和Stepic進行隱寫術
除了手動實作LSB隱寫術外,還可以使用現有的工具,如Stegano和Stepic。
#### Stegano
Stegano是一個用於在PNG影像中隱藏文字資訊的工具。可以使用以下命令安裝:
```bash
$ sudo pip3 install stegano
Stepic
Stepic是一個Python模組,用於在影像中隱藏任意資料。可以使用以下命令安裝:
$ pip3 install stepic
安全地生成金鑰和密碼
在進行加密和隱寫術時,生成安全、隨機的金鑰和密碼非常重要。Python的secrets模組提供了生成強隨機數的功能,適用於密碼學應用。
使用secrets模組生成金鑰
secrets模組可以生成可靠的隨機資料,用於密碼學操作。推薦使用secrets模組而不是random模組,因為random模組是為建模和模擬而設計的,而不是為了安全或密碼學。
import secrets
# 生成一個安全的隨機令牌
token = secrets.token_urlsafe(32)
print(token)
#### 內容解密:
此程式碼使用`secrets.token_urlsafe()`函式生成一個安全的隨機URL安全令牌,該令牌可以用作金鑰或密碼。