3DES PHP 即使在末尾添加一个字符也能解密相同的结果

3DES PHP decrypts same result even if a char is added at the end

所以我正在使用这个 class 来加密或解密数据:

class CryptData
{
    private $hash;
    function __construct($hash) {
        $key = md5($hash, true);
        $key .= substr($key, 0, 8);
        $this->hash = $key;
    }
    public function Encrypt($data)
    {
        $encData = openssl_encrypt($data, 'DES-EDE3', $this->hash, OPENSSL_RAW_DATA);
        return base64_encode($encData);
    }
    public function Decrypt($data)
    {
        $data = base64_decode($data);
        return openssl_decrypt($data, 'DES-EDE3', $this->hash, OPENSSL_RAW_DATA);
    }
}

它工作正常,但是例如,如果我使用:

hash = 12345
text = 1234567891234567

然后加密然后结果

decData = LQ1zff+UiAAs6GXEgA5x6beMPOubhpcA

现在,如果我尝试将此数据解密回纯文本,那么它会给出正确的结果,但即使我在 decData 的末尾添加任何字符,如

decData = LQ1zff+UiAAs6GXEgA5x6beMPOubhpcAa

令人惊讶的是它也给出了正确的纯文本..!! 经过几次测试后我注意到,decData 末尾没有“=”,如果我添加一个字符,那么它将解密为文本而不会出错。 例如,如果我尝试

hash = 12345
text = 12345

那么结果就是

decData = CQm/ZBYSrrs=

现在如果我解密这个在末尾添加一个字符就会出错。

总而言之,当我尝试加密长度为 16 或更长的文本时,解密数据中没有“=”。我对此没有任何问题,但如果我尝试解密在末尾添加任何字符的解密数据,它会返回正确的文本。

为什么会这样,我的数据是否存在与此相关的安全问题?

Base64 用于将二进制数据编码为文本,其中每个 Base64 字符代表 6 位。每 3 个字节(24 位)的输入给出 4 个 Base64 个字符。在输入长度不是 3 的倍数的情况下,Base64 的最后一个块用一个或两个 '='

填充

Base64 编码数据需要在 4 个 Base64 字符块中才有效 Base64.似乎 php 的 base64_decoder(..) 只是忽略了您最后一个无效的 Base64 字符。您可以使用以下代码查看:

echo strlen(base64_decode("LQ1zff+UiAAs6GXEgA5x6beMPOubhpcA"));
echo "\n";
echo strlen(base64_decode("LQ1zff+UiAAs6GXEgA5x6beMPOubhpcAa"));

给予:

24
24