全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 10 分钟 ✍️ juanwangdev

Python加密与解密操作

加密是保护数据机密性的核心手段。使用cryptography库实现安全的加密操作。

cryptography 库概述

Bash
pip install cryptography
Python
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes, symmetric, asymmetric
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
import base64
import os

# 主要组件:
# - Fernet: 对称加密(简单API)
# - AES: 高级对称加密
# - RSA: 非对称加密
# - 哈希: SHA256等

对称加密 - Fernet

Python
from cryptography.fernet import Fernet

# 生成密钥
key = Fernet.generate_key()
print(key)  # base64编码的32字节密钥

# 创建加密器
cipher = Fernet(key)

# 加密
message = "敏感数据"
encrypted = cipher.encrypt(message.encode())
print(encrypted)  # bytes

# 解密
decrypted = cipher.decrypt(encrypted)
print(decrypted.decode())  # "敏感数据"
Python
# 密钥管理
from cryptography.fernet import Fernet
import os

class SecureKeyManager:
    "安全密钥管理"

    def __init__(self, key_file: str):
        self.key_file = key_file
        self.key = self._load_or_create_key()
        self.cipher = Fernet(self.key)

    def _load_or_create_key(self):
        "加载或创建密钥"
        if os.path.exists(self.key_file):
            with open(self.key_file, 'rb') as f:
                return f.read()
        else:
            key = Fernet.generate_key()
            # 安全存储密钥
            with open(self.key_file, 'wb') as f:
                f.write(key)
            os.chmod(self.key_file, 0o600)  # 仅所有者可读写
            return key

    def encrypt_data(self, data: str) -> bytes:
        "加密数据"
        return self.cipher.encrypt(data.encode())

    def decrypt_data(self, encrypted: bytes) -> str:
        "解密数据"
        return self.cipher.decrypt(encrypted).decode()

manager = SecureKeyManager('/secure/key.key')
encrypted = manager.encrypt_data("敏感信息")

从密码生成密钥

Python
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.fernet import Fernet
import base64
import os

def generate_key_from_password(password: str, salt: bytes = None) -> tuple:
    "从密码生成加密密钥"
    if salt is None:
        salt = os.urandom(16)

    # PBKDF2密钥派生
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=100000,
        backend=default_backend()
    )

    key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
    return key, salt

def encrypt_with_password(data: str, password: str) -> dict:
    "使用密码加密"
    key, salt = generate_key_from_password(password)
    cipher = Fernet(key)
    encrypted = cipher.encrypt(data.encode())

    return {
        'encrypted': encrypted,
        'salt': salt  # 需要存储盐以解密
    }

def decrypt_with_password(encrypted: bytes, password: str, salt: bytes) -> str:
    "使用密码解密"
    key, _ = generate_key_from_password(password, salt)
    cipher = Fernet(key)
    return cipher.decrypt(encrypted).decode()

# 使用
result = encrypt_with_password("敏感数据", "user_password")
decrypted = decrypt_with_password(
    result['encrypted'],
    "user_password",
    result['salt']
)

AES 高级加密

Python
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os

class AESCipher:
    "AES加密器"

    def __init__(self, key: bytes = None):
        self.key = key or os.urandom(32)  # AES-256需要32字节密钥

    def encrypt(self, data: bytes) -> dict:
        "AES-CBC加密"
        # 生成随机IV
        iv = os.urandom(16)

        cipher = Cipher(
            algorithms.AES(self.key),
            modes.CBC(iv),
            backend=default_backend()
        )

        encryptor = cipher.encryptor()

        # PKCS7填充
        padded_data = self._pad(data)
        encrypted = encryptor.update(padded_data) + encryptor.finalize()

        return {'encrypted': encrypted, 'iv': iv}

    def decrypt(self, encrypted: bytes, iv: bytes) -> bytes:
        "AES-CBC解密"
        cipher = Cipher(
            algorithms.AES(self.key),
            modes.CBC(iv),
            backend=default_backend()
        )

        decryptor = cipher.decryptor()
        decrypted = decryptor.update(encrypted) + decryptor.finalize()

        return self._unpad(decrypted)

    def _pad(self, data: bytes) -> bytes:
        "PKCS7填充"
        block_size = 16
        padding_length = block_size - len(data) % block_size
        return data + bytes([padding_length]) * padding_length

    def _unpad(self, data: bytes) -> bytes:
        "移除填充"
        padding_length = data[-1]
        return data[:-padding_length]

aes = AESCipher()
encrypted = aes.encrypt(b"敏感数据")
decrypted = aes.decrypt(encrypted['encrypted'], encrypted['iv'])
Python
# AES-GCM(推荐,提供认证加密)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

class AESGCMCipher:
    "AES-GCM认证加密"

    def __init__(self, key: bytes = None):
        self.key = key or os.urandom(32)
        self.aesgcm = AESGCM(self.key)

    def encrypt(self, data: bytes, associated_data: bytes = None) -> dict:
        "加密"
        nonce = os.urandom(12)  # GCM推荐12字节nonce
        encrypted = self.aesgcm.encrypt(nonce, data, associated_data)

        return {
            'encrypted': encrypted,
            'nonce': nonce,
            'associated_data': associated_data
        }

    def decrypt(self, encrypted: bytes, nonce: bytes,
                associated_data: bytes = None) -> bytes:
        "解密"
        return self.aesgcm.decrypt(nonce, encrypted, associated_data)

