如何使用Python通过AWS非对称密钥实现大文件加密与解密
使用Python结合AWS非对称密钥加密解密大文件
由于AWS KMS非对称密钥(如RSA、ECC)的加密 payload 存在大小限制(例如RSA 2048位最多加密245字节),直接加密大文件不可行,因此必须采用信封加密方案,核心逻辑如下:
核心思路
- 生成一次性对称密钥(如AES-256),用它加密大文件(对称加密效率远高于非对称加密)
- 使用AWS KMS的非对称公钥加密上述对称密钥
- 保存加密后的文件、加密后的对称密钥及加密所需的初始化向量(IV)
- 解密时,先用AWS KMS的非对称私钥解密对称密钥,再用该密钥解密大文件
前置准备
- 安装依赖:
pip install boto3 cryptography - 配置AWS凭证:通过环境变量、
~/.aws/credentials文件或IAM角色授权 - 拥有AWS KMS非对称密钥对,且当前身份具备
kms:Encrypt(加密)和kms:Decrypt(解密)权限
加密实现代码
import boto3 import os from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend def encrypt_large_file(kms_key_id, input_file_path, output_file_path): # 初始化KMS客户端 kms_client = boto3.client('kms') # 生成AES-256对称密钥和16字节IV(CBC模式) aes_key = os.urandom(32) iv = os.urandom(16) # 用AWS KMS非对称公钥加密AES密钥 encrypted_aes_key = kms_client.encrypt( KeyId=kms_key_id, Plaintext=aes_key, EncryptionAlgorithm='RSAES_OAEP_SHA_256' )['CiphertextBlob'] # 用AES-CBC加密大文件 cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend()) encryptor = cipher.encryptor() with open(input_file_path, 'rb') as infile, open(output_file_path, 'wb') as outfile: # 先写入加密后的AES密钥长度、密钥本身、IV outfile.write(len(encrypted_aes_key).to_bytes(4, byteorder='big')) outfile.write(encrypted_aes_key) outfile.write(iv) # 分块读取加密(避免加载整个大文件到内存) chunk_size = 64 * 1024 while chunk := infile.read(chunk_size): # 填充到16字节倍数(CBC模式要求) if len(chunk) % 16 != 0: chunk += b' ' * (16 - len(chunk) % 16) outfile.write(encryptor.update(chunk)) outfile.write(encryptor.finalize()) # 使用示例 # encrypt_large_file('arn:aws:kms:us-east-1:123456789012:key/your-key-id', 'input.txt', 'encrypted.bin')
解密实现代码
def decrypt_large_file(kms_key_id, input_file_path, output_file_path): kms_client = boto3.client('kms') with open(input_file_path, 'rb') as infile, open(output_file_path, 'wb') as outfile: # 读取加密后的AES密钥长度和密钥 encrypted_key_len = int.from_bytes(infile.read(4), byteorder='big') encrypted_aes_key = infile.read(encrypted_key_len) # 读取IV iv = infile.read(16) # 用AWS KMS非对称私钥解密AES密钥 decrypted_aes_key = kms_client.decrypt( CiphertextBlob=encrypted_aes_key, KeyId=kms_key_id, EncryptionAlgorithm='RSAES_OAEP_SHA_256' )['Plaintext'] # 用AES-CBC解密文件 cipher = Cipher(algorithms.AES(decrypted_aes_key), modes.CBC(iv), backend=default_backend()) decryptor = cipher.decryptor() chunk_size = 64 * 1024 while chunk := infile.read(chunk_size): outfile.write(decryptor.update(chunk)) outfile.write(decryptor.finalize()) # 去除填充的空格 outfile.seek(-1, os.SEEK_END) while outfile.read(1) == b' ': outfile.seek(-2, os.SEEK_CUR) outfile.truncate() # 使用示例 # decrypt_large_file('arn:aws:kms:us-east-1:123456789012:key/your-key-id', 'encrypted.bin', 'decrypted.txt')
关键注意事项
- 加密模式选择:如果需要完整性校验,推荐使用AES-GCM模式(自带认证标签),替换上述代码中的CBC模式即可,避免文件被篡改
- 权限控制:确保IAM策略仅允许必要的身份访问KMS密钥,遵循最小权限原则
- 密钥存储:加密后的对称密钥和IV可直接附加在加密文件头部(如示例所示),无需单独存储,简化管理
- 分块处理:代码采用分块读写,避免大文件占用过多内存,适用于GB级文件
内容的提问来源于stack exchange,提问作者gregory jithin
相关产品推荐
相关产品推荐

