AES_ENCRYPT使用 128 位长的密钥来加密数据,但 MySQL 如何处理更长或更短的密钥?我发现 PyCrypto 实例建议通过使用 MD5、SHA-1、SHA-2 等哈希来转换密钥,然后使用生成的密钥进行加密。它如何与 MySQL 一起工作?
MySQL AES_ENCRYPT 密钥长度
MySQL 5.5 不处理其他密钥大小。如http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html所述:
AES_ENCRYPT() 和 AES_DECRYPT() 启用使用官方 AES(高级加密标准)算法(以前称为“Rijndael”)对数据进行加密和解密。使用 128 位密钥长度编码,但您可以通过修改源将其扩展到 256 位。我们选择了 128 位,因为它速度更快,并且对于大多数用途来说足够安全。
我从未尝试将更大的密钥传递给 MySQL,但我猜它会产生错误或截断为 128 位。
我不确定 MD5 是否使用它的完整 codomain,因为我找不到任何证据证明 MD5 是 surjection。因此,我假设您将less 通过使用 MD5 哈希来获得安全性,因为您减少了密钥的可能值集。这仍然是非常主观的。
就较小的密钥而言,我想0x1 == 0x00...01它仍然是有效的密钥。
顺便说一句,我不明白你为什么不生成给定大小的密钥。如果您有一些限制(您想重用已经存在的密钥,...),请告诉我们。
抱歉,后来我从RubyForum发现了
“该算法只是创建一个 16 字节缓冲区设置为全零,然后遍历您提供的字符串的所有字符,并在两个值之间使用按位异或进行赋值。如果我们迭代直到我们到达 16 字节缓冲区的末尾,我们只是从头开始做 ^=。对于短于 16 个字符的字符串,我们在字符串的末尾停止。
bzero((char*) rkey,AES_KEY_LENGTH/8); /* Set initial key */
for (ptr= rkey, sptr= key; sptr < key_end; ptr++,sptr++)
{
if (ptr == rkey_end)
ptr= rkey; /* Just loop over tmp_key until we used all key */
*ptr^= (uint8) *sptr;
}
在 Ruby 中看起来像这样
def mysql_key2(key)
final_key = "\0" * 16
key.length.times do |i|
final_key[i%16] ^= key[i]
end
final_key
end
我将它应用于python:
finalKey = b'\0'*16
key = b'mySecretKey'
for i, c in enumerate(key) :
finalKey[i%16] ^= key[i]
不要使用重复的密码可能是明智的,"MySQL=insecure! MySQL=insecure! "因为它会使生成的密钥归零。
默认情况下,这些函数使用 128 位密钥长度实现 AES。从 MySQL 5.7.4 开始,可以使用 196 或 256 位的密钥长度,如下所述。密钥长度是性能和安全性之间的权衡。加密函数
我必须在 PHP 中执行此操作。您需要按照@joecks 的描述执行 XOR,并删除任何小于 16 字节的加密数据的填充,如下所述:http://forums.devnetwork.net/viewtopic.php?f=34&t= 97082
工作代码:
<?php
$key = 'SomeSecretKeyThatCanBeLongerThan16Bytes';
$encodedString = [fetched from DB];
$finalKey = array_fill(0, 16, 0);
foreach (unpack('C*', $key) as $i => $char)
{
$finalKey[($i-1)%16] = $finalKey[($i-1)%16] ^ $char;
}
$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, implode(array_map("chr", $finalKey)), $encodedString, MCRYPT_MODE_ECB, '');
return rtrim($dec, ((ord(substr($dec, strlen($dec) - 1, 1)) >= 0 and ord(substr($dec, strlen($dec) - 1, 1 ) ) <= 16 ) ? chr(ord(substr($dec, strlen($dec ) - 1, 1))): null) );