我一直在尝试将这个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?
答案 0 :(得分:1)
鉴于您的初始化向量是在第一个示例中随机创建的,因此输出看起来不同,加密和Base 64编码也就不足为奇了。重要的是你可以可靠地解码和解密。
此外,你的python代码看起来根本不像是使用初始化向量(除非库默认使用它,在这种情况下,它们不是)。这意味着您将不会使用密码块链接,因此不如PHP示例安全。
未编码输出的前几个字节传统上是初始化向量,接收方知道其长度,然后用于初始化解密过程。
看起来Python 2.x库并不是特别有用,请参阅this example here。 Python 3似乎有你需要的here。
此外,对于块大小,使用16作为AES标准(参见here),32将无效。
答案 1 :(得分:1)
你必须使用相同的东西:
块大小(Rijndael支持不同的块大小,必须使用相同的块)
BLOCK_SIZE = 16
填充(PKCS#7填充垫,其中包含表示填充字节数的字节)
padbyte = BLOCK_SIZE - len(plaintext) % BLOCK_SIZE
padded_text = plaintext + padbyte * chr(padbyte)
安全注意事项:
永远不要使用ECB模式。这是非常不安全的。使用随机IV至少使用CBC模式。 IV不必是秘密的,因此您可以将其添加到密文并在解密之前将其切片。
验证您的密文:使用加密然后MAC方案来保护您的密文(使用强大的MAC,如HMAC-SHA256)进行(恶意)修改,或者使用经过身份验证的模式,如GCM。