You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AES-CTR解密函数异常:无法获取目标明文,返回字节数据求助

AES-CTR解密失败无法得到预期明文问题排查

问题描述

编写AES-CTR加解密函数后,调用解密时得到字节数据,解码UTF-8时报错:'utf-8' codec can't decode byte 0xf6 in position 0: invalid start byte,无法得到预期明文SandI2021。

输入信息

  • 密钥:maru000000000000
  • IV:b'\x19\x89j=-\xed)\xe3\xca\x1b\xde?\x15\x1d$!'
  • 密文:b'\xc6Q\xff\x94\x82\xf8\xd4\xfd\x17'
  • 当前解密结果:b'\xf6\x18n:\x8a\xb6\x8e\xb1\xb1'

现有代码

解密函数

def decrypt(key, iv, ciphertext):
    assert len(key) == key_bytes                                                                 
    # Initialize counter for decryption. iv should be the same as the output of
    # encrypt().
    iv_int = int(binascii.hexlify(iv), 16)
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)

    # Create AES-CTR cipher.
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

    # Decrypt and return the plaintext.
    plaintext = aes.decrypt(ciphertext)
    return plaintext

加密函数

def encrypt(key, pt):
    plaintext = read_file(pt)
    if isinstance(plaintext, str):
        pt= plaintext.encode("utf-8")

    if len(key) <= key_bytes:
        for x in range(len(key),key_bytes):
            key = key + "0"

    assert len(key) == key_bytes
    
    # Choose a random, 16-byte IV.
    iv = Random.new().read(AES.block_size)

    # Convert the IV to a Python integer.
    iv_int = int(binascii.hexlify(iv), 16)

    # Create a new Counter object with IV = iv_int.
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)

    # Create AES-CTR cipher.
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

    # Encrypt and return IV and ciphertext.
    ciphertext = aes.encrypt(pt)
    return (iv, ciphertext)

问题排查与修复

1. 加密函数read_file逻辑错误

加密函数第一行plaintext = read_file(pt)默认将输入的pt当作文件路径读取,若调用时传入的是明文字符串(如SandI2021),实际加密的是文件内容(文件不存在则为错误数据),而非预期明文,导致解密结果不符。

修复方案:修改加密函数,支持直接传入明文或文件路径:

def encrypt(key, pt):
    # 尝试读取文件,失败则将pt视为明文
    try:
        with open(pt, 'r', encoding='utf-8') as f:
            plaintext = f.read()
    except (FileNotFoundError, IsADirectoryError):
        plaintext = pt

    if isinstance(plaintext, str):
        pt = plaintext.encode("utf-8")

    # 用ljust简化密钥补0逻辑,替代循环
    key_bytes = 16  # 需与AES密钥长度匹配:16(AES-128)/24(AES-192)/32(AES-256)
    key = key.ljust(key_bytes, '0')
    assert len(key) == key_bytes
    
    iv = Random.new().read(AES.block_size)
    iv_int = int(binascii.hexlify(iv), 16)
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)
    ciphertext = aes.encrypt(pt)
    return (iv, ciphertext)

2. 解密函数缺失密钥补全逻辑

加密函数会对长度不足的密钥补0,但解密函数直接断言密钥长度等于key_bytes,若解密时传入原始短密钥会触发错误,且无法与加密流程匹配。

修复方案:让解密函数与加密函数保持一致的密钥补全逻辑:

def decrypt(key, iv, ciphertext):
    key_bytes = 16  # 与加密函数的key_bytes值一致
    key = key.ljust(key_bytes, '0')
    assert len(key) == key_bytes                                                                 

    iv_int = int(binascii.hexlify(iv), 16)
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)

    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)
    plaintext = aes.decrypt(ciphertext)
    return plaintext

3. 验证输入一致性

确保解密使用的密钥、IV、密文完全匹配加密输出:

  • 手动输入的IV/密文可能存在字节转义错误,建议通过加密函数生成对应值后再测试;
  • 运行以下测试代码验证流程:
# 依赖导入需确保齐全
from Crypto.Cipher import AES
from Crypto.Util import Counter
from Crypto.Random import Random
import binascii

# 测试加解密流程
key = "maru000000000000"
expected_plaintext = "SandI2021"

# 加密生成IV和密文
iv, ciphertext = encrypt(key, expected_plaintext)
# 解密验证
decrypted_data = decrypt(key, iv, ciphertext)
print(f"解密结果: {decrypted_data.decode('utf-8')}")  # 应输出SandI2021

内容的提问来源于stack exchange,提问作者PyhonLovers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 14:12:26