将此php加密函数转换为python
Posted
技术标签:
【中文标题】将此php加密函数转换为python【英文标题】:Convert this php encryption function to python 【发布时间】:2015-09-23 11:06:20 【问题描述】:我一直在尝试将这个php函数改成python,但无济于事。
public static function encode($text, $KEY)
$pkcs5text= self::pkcs5_pad($text,16);
$size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($size, MCRYPT_RAND);
$bin = pack('H*', bin2hex($pkcs5text) );
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $KEY, $bin, MCRYPT_MODE_ECB, $iv);
return base64_encode($encrypted);
我的 Python 脚本如下
import rijndael
import base64
KEY_SIZE = 16
BLOCK_SIZE = 32
def encrypt(key, plaintext):
padded_key = key.ljust(KEY_SIZE, '\0')
padded_text = plaintext + (BLOCK_SIZE - len(plaintext) % BLOCK_SIZE) * '\0'
# could also be one of
#if len(plaintext) % BLOCK_SIZE != 0:
# padded_text = plaintext.ljust((len(plaintext) / BLOCK_SIZE) + 1 * BLOCKSIZE), '\0')
# -OR-
#padded_text = plaintext.ljust((len(plaintext) + (BLOCK_SIZE - len(plaintext) % BLOCK_SIZE)), '\0')
r = rijndael.rijndael(padded_key, BLOCK_SIZE)
ciphertext = ''
for start in range(0, len(padded_text), BLOCK_SIZE):
ciphertext += r.encrypt(padded_text[start:start+BLOCK_SIZE])
encoded = base64.b64encode(ciphertext)
return encoded
两个脚本都从彼此不同的同一消息生成编码文本。我不确定我哪里出错了。如何在 rijndael 128 之上将 mcrypt 实现到 python 中?
【问题讨论】:
我尝试了你的代码,但它给了我错误“AttributeError: module 'rijndael' has no attribute 'rijndael'” 这是为“rijndael.rijndael(padded_key, BLOCK_SIZE)”行给出的错误 【参考方案1】:你必须使用相同的:
块大小(Rijndael 支持不同的块大小,必须使用相同的大小才能兼容)
BLOCK_SIZE = 16
padding(PKCS#7 用代表填充字节数的字节填充)
padbyte = BLOCK_SIZE - len(plaintext) % BLOCK_SIZE
padded_text = plaintext + padbyte * chr(padbyte)
安全注意事项:
永远不要使用 ECB 模式。这是非常不安全的。至少使用随机 IV 的 CBC 模式。 IV 不必保密,因此您可以将其添加到密文中并在解密之前将其切掉。
验证您的密文:使用 encrypt-then-MAC 方案来保护您的密文免受(恶意)修改,使用 HMAC-SHA256 等强 MAC 或使用 GCM 等验证模式。
【讨论】:
感谢您的解决方案有效。但我仍然不明白我的初始填充脚本有什么问题 您使用 \0 作为填充字符。 PKCS5Padding bytes 包含填充字节数。【参考方案2】:鉴于您的初始化向量在第一个示例中是随机创建的,因此输出看起来不同的加密和 Base 64 编码也就不足为奇了。重要的是您可以可靠地解码和解密。
此外,您的 python 代码看起来根本没有使用初始化向量(除非库默认这样做,在这种情况下,它们不是)。这意味着您不会使用密码块链接,因此安全性低于 PHP 示例。
您的未编码输出的前几个字节传统上是初始化向量,接收方知道其长度,然后用于初始化解密过程。
看起来 Python 2.x 库并不是特别有用,请参阅 this example here。 Python 3 似乎有你所需要的here。
此外,对于块大小,请使用 16,因为它是 AES 标准(请参阅 here),32 将不起作用。
【讨论】:
以上是关于将此php加密函数转换为python的主要内容,如果未能解决你的问题,请参考以下文章
中文字符串C++MD5加密结果与PHP的加密结果不一致,怎么办