我有一个非常具体的要求,其中一些列需要使用aes_encrypt / aes_decrypt加密。我们需要使用eas在SQL级别加密信息,以便可以使用另一个应用程序读取信息,或者使用查询和aes_encrypt / aes_decrypt直接从MySQL读取信息。
我们的应用程序是使用CakePHP 3开发的,数据库是MySQL 5.6.25。
我找到并仔细地按照这一选定答案上的说明去做:Encyption/Decryption of Form Fields in CakePHP 3
现在,数据被加密保存在数据库中...问题是,我们仍然需要能够在MySQL上使用aes_decrypt来解密信息,但它返回NULL。
在CakePHP 3上,配置/应用程序.php:
'Security' => ['salt' => '1234567890']
然后使用以下方式加密:
Security::encrypt($value, Security::salt());
数据保存在MySQL中,但aes_decrypt()返回NULL
SELECT AES_DECRIPT(address_enc, '1234567890') FROM address;
如何设置CakePHP 3正确加密信息,以便稍后在MySQL中使用aes_decrypt()解密?
[编辑]
我的MYSQL表:
CREATE TABLE IF NOT EXISTS `address` (
`id` int(11) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`address_enc` blob,
`comment` varchar(255) DEFAULT NULL,
`comment_enc` blob
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
注:地址和备注仅供测试使用。
然后,在CakePHP上,我创建了一个自定义数据库类型:
源代码/数据库/类型/加密类型.php
<?php
namespace App\Database\Type;
use Cake\Database\Driver;
use Cake\Database\Type;
use Cake\Utility\Security;
class CryptedType extends Type
{
public function toDatabase($value, Driver $driver)
{
return Security::encrypt($value, Security::salt());
}
public function toPHP($value, Driver $driver)
{
if ($value === null) {
return null;
}
return Security::decrypt($value, Security::salt());
}
}
源代码/配置/引导程序.php
注册自定义类型。
use Cake\Database\Type;
Type::map('crypted', 'App\Database\Type\CryptedType');
源文件/模型/表/地址表.php
最后,将可加密列Map到已注册的类型,就这样,从现在开始,一切都将自动处理。
use Cake\Database\Schema\Table as Schema;
class AddressTable extends Table
{
// ...
protected function _initializeSchema(Schema $table)
{
$table->columnType('address_enc', 'crypted');
$table->columnType('comment_enc', 'crypted');
return $table;
}
// ...
}
3条答案
按热度按时间ki0zmccv1#
您真的需要这样做吗?
我不打算讨论在数据库中存储加密数据的利弊,但尝试在SQL级别解密是否是一个好主意,这是一个应该问的问题。
因此,问问你自己是否真的 * 需要 * 这样做,也许在应用程序级别实现解密会更好,这可能会使复制 * 确切 *
Security::decrypt()
所做的事情更容易,这不仅是解密,而且是完整性检查。看看
Security::decrypt()
的内部功能。*http://github.com/cakephp/cakephp/blob/3.1.7/src/Utility/Security.php#L201
*http://github.com/cakephp/cakephp/blob/3.1.7/src/Utility/Crypto/OpenSsl.php#L77
*http://github.com/cakephp/cakephp/blob/3.1.7/src/Utility/Crypto/Mcrypt.php#L89
在您的其他应用程序中重新实现它应该非常容易。
小心,你的手指可能会被烫伤!
我绝不是一个加密Maven,所以考虑以下只是一个基本的例子,让事情开始,并通知自己可能的概念,特别是安全相关的问题!
在不知道自己在做什么的情况下处理数据的加密/解密是一个非常糟糕的主意-我怎么强调都不为过!
在SQL级别解密数据
也就是说,使用您链接到的我的糟糕(原文如此)答案中的示例代码,即使用
Security::encrypt()
和Security::salt()
作为加密密钥,默认情况下将为您留下一个在AES-256-CBC
模式下加密的值,使用从与其自身连接的salt派生的加密密钥(其SHA 256表示形式的前32个字节)。但这还不是全部,此外,加密的值会得到一个HMAC哈希,初始化向量会被挂起,这样就不会得到可以直接传递给
AES_DECRYPT()
的“普通”加密数据。因此,如果您希望在MySQL级别解密此数据(无论出于何种原因),则首先必须设置正确的块加密模式
稀疏HMAC散列(前64个字节)和初始化向量(后16个字节)
并且使用
hash('sha256', Security::salt() . Security::salt())
的前32个字节作为加密密钥,并使用来自加密值的初始化向量进行解密,所以最后你会得到这样的结果
最后,您可能还希望转换值(
CAST(AES_DECRYPT(...) AS CHAR)
),并删除可能的零填充(不确定AES_DECRYPT()
是否自动执行此操作)。数据完整性检查
需要注意的是,加密值前面的HMAC哈希有一个特定的用途,它用于确保完整性,因此如果直接删除它,您将失去完整性。为了保留它,您还必须在SQL级别实现(定时攻击安全)HMAC 256生成/比较。这将我们带回到最初的问题,您真的需要在SQL级别解密吗?
x3naxklr2#
[解决方案]针对这一特定需求(我们需要使用eas在SQL级别加密信息,以便使用其他应用程序或使用查询和aes_encrypt / aes_decryp直接从MySQL读取信息)的解决方案是在CakePHP中创建自定义数据库类型,而不是使用CakePHP加密方法,我们实现了PHP Mcrypt。
现在信息从我们的CakePHP 3应用程序保存到数据库中,并使用eas_decrypt和aes_encrypt在MySQL/phpMyAdmin级别读取数据。
mccptt673#
对于任何努力使用MYSQL解密的人:这通常适用于使用对称AES加密/解密的任何人-特别是在尝试使用AES_DECRYPT解密时。
例如,如果您使用的是aes-128-ecb,并且加密数据的长度为16个字节且没有填充,则需要在尝试解密之前向加密数据添加填充字节。(因为mySQL需要PKCS 7填充)。因为MySQL使用PKCS 7,您需要再添加16个字节,在本例中,这些填充字节为0x 10101010101010101010101010101010101010101010。我们取左边的16个字节,因为当我们加密0x 1010101010101010101010101010101010时,我们得到32个字节,而我们只需要前16个字节。