在資訊安全領域,保護敏感資料至關重要。本文介紹如何使用 Python 的 cryptography 模組實作對稱加密,例如 AES 和 Fernet,以及如何使用 PBKDF2HMAC 函式從密碼派生金鑰,確保資料機密性。同時,我們也將探討隱寫術,特別是 LSB 技術,如何將資訊隱藏於影像中,並介紹 Stegano 和 Stepic 等實用工具。最後,我們將強調使用 secrets 模組生成安全金鑰和密碼的最佳實踐,以提升整體安全性。

使用密碼學進行資訊加密與解密

在前面的章節中,我們已經探討了使用 pycryptodome 模組進行加密與解密的方法。本章節將著重介紹另一個強大的密碼學模組——cryptography,以及如何利用它來進行資料的加密與解密,包括使用 AES 等演算法。

cryptography 模組簡介

cryptography 是一個在 PyPI 倉函式庫中可用的模組,可以透過以下命令進行安裝:

$ pip3 install cryptography

相較於其他密碼學模組,如 pycryptodomecryptography 的主要優勢在於其在執行密碼學操作時提供了卓越的效能。該模組同時包含了高階和低階介面,以支援常見的密碼學演算法,例如對稱加密、訊息摘要和金鑰派生函式。

使用 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()))

程式碼解析:

  1. 首先,從 cryptography.fernet 模組匯入 Fernet 類別。
  2. 使用 Fernet.generate_key() 方法產生一個用於對稱加密的金鑰。
  3. 建立一個 Fernet 物件 cipher_suite,並將產生的金鑰傳入。
  4. 將待加密的訊息編碼為 bytes 型別。
  5. 使用 cipher_suite.encrypt() 方法對訊息進行加密,得到密鑰。
  6. 使用 cipher_suite.decrypt() 方法對密鑰進行解密,得到原始訊息。
  7. 列印出密鑰和解密後的原始訊息。

執行上述程式碼後,可以看到以下輸出:

$ 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))

程式碼解析:

  1. 定義 generate_key() 函式,用於產生金鑰並將其儲存於 secret.key 檔案中。
  2. 定義 load_key() 函式,用於從 secret.key 檔案中讀取金鑰。
  3. 定義 encrypt_message() 函式,用於對訊息進行加密。
  4. 定義 decrypt_message() 函式,用於對加密後的訊息進行解密。
  5. 在主程式中,呼叫上述函式以測試加密和解密的功能。

使用 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()))

程式碼解析:

  1. 從相關模組中匯入必要的類別和函式。
  2. 設定密碼並產生一個隨機的 salt 值。
  3. 使用 PBKDF2HMAC 類別從密碼和 salt 值中派生出金鑰。
  4. 使用 verify() 方法驗證派生出的金鑰是否正確。
  5. 將金鑰進行 base64 編碼,以符合 Fernet 的要求。
  6. 建立一個 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進行對稱加密
AESAdvanced 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隱寫術
LSBLeast 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安全令牌該令牌可以用作金鑰或密碼