我有一个非常具体的要求,其中某些列需要使用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上,config / app.php:
'Security' => ['salt' => '1234567890']
然后使用:
加密Security::encrypt($value, Security::salt());
数据保存在MySQL上,但aes_decrypt()返回NULL
SELECT AES_DECRIPT(address_enc, '1234567890') FROM address;
如何设置CakePHP 3以正确加密信息,以便稍后使用aes_decrypt()在MySQL上解密?
[编辑]
我的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上,我创建了一个自定义数据库类型:
的src /数据库/类型/ CryptedType.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());
}
}
SRC /配置/ bootstrap.php中
注册自定义类型。
use Cake\Database\Type;
Type::map('crypted', 'App\Database\Type\CryptedType');
的src /型号/表/ AddressTable.php
最后将加密列映射到已注册的类型,就是这样,从现在开始自动处理所有内容。
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;
}
// ...
}
答案 0 :(得分:1)
我不打算讨论将加密数据存储在数据库中的优缺点,但是,尝试在SQL级别解密是一个好主意,是一个应该问的问题。
因此,问问自己是否真的需要这样做,也许最好在应用程序级别实现解密,这可能会使复制的确更容易< / em> Security::decrypt()
做了什么,这不仅解密,还包括完整性检查。
只需看看内部Security::decrypt()
的作用。
在其他应用程序中重新实现它应该很容易。
我绝不是加密专家,所以请将以下内容作为开始工作的基本示例,并特别告知自己可能出现的概念和安全问题!
处理数据的加密/解密而不确切知道你在做什么,一个非常糟糕的主意 - 我不能强调这一点!
话虽如此,使用我链接到的可怕(原文如此)答案的示例代码,即使用Security::encrypt()
和Security::salt()
作为加密密钥,默认情况下会离开使用从与自身连接的salt(first 32 bytes of its SHA256 representation)派生的加密密钥以AES-256-CBC
模式加密的值。
但并非全部,此外,加密值会获得HMAC哈希值,并且初始化向量会挂起,这样您就不会得到可以直接传递给AES_DECRYPT()
的“普通”加密数据。
因此,如果您想在MySQL级别上解密(无论出于何种原因),那么您首先必须设置正确的块加密模式
SET block_encryption_mode = 'aes-256-cbc';
稀疏HMAC散列(前64个字节)和初始化向量(后跟16个字节)
SUBSTRING(`column` FROM 81)
并使用hash('sha256', Security::salt() . Security::salt())
SUBSTRING(`column`, 65, 16)
作为加密密钥,并使用加密值的初始化向量进行解密
SET block_encryption_mode = 'aes-256-cbc';
SELECT
AES_DECRYPT(
SUBSTRING(`column` FROM 81), -- the actual encryted data
'the-encryption-key-goes-here',
SUBSTRING(`column`, 65, 16) -- the intialization vector
)
FROM table;
所以最后你会留下像
这样的东西CAST(AES_DECRYPT(...) AS CHAR)
最后,您可能还想要转换值(AES_DECRYPT()
),并删除可能的零填充(不确定<script>
$(document).ready(function() {
clearInterval(refreshId);
$("#windraw").load("../raw/wind.php");
});
$(document).ready(function() {
refreshId = setInterval(function() {
$("#windraw").load("../raw/wind.php");
$('#winddirneedle').css('rotate', $"#windraw");
}, 5000);
});
</script>
是否自动执行此操作。)
应该注意的是,加密值前面的HMAC哈希有一个特定的目的,它用于the first 32 bytes,所以只要丢弃它,你就会失去它。为了保持它,你必须在SQL级别上实现(定时攻击安全)HMAC256生成/比较。这导致我们回到初始问题,你真的需要在SQL级别解密吗?
答案 1 :(得分:0)
[解决方案]针对此特定需求的解决方案(我们需要使用eas加密SQL级别的信息,以便可以使用其他应用程序或使用查询和aes_encrypt / aes_decryp直接从MySQL读取)来创建自定义CakePHP中的数据库类型,我们实现了PHP Mcrypt。而不是使用CakePHP加密方法。
现在,我们的CakePHP 3应用程序将信息保存到数据库中,并使用eas_decrypt和aes_encrypt在MySQL / phpMyAdmin级别读取数据。