PHP Openssl 解密 AES Mysql 加密

问题描述 投票:0回答:3

所以我只是对我的 mysql 表进行一些基本的数据加密。我遵循了这里找到的指南 https://dev.mysql.com/doc/refman/5.6/en/cryption-functions.html#function_aes-encrypt

但我遇到了一个问题。虽然我知道我可以在 mysql 查询中使用 aes_decrypt 来解密数据。我希望 php 本身也能做到这一点。

我已经让这部分工作了。如果 MySQL 像这样执行非常基本的 AES_ENCRYPTION

INSERT INTO tablename (dataset) VALUES (AES_ENCRYPT('testvalue','mysecretphrase'))

我可以像这样用 php 解密它

openssl_decrypt(base64_encode($dR['dataset']), 'aes-128-ecb', 'mysecretphrase')

当我使用 MySQL 在上面的 url 中提到的推荐的 UNHEX(SHA2('mysecretphrase',512)) 时,我的问题出现了。

我尝试使用的 php sha* 函数可以确认它们都生成与 MySQL sha2() 相同的字符串

openssl_digest('mysecretphrase', 'sha512')
// AND
hash('sha512', 'mysecretphrase')

最后为了解决 mysql 使用的 UNHEX() 问题,经过一番研究,我发现 PHP hex2bin == unhex http://www.php.net/manual/en/function.hex2bin.php

但是,我在解密数据时没有得到任何结果。这就是它不断失败的地方。我觉得好像我错过了一些东西,但这只是不解密数据,只返回空结果。

openssl_decrypt(base64_encode($dR['dataset']), 'aes-128-ecb', hex2bin(openssl_digest('mysecretphrase', 'sha512')))

任何帮助、指示或提示将不胜感激。

php mysql openssl sha512
3个回答
5
投票

我遇到了同样的问题,感谢 MIvanIsten 的回答,我弄清楚了如何使用 MariaDB/MySQL 正确加密并使用 PHP 解密:

加密:

SELECT HEX( AES_ENCRYPT( 'secret data', 
SUBSTR(UNHEX(SHA2('mysecretphrase', 512)), 1, 16) )) AS encrypted;

解密:

openssl_decrypt(
   base64_encode(hex2bin($encrypted_string_from_mysql)), 
   'aes-128-ecb',
   substr(hex2bin(openssl_digest('mysecretphrase', 'sha512')), 1, 16)  
);

4
投票

我在这里回答是因为它显然比评论便宜......

上面的帖子非常准确地告诉您问题是什么,但并没有真正说明如何解决它。

openssl_encrypt() 和 openssl_decrypt() 将密钥静默切割为最大 16 字节长度(至少对于 aes-128-ecb)

并且无法更改此设置,因此在 MySQL 中使用

AES_ENCRYPT
时,您需要通过创建其子字符串来缩短密钥。

INSERT INTO tablename (dataset) 
VALUES (AES_ENCRYPT('testvalue',SUBSTR( UNHEX(SHA2('mysecretphrase',512)), 1, 16))))

请注意,既然您使用了子字符串,上面答案中的

l_16
列与
["data2"]
是如何相同的? (可能需要在 php 中执行
strtolower()

如果这给您带来了安全问题,您将需要找到一种没有此限制的替代加密算法


4
投票

openssl_encrypt()
openssl_decrypt()
无声地将密钥切割为最大 16 字节长度(至少对于 aes-128-ecb)。

密码短语文档

如果密码短于预期,则会用 NUL 字符默默填充;如果密码比预期长,它会被静默截断。

<?php
    $key1 = hex2bin(openssl_digest('mysecretphrase', 'sha512'));
    $key2 = substr($key1, 0, 16);
    $key3 = substr($key1, 0, 15);
    $method = 'aes-128-ecb';
    $in = 'testvalue';
    $data1 = base64_decode(openssl_encrypt($in, $method, $key1));
    $data2 = base64_decode(openssl_encrypt($in, $method, $key2));
    $data3 = base64_decode(openssl_encrypt($in, $method, $key3));
    var_dump(
        array(
            'key1'=>bin2hex($key1),
            'key2'=>bin2hex($key2),
            'key3'=>bin2hex($key3),
            'data1'=>bin2hex($data1),
            'data2'=>bin2hex($data2),
            'data3'=>bin2hex($data3),
            'data1==data2'=>($data1===$data2),
            'data1==data3'=>($data1===$data3)
        )
    );
?>

结果:

   array(8) {
        ["key1"]=>string(128) "5fe76dfd5b75cf7cf68fae85d26fcc9b7951806ad6daaa71d843c6ec0e0ec9233a828ad9b60986a43d734983c8a0a50d3a0a49ec5ac196cfcc136aa16e0c5f89"
        ["key2"]=>string(32) "5fe76dfd5b75cf7cf68fae85d26fcc9b"
        ["key3"]=>string(30) "5fe76dfd5b75cf7cf68fae85d26fcc"
        ["data1"]=>string(32) "eb69e89312c1f7b9522d0e66346f2029"
        ["data2"]=>string(32) "eb69e89312c1f7b9522d0e66346f2029"
        ["data3"]=>string(32) "664f5a28d241f959beac350f2314b079"
        ["data1==data2"]=>bool(true)
        ["data1==data3"]=>bool(false)
    }

在 mysql 中,全长密钥由

AES_ENCRYPT()
AES_DECRYPT()

使用
SELECT 
    HEX(AES_ENCRYPT('testvalue',UNHEX(SHA2('mysecretphrase',512)))) AS l_full,
    HEX(AES_ENCRYPT('testvalue',SUBSTR(UNHEX(SHA2('mysecretphrase',512)),1,16))) AS l_16,
    HEX(AES_ENCRYPT('testvalue',SUBSTR(UNHEX(SHA2('mysecretphrase',512)),1,15))) AS l_15;

结果:

l_full                           | l_16                             | l_15
---------------------------------|----------------------------------|----------------------------------------
A88DD1EFB377FD31A0EFA55EA29BA8C6 | EB69E89312C1F7B9522D0E66346F2029 | 664F5A28D241F959BEAC350F2314B079
© www.soinside.com 2019 - 2024. All rights reserved.