【问题标题】:how to make correctly way AES.encrypt contain control character in Python3如何正确地使 AES.encrypt 包含 Python3 中的控制字符
【发布时间】:2021-02-01 23:57:45
【问题描述】:

我要将加密逻辑从 php 更改为 python3。

原始代码有填充ascii的逻辑,我把它带进了我的python代码。

来自

function toPkcs7 ($value)
{
    $padSize = 16 - (strlen ($value) % 16) ;
    return $value . str_repeat (chr ($padSize), $padSize) ;
}

def to_pkcs7(s):
    padding_size = 16 - (len(s) % 16)
    return s + (chr(padding_size) * padding_size)

但是当 to_pkcs7 有 11 个字符(例如“12345678901”)并且返回结果包含控制字符(例如 12345678901\x05\x05\x05\x05\x05,chr(5) 表示 ENQ \x05)时,两个加密器的工作方式不同。

我认为结果的控制字符在 python3 的 AES 中被忽略了。 因为php toPkcs7python3 to_pkcs7 返回的字符串长度相同。

例如

# in php
$message = toPkcs7($message);
echo strlen($message);  # 16
$encrypted = openssl_encrypt($message, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);

# in python3
message = to_pkcs7(message) 
print(len(message))  # 16
cipher = AES.new(key, AES.MODE_CBC, iv())
encrypted = cipher.encrypt(message.encode("utf-8"))

我想知道如何让我的 python 代码像 php 一样工作。

【问题讨论】:

    标签: python php python-3.x encryption


    【解决方案1】:

    在发布的 PHP 代码中,填充了两次,这是不必要的(实际上甚至是一个错误)。

    填充的目的是明文的长度是块大小的整数倍(AES 为 16 字节),这是块密码的要求。这已经通过第一个填充实现,即第二个填充是无用的。它只会导致附加(此处)具有 0x10 值的(冗余)完整块,这会不必要地膨胀密文。

    为了使用 Python 代码获得双填充明文的密文,还需要简单的双填充:

    message = to_pkcs7(to_pkcs7(message)) 
    

    要在 PHP 代码中只填充一次,请注意以下几点:openssl_encrypt() 隐式使用 PKCS7 填充,即自定义填充不是必需的,因此只需删除即可。但是,如果应该应用自定义填充,则只需禁用隐式填充(通过设置 OPENSSL_ZERO_PADDING 标志)。两种变体提供相同的结果。

    顺便说一下,PyCryptodome(与旧版 PyCrypto 不同)在专用的 module 中支持 PKCS7。

    【讨论】:

    • 你太棒了!!它使用双填充。我会检查 PyCryptodome 。谢谢!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 2016-05-21
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多