PHP mcrypt 到 Python

Posted

技术标签:

【中文标题】PHP mcrypt 到 Python【英文标题】:PHP mcrypt to Python 【发布时间】:2017-10-14 19:30:55 【问题描述】:

我正在尝试将 php 加密函数转换为 Python。为了示例方便,我们预先设置了iv和相关数据。

$salt = sha1('12345'.'654321'); 
encrypt('12345678', 'cutekittens12345', $salt);

function encrypt($decrypted, $password, $salt)

    // Build a 256-bit $key which is a SHA256 hash of $salt and $password.
    $key = hash('SHA256', $salt . $password, true);
    $hexkey = hash('SHA256', $salt . $password, false);
    // Build $iv and $iv_base64.  We use a block size of 128 bits (AES compliant) and CBC mode.  (Note: ECB mode is inadequate as IV is not used.)
    #$iv = mcrypt_create_iv(16, MCRYPT_RAND);
    $iv = "0000000000000000";
    if (strlen($iv_base64 = rtrim(base64_encode($iv), '=')) != 22)
        return false;
    // Encrypt $decrypted and an MD5 of $decrypted using $key.  MD5 is fine to use here because it's just to verify successful decryption.
    $concatdecrypted = ($decrypted . md5($decrypted));
    $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $concatdecrypted, MCRYPT_MODE_CBC, $iv));
    // We're done!
    return $iv_base64 . $encrypted;

结果

$salt: 6ed52d21d5cc15e76e9879675f4bd0dd51593652
$hexkey: 879522bb98c1f5fb16acd6bf3454b0d4e313e8b71e0aa3cdf5cbf91158dfde71
$iv_base64: MDAwMDAwMDAwMDAwMDAwMA
$concatdecrypted: 1234567825d55ad283aa400af464c76d713c07ad 
$encrypted: C3CWJPt2gtmg+id1ySmSazMvvWC7cgDpovJ/tDN0GeuVv9Pf/9+9ZSG+wjl6qD5h

我最干净的重新创建函数的尝试是here 并且:

from base64 import b64encode, b64decode
from Crypto.Cipher import AES
import hashlib

charid = "654321"
apikey = "12345"
vcode = "12345678"
password = "cutekittens12345"

salt = hashlib.sha1((apikey + charid).encode('utf-8')).hexdigest()
key = hashlib.sha256(salt + password).digest()
iv = "0000000000000000"
concatkey = vcode + hashlib.md5(vcode).hexdigest()

AES.key_size=128
encryptor=AES.new(key=key,mode=AES.MODE_CBC,IV=iv)
encoded = encryptor.encrypt(concatkey_pad)
encoded = b64encode(encoded)

print 'Encrypted string:', encoded

我可以重新创建除了最终结果之外的所有内容。我尝试了 unhex 的组合,看看它是否与传递原始输入有关,但没有一个 $encrypted 结果匹配。

任何帮助将不胜感激。

【问题讨论】:

不要提供代码链接。相反,edit 你的问题包括代码。链接总是断开,如果断开,这个问题将失去所有价值。 很可能是填充问题。我会假设 Python 库应该使用 PKCS5Padding。 Mcrypt 没有。您应该修改您的 PHP 以使用 openssl_encrypt 函数。 【参考方案1】:

我尝试了 M2Crypto、Crypto.Cipher 和 pyDes。在阅读'Lessons learned implementing AES in PHP using Mcrypt' 之后,我在用 ascii 0 填充字符串以绕过 16 的倍数问题后使用 Crypto.Cipher 取得了成功,并且编码字符串的前半部分与我的 php 函数匹配。

concatkey_pad = concatkey.ljust(48, '\0')
AES.key_size=128
encryptor=AES.new(key=key,mode=AES.MODE_CBC,IV=iv)
encoded = encryptor.encrypt(concatkey_pad)
encoded = b64encode(encoded)

print 'Encrypted string:', encoded

使用二进制 0 填充 concatkey 刚刚生成正确的编码值。

【讨论】:

@LukePark 虽然这可能是真的,但我的目标是重新创建已弃用的 PHP 函数的功能,作为更大项目的一部分,以适应未来的发展。出于临时向后兼容的原因,我只是需要这个函数。

以上是关于PHP mcrypt 到 Python的主要内容,如果未能解决你的问题,请参考以下文章

PHP mcrypt 到 Python

更新到 php 5.6.2 时的 mcrypt 警告;不支持大小为 x 的密钥

在升级到 PHP 5.4.33 的 Centos VPS 上安装 mcrypt 扩展时出错

我要安装php的mcrypt扩展

将 Crypto++ AES 加密移植到 PHP 的 mcrypt 时密钥大小不正确

windows 下php5 开启 mcrypt