当前位置: 首页 > 知识库问答 >
问题:

如何从MySQL中解密Cakephp3加密数据?

上官迪
2023-03-14

现在数据被加密保存在数据库中...问题是我们仍然需要能够在MySQL上使用aes_decrypt来解密信息,而它返回null。

在CakePHP 3上,config/app.php:

'Security' => ['salt' => '1234567890']

然后使用:

Security::encrypt($value, Security::salt());
SELECT AES_DECRIPT(address_enc, '1234567890') FROM address;

我的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
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());
    }
}
use Cake\Database\Type;
Type::map('crypted', 'App\Database\Type\CryptedType');

最后,将加密列映射到注册类型,就这样,从现在开始,所有的事情都将自动处理。

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;
    }

    // ...
}

共有1个答案

宫高义
2023-03-14

我不打算讨论在数据库中存储加密数据的利弊,但尝试在SQL级别上解密是否是一个好主意,这是一个应该问的问题。

因此,问问自己是否真的需要这样做,也许在应用程序级别实现解密会更好,这可能会使复制security::decrypt()所做的事情变得更容易,这不仅是解密,也是完整性检查。

只需看看security::decrypt()在内部做了什么。

  • https://github.com/cakephp/cakephp/blob/3.1.7/src/utility/security.php#l201
  • https://github.com/cakephp/cakephp/blob/3.1.7/src/utility/crypto/openssl.php#l77
  • https://github.com/cakephp/cakephp/blob/3.1.7/src/utility/crypto/mcrypt.php#l89

在其他应用程序中重新实现它应该非常容易。

也就是说,使用链接到的我的糟糕(原文如此)答案中的示例代码,即使用security::encrypt()security::salt()作为加密密钥,在默认情况下会留下一个在AES-256-CBC模式下加密的值,该值使用的加密密钥是从与自身连接的salt派生的(其SHA256表示形式的前32个字节)。

但这还不是全部,此外,加密的值得到一个HMAC散列,初始化向量被插入,这样您就不会得到可以直接传递给aes_decrypt()的“普通”加密数据。

因此,如果您想要在MySQL级别上解密(无论出于什么原因),那么首先必须设置正确的块加密模式

SET block_encryption_mode = 'aes-256-cbc';

稀疏HMAC散列(前64字节)和初始化向量(后16html" target="_blank">字节)

SUBSTRING(`column` FROM 81)

并使用哈希('SHA256',security::salt().security::salt())的前32字节作为加密密钥,以及加密值的初始化向量进行解密

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()是否自动执行此操作)。

需要注意的是,预先设置在加密值之前的HMAC散列有一个特定的目的,它用于确保完整性,所以如果删除它,就会丢失完整性。为了保持它,您还必须在SQL级别上实现(定时攻击安全)HMAC256生成/比较。这将我们引向一个内部问题,您真的需要在SQL级别上解密吗?

 类似资料:
  • 问题内容: 我目前是一名学生,并且正在学习PHP,我正在尝试对PHP中的数据进行简单的加密/解密。我进行了一些在线研究,其中一些非常令人困惑(至少对我而言)。 这是我想做的事情: 我有一个包含这些字段 (用户ID,Fname,Lname,Email,Password)的表 我要拥有的是先将所有字段加密,然后再解密(如果没有任何加密算法,是否可以用于加密/解密) 我想学习的另一件事是如何创建一种与优

  • 我有一个由以下字段组成的表(UserID、Fname、Lname、Email、Password) 我想要的是加密所有字段,然后解密(如果没有任何加密算法,是否可以使用进行加密/解密) 我想学的另一件事是如何创建一个单向的并结合一个好的“salt”。(基本上我只想有一个加密/解密的简单实现,先生/女士,您的回答将会有很大的帮助,非常感谢。谢谢++

  • 问题内容: 创建公司使用的平台的开发人员不再为我们工作,而且我不知道如何从自定义PHP应用程序中检索密码。 当我查看PHPmyAdmin时,密码已加密(例如* 2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19) 如何更改或检索这些? 问题答案: 如果使用正确的加密方法,将无法轻松检索它们。 只需使用新密码重置即可。 编辑: 字符串看起来像它正在使用:

  • 我用RSA加密来加密C#中的一些数据。现在我想用Java解密加密的数据。但是我遇到了一些问题。 主要问题可能是将加密消息从c#获取到java。在c#中,我们有无符号字节,字节序是不同的 因此,为了进行测试,我将c#中加密数据的数组转换为数组并获得它的字符串表示形式。然后我将字节数组的字符串表示形式复制到我的java代码中并将其转换回“字节”数组。之后,我反转数组以匹配java的endianess。

  • 前面小节介绍了如何存储密码,但是有的时候,我们想把一些敏感数据加密后存储起来,在将来的某个时候,随需将它们解密出来,此时我们应该在选用对称加密算法来满足我们的需求。 base64加解密 如果Web应用足够简单,数据的安全性没有那么严格的要求,那么可以采用一种比较简单的加解密方法是base64,这种方式实现起来比较简单,Go语言的base64包已经很好的支持了这个,请看下面的例子: package

  • 我正在尝试使用KMS和AWS加密SDK加密数据。查看AWS文档中提供的示例,似乎没有地方可以显式设置数据键。 使用由KMS生成的数据密钥使用AWS加密SDK加密数据的推荐方法是什么?