当前位置: 首页 > 知识库问答 >
问题:

以SagePay形式将mcrypt升级为OpenSSL加密

欧阳飞章
2023-03-14

我有一个收集数据的表单,然后提交给SagePay,传递数据。在我们需要更新到PHP 7.2之前,这一直工作得很好,由于不再支持mcrypt,我们正在切换到OpenSSL。

收集数据的表单工作正常,但是传输数据不加密,交易失败。

函数文件中的代码

$protx_encryption_password      = "my_password";
$protx_vendor                   = "my_vendor";

$data = "";
while(list($key,$value) = each($protx)) {
    $data .= $key."=".$value."&";
}
$data = trim($data," &");

$crypt = openssl_encrypt($data, $protx_encryption_password);

function openssl_encrypt($string, $key) {
    $iv = substr($value, 0, 16);
    $ciphertext = substr($value, 16);
    $key = hash('sha256', $key, true);
    $crypt = openssl_encrypt(
        $ciphertext, 'AES-256-CBC', $key, 
        OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, 
        $iv
    );
    return rtrim($crypt, "\0");
}

$crypt数据在mcrypt版本中一样在隐藏字段中发送,我只需要一些帮助即可使加密正常工作。

前情提要。

$crypt = encryptAes($data, $protx_encryption_password);

function encryptAes($string, $key) {
// AES encryption, CBC blocking with PKCS5 padding then HEX encoding.
// Add PKCS5 padding to the text to be encypted.
$string = addPKCS5Padding($string);

// Perform encryption with PHP's MCRYPT module.
$crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key);

// Perform hex encoding and return.
return "@" . strtoupper(bin2hex($crypt));
}

function addPKCS5Padding($input) {
    $blockSize = 16;
    $padd = "";

    // Pad input to an even block size boundary.
    $length = $blockSize - (strlen($input) % $blockSize);
    for ($i = 1; $i <= $length; $i++)
    {
        $padd .= chr($length);
    }

    return $input . $padd;
}

这是我做的第一个OpenSSL加密,如果有任何帮助,我将不胜感激。SagePay需要使用PCKS#5(AES-128-CBC-PKCS#5)在CBC模式下使用128位块大小的AES-128加密进行加密。任何帮助都将非常有帮助。

共有1个答案

姜景焕
2023-03-14

首先,这是一个糟糕的计划。使用(真实)密码作为现代密码学的密钥,即使在可能的情况下,也几乎总是不安全的。密码和密钥是不同的东西,以不同的方式设计和指定。当然,一些不知道自己在做什么的人会把一个实际上是密钥的东西称为密码,而且由于我不知道SagePay(当然你没有给出真正的价值),我不知道这里的情况是否如此。此外,将密钥(或密码)用作IV是完全不标准的。IV的全部意义在于给定密钥下的每个加密(或至少每个数据值)都是不同的,而给定的密钥根据定义与自身相同。这太愚蠢了,我不记得看到过任何关于它是否以及它引起的攻击的分析,尽管作为一般规则,违反“安全合同”通常会导致问题。对IV使用任何固定值,这是一个相当常见的错误,对于CBC模式来说只是中等程度的坏处,尽管对于其他一些模式来说要糟糕得多。

然而,你显然没有选择改变这个方案,如果你做了,它将不是一个真正的编程问题,而是属于security.SX或者crypto.SX。

另外,仅供参考,说“具有128位块的AES-128”毫无意义。AES总是使用128位块;这是建立它的竞争规则的一部分。Rijndael确实有其他块大小的选项,这就是为什么实现Rijndael或多或少的mcrypt指定块大小,但OpenSSL实现了AES,它不需要也不指定块大小——只指定密钥大小。

其次,你提出的新代码是无稽之谈。首先,你尝试重新定义一个标准函数,这是不允许的,然后你提出的html" target="_blank">逻辑显然是为了解密而不是加密一个本质上不同的方案而设计的,而不是你提出的方案,然后被破坏。

<code>mcrypt_encrypt</code>零填充明文,在旧版本中,根据需要填充密钥和iv。对于Rijndael,它还根据提供的密钥选择密钥大小;因为您说您想要AES-128(即128位密钥),所以所谓的“密码”不能超过128位,但可以少于128位。您发布的代码对数据进行了显式的PKCS5填充,因此不使用mcrypt的零填充,正如Peter所评论的,openssl_encrypt(以及它下面使用的openssl例程)默认情况下进行PCKS5/7填充,因此您只需要:

function encryptAes_new ($string, $key) {
  $key = str_pad($key,16,"\0"); # if supplied key is, or may be, less than 16 bytes
  $crypt = openssl_encrypt($string, 'aes-128-cbc', $key, OPENSSL_RAW_DATA, $key);
  // Perform hex encoding and return.
  return "@" . strtoupper(bin2hex($crypt));
}

(注意:原始 PKCS5 填充仅处理 64 位/8 字节块,PKCS7 将其扩展到其他大小,但 PKCS5v2.1 在 2017 年也扩展了它,引用了 CMS,这是 PKCS7 的 IETF 版本,因此它们现在是相同的。

 类似资料:
  • 问题内容: 我正在使用以下通常引用的库进行加密。我想将其从Mcrypt升级到OpenSSL,以便不再使用不推荐使用的库。 更新:我一直在尝试通过将库转换为OpenSSL来解密使用OpenSSL使用Mcrypt加密的字符串。 然后,我使用上面的代码使用密钥对字符串加密,并尝试使用下面的代码和相同的密钥解密该值。但是我只是得到一个空白的答复。如果我注释掉: $ data = $ this-> unpa

  • 我正在使用以下函数通过Qt中的OpenSSL库加密我的数据: “源”在“123456789012345678901234567890123456789012ABC”中。 “密码”为“1HA!DH==SJAH48S8AK!?SKIITFI120XX”。 所以...如果我正确的话,那么EVP_BytesToKey()应该从密码中生成一个密钥,并提供数据以在后面解密字符串。 对base64编码的密钥是:

  • 由于 mcrypt 被认为是过时的,我的任务是升级当前代码以使用 openssl。听起来很简单,但是...经过几天的尝试和失败,我觉得自己疯了。 我的问题是:有什么方法可以用以前用mcrypt加密的openssl数据解密吗?我读过很多关于这个问题的帖子,大多数帖子都说,在运行mcrypt之前,需要对数据进行手动填充。问题是,mcrypted数据已经加密(使用mcrypt提供的自动空填充),并驻留在

  • 或者唯一的方法是运行一个脚本,它将用mcrypt解密我存储的所有加密数据,并用openssl编码? 谢谢

  • 在我将我的系统从Ubuntu 13.04升级到13.10之后,apache、mysql和php配置出现了几个问题。 我解决了大部分问题,但我似乎无法让mCrypt库正常工作。软件包已安装,因此我不需要获取它。服务器工作正常,一切正常,但当我尝试使用Laravel4运行时,我得到一条消息,需要mCrypt。 我做了,输出是我尝试把到但是它没有工作。 有什么想法吗?

  • 在postgres中,如何将现有用户更改为超级用户?由于各种原因,我不想删除现有用户。