繁体   English   中英

MySql AES_DECRYPT & AES_ENCRYPT 密钥在 PHP 中不起作用

[英]MySql AES_DECRYPT & AES_ENCRYPT Key is not working in PHP

在我们的项目中,我们计划将数据以加密格式存储在 mysql 数据库中,我们在我们的项目中使用了 php 和 MqSql。 Mqsql 加密工作正常,我对 MqSql 使用了以下方法

 INSERT INTO emails  SET email= TO_BASE64(AES_ENCRYPT('selvamani.p','3xY4/xrbFETctQS0Rkd1r6MKS4PUXetmjTeuRHkMt2w=', '44Y9/xrbFETcmQS0'));

    SELECT  id, AES_DECRYPT(FROM_BASE64(email), '3xY4/xrbFETctQS0Rkd1r6MKS4PUXetmjTeuRHkMt2w=','44Y9/xrbFETcmQS0') AS decrypt_string  from emails e 

但是我们无法解密 PHP 中的字符串,它是由 MqSql 加密的。 在 php 我们下面这样使用

 $stringValue = openssl_encrypt($stringValue, $this->cipher_method,$this->encryption_key, $this->options, $this->encryption_iv);    

    $stringValue = openssl_decrypt(base64_decode($stringValue), $this->cipher_method, $this->encryption_key, $this->options, $this->encryption_iv);     

当使用 AES 使用一个库进行加密,然后使用不同的库进行解密时,重要的是要确保双方的所有细节都相同。 例如。

  • AES 有许多模式(例如 aes-128-cbc、aes_128-ecb、aes-128-gcm、aes-256-cbc、aes_256-ecb、aes-256-gcm 等等)。 对加密和解密使用相同的模式很重要。

  • 许多 AES 加密/解密函数允许您传入密码而不是密钥,并且 function 在内部从密码派生密钥。 然而,当从一个库转移到另一个库时,这通常充满了问题,因为内部用于密钥派生的方法在不同的实现之间差异很大。 因此,最好直接传递密钥(长度正确,适用于您使用的 AES 模式),而不是传递密码。

  • 加密和解密函数通常期望明文、密文、密钥、iv 等输入作为原始字节而不是文本传入。 请注意这一点,并确保在需要时传入原始字节。 同样,加密和解密函数通常会产生原始字节的输出。 一定要相应地处理这些。

MySQL uses aes_128_ecb mode by default (see https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html ). 因此,要在 MySQL 中使用 aes_128_ecb 模式使用密钥 F3229A0B371ED2D9441B830D21A390C3 加密明文“bill.smith@gmail.com”,我们可以这样做:

 select to_base64(aes_encrypt('bill.smith@gmail.com', UNHEX('F3229A0B371ED2D9441B830D21A390C3')));

请注意,密钥是作为正在使用的模式(128 字节)的正确长度的十六进制编码字符串提供的,我们使用 UNHEX() 将其转换为 MySQL aes_encrypt() function 要求的原始字节. aes_encrypt() 函数生成原始字节作为其 output,我们使用 to_base64() 对这些原始字节进行 base64 编码以生成可显示的文本。 上面的语句产生以下 base64 编码的密文:

oPN1EIfxX+MFMfcp2jTjjB55QVUURKV8lbfcwhT3MMk=

让我们看看我们是否可以使用相同的密钥解密它,在命令行上使用 openssl,看看是否会生成我们开始使用的明文:

echo -n 'oPN1EIfxX+MFMfcp2jTjjB55QVUURKV8lbfcwhT3MMk=' | base64 -d | openssl aes-128-ecb -d -K F3229A0B371ED2D9441B830D21A390C3

同样,请注意确保所有输入都正确传递。 上面的命令产生:

bill.smith@gmail.com

伟大的。 我们能够在 MySQL 中加密一些明文,然后在 openssl 中执行相反的操作,并且成功了。 现在,让我们看看我们是否可以解密 PHP 中的密文。 让我们试试这个:

$ciphertextbase64="oPN1EIfxX+MFMfcp2jTjjB55QVUURKV8lbfcwhT3MMk=";
$keyhex='F3229A0B371ED2D9441B830D21A390C3'; 
$ciphertextbytes=base64_decode($ciphertextbase64);
$keybytes=hex2bin($keyhex);
$plaintext = openssl_decrypt($ciphertextbytes, 'aes-128-ecb', $keybytes);
print $plaintext;

同样,请注意正确传递所有内容的注意事项。 但是,在我的系统上,上面的代码片段没有产生 output。 有什么问题?

在我的系统上运行openssl_get_cipher_methods ,我看到不支持 aes-128-ecb。 这并不奇怪,因为 aes-128-ecb 有已知的弱点 To solve the problem, it would be best to encrypt using some other mode on the MySQL side (see https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html for more info on this) .

我们在 Mcrypt_encrypt 和 mcrypt_decrypt 中得到了解决方案

MySql:

SELECT TO_BASE64(AES_ENCRYPT('selvamani', '34/xrbFET445QS0')) 作为编码

SELECT AES_DECRYPT(FROM_BASE64("Bdc3RbB4rU3vBrkdIjTFoQ=="),'34/xrbFET445QS0') AS decrypt_string

PHP:

$val = "塞尔瓦玛尼"; $key = "34/xrbFET445QS0"; $pad_value = 16-(strlen($val) % 16); $val = str_pad($val, (16*(floor(strlen($val) / 16)+1)), chr($pad_value)); $data = Mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $val, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM)) ; 回声 base64_encode($data);

$key = "34/xrbFET445QS0"; $val = base64_decode("Bdc3RbB4rU3vBrkdIjTFoQ=="); $val = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $val, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM)) ;

回声 $val;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM