每个人都应该已经停止使用PHP Mcrypt扩展程序进行新的工作,并且应该计划将其现有的应用程序关闭,因为libmcrypt在2003年被放弃,并且不被保护。
我认为最好的选择是OpenSSL。近年来热度很高,但我认为对称块加密是一个很好的选择。 (我可能会解释为什么我这么想呢)
PHP中的 openssl_encrypt()
和openssl_decrypt()
的文档有点缺乏。本文旨在填补一些空白。这是两者的签名。
string openssl_encrypt ( string $data , string $method , string $password [, int $options = 0 [, string $iv = "" ]] ) string openssl_decrypt ( string $data , string $method , string $password [, int $options = 0 [, string $iv = "" ]] )
我们将始终使用一个初始化向量,结果是$options
有很大的不同,所以我们可以简化:
string openssl_encrypt ( string $data , string $method , string $password , int $options, string $iv ) string openssl_decrypt ( string $data , string $method , string $password , int $options, string $iv )
其中$opention
将是OPENSSL_RAW_DATA
或OPENSSL_ZERO_PADDING
## $password
参数是加密密钥
$password
参数名称非常误导。它不是密码,它是一个加密密钥。openssl enc
命令行实用程序将接受密码或密钥将执行密钥导出和盐析,如果你想要的。但这些PHP函数希望$password
成为加密密钥。
它们还需要为您使用的密码算法准备好密钥。我只使用密钥大小为16字节的AES-128。如果您通过openssl_en/decrypt()
一个密钥(在$ password参数中)长于密码的本质密钥大小,则会将该余数丢弃。如果通过一个短于预期的键,则填充为零,即\x00
字节。
所以你需要仔细准备你的钥匙。如果用户提供密码,请使用类似PBKDF2的特殊盐。如果您有输入加密密钥,则可以使用HKDF导出openssl_en/decrypt()
的密钥。
所以让我们再简化一下:
string openssl_encrypt ( string $data , string $method , string $key , int $options, string $iv ) string openssl_decrypt ( string $data , string $method , string $key , int $options, string $iv )
如果您正在生成密钥,而不是从用户输入密钥或密码中导出密钥,则应使用从加密安全伪随机数生成器或CSPRNG中提取的随机字节的二进制字符串.(我也许会博客介绍如何在PHP中获取这样的字符串,实际上并不像调用openssl_random_pseudo_bytes()
一样简单。)
初始化向量 $iv
初始化向量$ iv的要求类似于$password
的要求。它应该是与密码块大小相同长度的二进制字符串。过多的字节被丢弃,并且太短的$ iv被填充到零字节的块大小。
初始化向量应该是来自CSPRNG的随机字节的二进制串。不要重复使用IV。
密码规范 $method
$method
允许值由PHP平台上的openssl_get_cipher_methods()
函数列出,并在openssl enc文档中更详细地列出。
我不打算讨论这些的相对优点。我唯一使用的是CBC模式的AES。除了RC5(由RAS获得专利但未被广泛使用)外,OpenSSL提供的所有其他对称块密码都具有64位或更小的块。
我总是使用AES-128,它有一个16字节的键。所以这意味着我会选择“AES-128-CBC”。我想你可以安全地选择’AES-192-CBC’或’AES-256-CBC’,但是我不会被引用到最好的论点。
在任何情况下,$method
都必须是openssl_get_cipher_methods()
返回的字符串之一,您必须使用适当长度的$ iv和$ key才能使用该密码。
编码、填充和OPENSSL_RAW_DATA与OPENSSL_ZERO_PADDING
在Mcrypt
中,加密和解密的输入和输出编码是原始的二进制字符串。 Paintext
和ciphertext
都是二进制字符串。
在CBC
或ECB
模式下使用块密码加密之前,Mcrypt
会自动将零字节填充添加到明文中,并在解密之后返回零字节填充的明文(即,Mcrypt
在解密之后不删除填充)。
注意:以下是错误,请参阅下面My1的注释。选项表示两个标志:将
OPENSSL_RAW_DATA
位设置为使用二进制字符串,并将其设置为base64。设置OPENSSL_ZERO_PADDING
位来进行自己的填充或取消设置,openssl_en/decrypt()
做PKCS7填充。
OpenSSL有两种模式:
– $options = OPENSSL_RAW_DATA
– openssl_encrypt()
和openssl_decrypt()
的输入和输出编码都是二进制字符串,即plaintext
和cipertext
都是二进制字符串。
– openssl_encrypt()
在CBC或ECB模式下使用块密码加密之前,将PKCS7填充添加到明文中。
– openssl_decrypt()
解密之后剥离填充。
– 如果$ options = OPENSSL_ZERO_PADDING则
– openssl_encrypt()
的输入编码和openssl_decrypt()
的输出编码是原始的二进制字符串,即明文是原始的二进制字符串。
– 输出编码fron openssl_encrypt()
和对openssl_decrypt()
的输入编码是base64,即密文是base64编码的。
– openssl_encrypt()
的输入大小必须是块大小的整数倍,否则返回错误代码。
– openssl_encrypt()
不添加填充,或者由openssl_decrypt()
删除,
可以做任何工作,但我更喜欢OPENSSL_RAW_DATA
。如果我需要密文的特定编码,那我宁愿自己做。而PKCS7将是我的填充选择,实际上这是我用于Mcrypt
的。
总结
已经弄清了这两个功能的所有这些未记录的功能,结果是我打算使用OpenSSL进行对称加密的唯一方法是这样的:
$ciphertext = openssl_encrypt($plaintext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); $plaintext = openssl_decrypt($ciphertext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
其中:
– $plaintext
是任何字符串,任何长度。
– $key
是16字节长的二进制字符串形式的加密密钥(因为AES-128的密钥大小为16字节)
– $iv
是一个16位字节长的加密安全随机二进制字符串(因为AES具有16个字节的块大小),我将只使用一次
– $ciphertext
是一个比$plaintext
长1到16个字节之间的二进制字符串(因为PKCS7填充到16字节块大小)
并记住加密密钥必须从输入密钥材料或密码中正确派生或由CSPRNG生成。
结语
记住,如果您需要加密数据,那么您几乎肯定也需要进行身份验证。为此,您可以使用HMAC签名。使用SHA-2
算法之一。 还要记住最后签名并进行认证,即HMAC需要覆盖包含加密数据的整个消息
原文 http://thefsb.tumblr.com/post/110749271235/using-opensslendecrypt-in-php-instead-of
第 压力机页
10 7月 2017您好,您的网站做的很不错,很漂亮,我已经收藏了
第 卷板机页
2 9月 2017学习了 谢谢博主的分享
第 校平机页
8 11月 2017不错的文章谢谢提供
第 天天页
15 11月 2017实用
第 剪板机折弯机页
20 12月 2017可以去试试
第 智能手机页
12 1月 2018文章不错支持一下吧
通告: php如何openssl_encrypt加密解密 – 1
第 丘八页
26 2月 2019文章不错,非常喜欢
第 trwtr页
21 8月 2019trhbsrhb
第 CommandNotFound-坑否页
20 9月 2019不错!!!