gcm = AESGCMCipher()
result = gcm.encrypt(b"敏感数据", b"metadata")
decrypted = gcm.decrypt(result['encrypted'], result['nonce'], result['associated_data'])

RSA 非对称加密

Python
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend

class RSACipher:
    "RSA加密器"

    def __init__(self):
        # 生成密钥对
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
            backend=default_backend()
        )
        self.public_key = self.private_key.public_key()

    def encrypt(self, data: bytes) -> bytes:
        "公钥加密"
        encrypted = self.public_key.encrypt(
            data,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        return encrypted

    def decrypt(self, encrypted: bytes) -> bytes:
        "私钥解密"
        decrypted = self.private_key.decrypt(
            encrypted,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        return decrypted

    def export_public_key(self) -> bytes:
        "导出公钥"
        from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
        return self.public_key.public_bytes(
            encoding=Encoding.PEM,
            format=PublicFormat.SubjectPublicKeyInfo
        )

    def export_private_key(self, password: str = None) -> bytes:
        "导出私钥"
        from cryptography.hazmat.primitives.serialization import (
            Encoding, PrivateFormat, BestAvailableEncryption, NoEncryption
        )

        if password:
            encryption = BestAvailableEncryption(password.encode())
        else:
            encryption = NoEncryption()

        return self.private_key.private_bytes(
            encoding=Encoding.PEM,
            format=PrivateFormat.PKCS8,
            encryption_algorithm=encryption
        )

rsa_cipher = RSACipher()
encrypted = rsa_cipher.encrypt(b"敏感数据")
decrypted = rsa_cipher.decrypt(encrypted)

数字签名

Python
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes

class DigitalSignature:
    "数字签名"

    def __init__(self):
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048
        )
        self.public_key = self.private_key.public_key()

    def sign(self, data: bytes) -> bytes:
        "签名"
        signature = self.private_key.sign(
            data,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return signature

    def verify(self, data: bytes, signature: bytes) -> bool:
        "验证签名"
        try:
            self.public_key.verify(
                signature,
                data,
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256()
            )
            return True
        except:
            return False

signer = DigitalSignature()
signature = signer.sign(b"待签名数据")
is_valid = signer.verify(b"待签名数据", signature)

混合加密

Python
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes

class HybridEncryption:
    "混合加密(RSA + AES)"

    def __init__(self):
        self.rsa_private = rsa.generate_private_key(
            public_exponent=65537, key_size=2048
        )
        self.rsa_public = self.rsa_private.public_key()

    def encrypt(self, data: bytes) -> dict:
        "加密"
        # 生成随机AES密钥
        aes_key = Fernet.generate_key()
        cipher = Fernet(aes_key)

        # AES加密数据
        encrypted_data = cipher.encrypt(data)

        # RSA加密AES密钥
        encrypted_key = self.rsa_public.encrypt(
            aes_key,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )

        return {
            'encrypted_data': encrypted_data,
            'encrypted_key': encrypted_key
        }

    def decrypt(self, encrypted_data: bytes, encrypted_key: bytes) -> bytes:
        "解密"
        # RSA解密AES密钥
        aes_key = self.rsa_private.decrypt(
            encrypted_key,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )

        # AES解密数据
        cipher = Fernet(aes_key)
        return cipher.decrypt(encrypted_data)

hybrid = HybridEncryption()
encrypted = hybrid.encrypt(b"大文件数据")
decrypted = hybrid.decrypt(encrypted['encrypted_data'], encrypted['encrypted_key'])

安全哈希

Python
from cryptography.hazmat.primitives import hashes

def secure_hash(data: bytes) -> bytes:
    "安全哈希"
    digest = hashes.Hash(hashes.SHA256())
    digest.update(data)
    return digest.finalize()

def secure_hash_file(filepath: str) -> bytes:
    "文件哈希"
    digest = hashes.Hash(hashes.SHA256())

    with open(filepath, 'rb') as f:
        while chunk := f.read(8192):
            digest.update(chunk)

    return digest.finalize()

# HMAC
from cryptography.hazmat.primitives.hmac import HMAC

def hmac_sign(key: bytes, data: bytes) -> bytes:
    "HMAC签名"
    h = HMAC(key, hashes.SHA256())
    h.update(data)
    return h.finalize()

def hmac_verify(key: bytes, data: bytes, signature: bytes) -> bool:
    "HMAC验证"
    h = HMAC(key, hashes.SHA256())
    h.update(data)
    try:
        h.verify(signature)
        return True
    except:
        return False

要点总结

  1. Fernet提供简单的对称加密API
  2. AES-GCM推荐用于认证加密
  3. RSA用于密钥加密和小数据,大数据用AES
  4. PBKDF2从密码安全派生密钥
  5. 混合加密结合对称和非对称的优点

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python代码注入防护
下一篇 → Python安全的随机数生成
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库