【问题标题】:How to use OpenSSL to decrypt a value generated with Mcrypt that has used an ASCII key?如何使用 OpenSSL 解密使用 ASCII 密钥的 Mcrypt 生成的值?
【发布时间】:2018-01-18 06:00:12
【问题描述】:

我需要能够使用 OpenSSL 解密在 PHP 下使用 Mcrypt 生成的值。

我有这个工作,除了用于加密它们的密钥是 ascii。

以下是我的代码,演示了一个工作案例,当密钥为 MD5 时,OpenSSL 可以解密使用 Mcrypt 加密的值。

<?php
$message = 'test';
$key = md5('Quigibo');

$iv = openssl_random_pseudo_bytes(0);

$encrypted = mcrypt_encrypt(
    MCRYPT_BLOWFISH,
    $key,
    $message,
    MCRYPT_MODE_ECB,
    $iv
);

$decrypted = openssl_decrypt(
    $encrypted,
    'bf-ecb',
    $key,
    OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,
    $iv
);

$trimDecrypted = rtrim($decrypted);

var_export(
    [
        'Original message' => $message,
        'Encrypted' => bin2hex($encrypted),
        'Decrypted' => $decrypted,
        'Trim decrypted' => $trimDecrypted,
        'Message length' => mb_strlen($message, '8bit'),
        'Decrypted length' => mb_strlen($decrypted, '8bit'),
        'Message == decrypted' => $message === $trimDecrypted
    ]
);

但是,如果您将 $key 更改为值“Quigibo”(而不是该值的 MD5 散列),则无法使用 OpenSSL 解码加密值。

在与 OpenSSL 一起使用之前,我是否可以对 ASCII 密钥应用某种编码形式,以便正确解密该值?

【问题讨论】:

标签: php openssl mcrypt


【解决方案1】:

修改后的答案:

OpenSSL 中有一个错误,它会将 Blowfish 的密钥填充为 16 个字节,这是不正确的,因为密码支持可变长度密钥。他们最近添加了一个标志来解决这个问题 - OPENSSL_DONT_ZERO_PAD_KEY - 但它仅在一周前发布的 php 7.1.8 中可用......相关错误:https://bugs.php.net/bug.php?id=72362

一种解决方法是手动循环密钥并将其输入 OpenSSL:

$keylen = (floor(mb_strlen($key, '8bit')/8)+1)*56;
$key_cycled = substr(str_repeat($key,ceil($keylen/strlen($key))),0,$keylen);

$decrypted = openssl_decrypt(
$encrypted,
'bf-ecb',
$key_cycled,
OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,
$iv
);

【讨论】:

  • 使用 16 个字符或更多字符的密钥将起作用。不幸的是,我的钥匙少了。如果我用"\0" 填充短键,它不起作用(str_pad($key, $pad, chr(0))))我尝试了各种填充值但没有成功,这让我认为它要么没有填充,要么填充了 null 以外的东西。
  • 您使用的是哪个版本的 mcrypt?如果您使用的版本太新,那么它将返回 FALSE 并拒绝在上面的测试代码中对数据进行加密。
  • 也许添加 OPENSSL_DONT_ZERO_PAD_KEY 将帮助您强制 OpenSSL 使用确切的密钥大小(相关:bugs.php.net/bug.php?id=72362bugs.php.net/bug.php?id=71917)刚刚发现这个 SO 帖子表明 mcrypt 没有密钥-河豚的填充行为,因为它支持可变长度键:stackoverflow.com/questions/16331928/…
  • 不幸的是,OPENSSL_DONT_ZERO_PAD_KEY 仅在一周前发布的 php 7.1.8 中... 16字节,然后用openssl用未填充的密钥解密,它可以工作。
  • 我可以确认 openssl 会自动填充密钥,而 mcrypt 不会填充。这意味着当密钥小于 16 个字节时,在释放 OPENSSL_DONT_ZERO_PAD_KEY 之前不可能使用 openssl 解密。如果您使用这些细节修改您的答案,我很乐意将其标记为已接受的答案。我自己不会想到这一点,并感谢您的努力。
猜你喜欢
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 2019-04-13
  • 2021-02-22
  • 2017-07-05
  • 2020-07-23
相关资源
最近更新 更多