我没有太多要添加到Maarten's answer 的内容,但我认为展示一些说明他的话的代码会很好。
mcrypt 加零以将明文填充为 8 字节的 BF 块大小的倍数,这可以通过打印明文和解密密文的十六进制转储来显示:
$key = "supersecretkey";
$data = "foobar";
$ctxt = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_ECB);
$ptxt = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $ctxt, MCRYPT_MODE_ECB);
echo bin2hex($data).PHP_EOL;
echo bin2hex($ptxt).PHP_EOL;
提供以下十六进制转储:
666f6f626172
666f6f6261720000
openssl 默认使用 PKCS#5 填充,在这种情况下,在块的末尾添加 2 个字节,值为 2:
$key = "supersecretkey";
$data = "foobar";
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY;
$ctxt = openssl_encrypt($data, 'BF-ECB', $key, $opts);
$ptxt = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $ctxt, MCRYPT_MODE_ECB);
echo bin2hex($data).PHP_EOL;
echo bin2hex($ptxt).PHP_EOL;
给予
666f6f626172
666f6f6261720202
mcrypt 和openssl 的密文可以通过手动添加填充字节来保持一致。注意OPENSSL_ZERO_PADDING 选项和"\0\0" 的添加:
$key = "supersecretkey";
$data = "foobar";
$ctxt_mc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_ECB);
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY | OPENSSL_ZERO_PADDING;
$ctxt_os = openssl_encrypt($data."\0\0", 'BF-ECB', $key, $opts);
echo bin2hex($ctxt_mc).PHP_EOL;
echo bin2hex($ctxt_os).PHP_EOL;
给予:
e73d2adf1367a24c
e73d2adf1367a24c
或者,当使用mcrypt 时,在末尾手动插入 PKCS#5 填充字节:
$key = "supersecretkey";
$data = "foobar";
$ctxt_mc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data."\2\2", MCRYPT_MODE_ECB);
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY;
$ctxt_os = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo bin2hex($ctxt_mc).PHP_EOL;
echo bin2hex($ctxt_os).PHP_EOL;
给予
d73caa6afabbb029
d73caa6afabbb029
最后,尝试在禁用填充且长度不是块大小倍数的情况下调用 openssl_encrypt():
$key = "supersecretkey";
$data = "foobar";
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY | OPENSSL_ZERO_PADDING;
$ctxt = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo(openssl_error_string().PHP_EOL)
给予
error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length
备注:OPENSSL_ZERO_PADDING 这个名字很混乱,但它的意思是“没有填充”。您可能很想使用标志OPENSSL_NO_PADDING,但该标志不打算与openssl_encrypt() 一起使用。其值为3,与OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING 相同。相反,it is intended for use with asymmetric cryptography。