openssl_encrypt函数的PHP文档说明
string openssl_encrypt(string $ data,string $ method,string $ password [,int $ options = 0 [,string $ iv =“”]])
有人可以帮我理解名为$password
的论点是什么吗?
答案可能包括确认或拒绝该想法,除了命名$password
之外,参数确实被用作加密的密钥。
openssl_encrypt
的密码参数是什么?它是一个密码字符串(只有可打印的字符)还是一个密钥(具有不可打印的字符和ASCII-Z终结符)?
我坚持使用PHP openssl_encrypt的文档。作为一个好人,并尝试做“RTM”我对imho不满意的文档没有多大意义。
问题在于,对于我来说,加密时密码和密钥之间存在差异。密钥直接是用于加密的参数,因此必须具有特定大小 - “密钥长度” - 即128/256/512位,取决于所需的密码和密钥长度。另一方面,密码是我理解通过键盘输入的人类可读字符串,它可能有任何长度,并且在用于加密之前首先转换为键
因此示意性差异:
不幸的是在PHP openssl_encrypt documentation中我找不到任何有关如何使用密钥的信息。唯一建议的是参数“密码”。
任何人都可以给我一个胶水如何使用钥匙? 当然我不想输入密钥作为密码参数,因为我希望在加密中使用特定的密钥。我不希望将此密钥简单地误解为参数,并根据我的“密钥被误认为密码”计算另一个密钥。
此外,该错误继续查看有关同一openssl_encrypt函数中的初始化向量参数的文档。它只是声明:
iv 非NULL初始化向量。 那个iv应该是一个字符串。鉴于iv通常是一定长度的二进制数据,例如字符串终止\ 0(十六进制0x00)可能在内部发生,我感到困惑的是什么格式。
从本质上讲,我非常感到与PHP文档无关,而且还说明了
警告此功能目前尚未记录;只有它的论点 列表可用。
我做了一些测试,并“试着”帮我弄清楚密码参数是什么。
使用此代码:
$pass="0123456789abcdefghijklmnob";
$iv="0123456789abcdef";
echo "using $pass results:\n";
echo openssl_encrypt("test secret string", 'aes-128-cbc', $pass,NULL,$iv);
我得到了这个结果:
using 0123456789abcdefghijklmnob results:
XjEeaLucY38Y6XEUceYMYKTebR4kOp3s727ipMl5KNc=
然后更改“密码”参数的长度:
$pass="0123456789abcdefg"; //hijklmnob";
$iv="0123456789abcdef";
echo "using $pass results:\n";
echo openssl_encrypt("test secret string", 'aes-128-cbc', $pass,NULL,$iv);
我仍然使用相同的加密代码:
using 0123456789abcdefg results:
XjEeaLucY38Y6XEUceYMYKTebR4kOp3s727ipMl5KNc
似乎是通过测试,而不是通过通过文档通知 密码确实只考虑前16个字节,这似乎是128位密钥。
令我感到害怕的是,在这样一个敏感的函数(用于加密)中,文档很糟糕,而且一个记录不完整的参数的过多输入甚至都没有被警告过。此外,我确信密码应该命名为 key ,因为这16个字节似乎直接代表密钥。
答案 0 :(得分:9)
$password
参数确实是关键。密钥大小取决于您使用的AES模式(如您所知)。
正如您在更新中所述,对于AES-128,只有前16个字符/字节计为密钥。对于AES-256,它将是前32个字符。
当使用openssl_encrypt()
和openssl_decrypt()
函数时,可以简单地为$password
/ key参数传递32个字符的人类可读密码。
例如,我输入的密码参数可能是$password = "This is 32 characters long......";
大多数人不喜欢写一个固定长度的明文密码,因此他们可能会计算一个哈希并将其截断到正确的长度。他们会使用此哈希作为加密密钥/密码。
例如,我可以计算我想要的任何长度的密码/短语的MD5哈希值,然后将其用作我的AES密码/密钥:
$plaintextPass = 'This is my password. This password is not exactly 32 bytes, but that is okay because I am hashing this.';
$password = hash('md5', $plaintextPass); /* the encryption key */
有了这个,无论我使用什么明文密码,我都可以使用有效的32个字符/字节字符串作为我的加密密钥/密码。但这确实减少了加密密钥/密码的熵,因为正常的32个字符串具有比MD5散列输出更大的密钥空间(每个字节256个可能性,每个字节16个可能性);然而,16 ^ 32仍然肯定超出蛮力范围。
关闭主题:在我的一些个人程序中,我一直在使用32个随机生成的字节,其值介于0-255之间。这将使得加密密钥256 ^ 32的熵对于暴力是不可行的。这也将抵抗字典攻击,因为32字节是使用cryptographically secure pseudo-random number generator (CSPRNG)随机生成的。
所以,总而言之,是的,$password
参数确实是用于加密的密钥。我同意你的意见,应该在文档中写成$key
,但是哦。您选择用于加密的密码/密钥可以是人类可读的,只要它满足散列密钥的长度要求即可。为了满足这些长度要求,可以对人类可读/明文密码进行哈希处理,并使用该密码的哈希值作为密钥($password
参数),但人类可读的密码仍然应该很长且唯一。
文档不是很清楚,但是openssl_encrypt()
PHP文档页面上的this comment在我试图理解该函数时确实帮助了我。评论提供了一个示例以及有用的信息。直接引用评论作者:
因为此处记录的密码参数不是密码。 ... 这是关键! [评论略有编辑]