Php 解密Laravel加密值

Php 解密Laravel加密值,php,mysql,laravel,encryption,Php,Mysql,Laravel,Encryption,我有一个Laravel应用程序,它使用默认的Laravel可加密特性进行加密和解密 现在我需要将数据库迁移到另一个数据库 我已经创建了一个SQL脚本来处理数据迁移,但是在迁移过程中,我需要对一些字段进行一些检查。例如: insert into test.table (valueA, valueB, valueC) SELECT tb.a, tb.b, tc.c from db2.tableB tb join test.tableC

我有一个Laravel应用程序,它使用默认的Laravel可加密特性进行加密和解密

现在我需要将数据库迁移到另一个数据库

我已经创建了一个SQL脚本来处理数据迁移,但是在迁移过程中,我需要对一些字段进行一些检查。例如:

insert into test.table
            (valueA, valueB, valueC) 
SELECT      tb.a, tb.b, tc.c
from        db2.tableB tb
join        test.tableC tc on tb.id = tc.tb_id;

UPDATE      test.table
SET         valueD =  CASE  
            WHEN valueA = 'example' THEN 1 
            ELSE 0
END;
SELECT AES_DECRYPT(from_base64(valueA),'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') from 
test.table;
问题是其中一些字段是加密的。 例如,valueA将类似于:

EYJPDII6IMTTTUTHN0DFT2N3QKT6REDAAMIYWG9PSISINZHBHVLIKOIAKFIA0RFTVDCSU1HWY3N0VUT09IIWIBWFJIJOIOGI1ZJY5ODVKYZMZMZYNZMZMZYNZMZMZYMWWNM2RZDZDZDYLZVLOCJ9

我尝试使用Laravel中的APP_密钥使用AES_DECRYPT(),但脚本总是返回null。例如:

insert into test.table
            (valueA, valueB, valueC) 
SELECT      tb.a, tb.b, tc.c
from        db2.tableB tb
join        test.tableC tc on tb.id = tc.tb_id;

UPDATE      test.table
SET         valueD =  CASE  
            WHEN valueA = 'example' THEN 1 
            ELSE 0
END;
SELECT AES_DECRYPT(from_base64(valueA),'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') from 
test.table;
始终返回NULL

显然,这把钥匙是为了这篇文章而隐藏的

我认为这是因为Laravel在加密时使用open_ssl,而AES_DECRYPT不使用。我说得对吗

有没有办法在运行迁移脚本之前解密数据库,或者在更新期间解密SELECT语句中的值


更新:

为了使用“AES-256-CBC”,我设置了MySql。 请记住,在Laravel中,应用程序密钥类似于:“base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”

这就是我现在要做的:

SET block_encryption_mode = 'aes-256-cbc';
SET @key_str = to_base64('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
SET @init_vector = (SELECT LEFT(CONVERT(encryptedVal USING binary), 16)  from tableA where id =1);
SELECT encryptedVal, AES_DECRYPT(encryptedVal,@key_str,@init_vector) from tableA where id = 1;
顺便说一句,我仍然有空值。
如果有人需要任何帮助,我们将不胜感激。

我最终创建了一个从Laravel调用的脚本,用于解密我需要的表和字段:

class DecryptDatabase extends Command
{
    protected $tables = (array(
        "tableA" => array(
           "pk" => 'id',
           "encrypted" =>  array('valueA', 'valueB', 'valueC'),
           "name" => "tableA"
           ),
        "users" => array(
            "pk" => 'id',
            "encrypted" =>  array('name', 'surname', 'profession'),
            "name" => "users"
            ),
        ));

    public function handle()
    {
        foreach($this->tables as $t) {
            $columns = implode(',', $t['encrypted']);
            $q = DB::connection('mysql2')->select('select ' . $t['pk']. ','. $columns . ' from '. $t['name']);
            foreach($q as $result)
            {
                $pk = $t['pk'];
                try {
                    foreach($t['encrypted'] as $enc) {
                        if($result->$enc != null){
                            $decrypted = Crypt::decrypt($result->$enc);
                            $query = DB::connection('mysql3')
                            ->table($t['name'])
                            ->where($t['pk'], $result->$pk)
                            ->update([$enc => $decrypted]);
                        }
                    }
                } catch (DecryptException $e) {
                    echo ("Error in decryption: ". $e);
                }
            }
        }  
        echo "Decryption terminated";
        return 0;
    }
}
此脚本解密$tables变量中定义的所有字段。 它使用“mysql2”连接中定义的数据库作为加密值的源,然后将解密值存储在“mysql3”连接中定义的数据库中

第一个数据库是原始数据库,而第二个数据库是第一个数据库的精确副本。我这样做是为了在解密时保持原始数据库不变,以防止在解密过程中出现错误时数据损坏


解密数据库后,我可以正确运行迁移脚本,然后按照解密函数的相反方向再次加密数据库。

如果有人需要,我最终创建了一个名为from Laravel的脚本,对我需要的表和字段进行解密:

class DecryptDatabase extends Command
{
    protected $tables = (array(
        "tableA" => array(
           "pk" => 'id',
           "encrypted" =>  array('valueA', 'valueB', 'valueC'),
           "name" => "tableA"
           ),
        "users" => array(
            "pk" => 'id',
            "encrypted" =>  array('name', 'surname', 'profession'),
            "name" => "users"
            ),
        ));

    public function handle()
    {
        foreach($this->tables as $t) {
            $columns = implode(',', $t['encrypted']);
            $q = DB::connection('mysql2')->select('select ' . $t['pk']. ','. $columns . ' from '. $t['name']);
            foreach($q as $result)
            {
                $pk = $t['pk'];
                try {
                    foreach($t['encrypted'] as $enc) {
                        if($result->$enc != null){
                            $decrypted = Crypt::decrypt($result->$enc);
                            $query = DB::connection('mysql3')
                            ->table($t['name'])
                            ->where($t['pk'], $result->$pk)
                            ->update([$enc => $decrypted]);
                        }
                    }
                } catch (DecryptException $e) {
                    echo ("Error in decryption: ". $e);
                }
            }
        }  
        echo "Decryption terminated";
        return 0;
    }
}
此脚本解密$tables变量中定义的所有字段。 它使用“mysql2”连接中定义的数据库作为加密值的源,然后将解密值存储在“mysql3”连接中定义的数据库中

第一个数据库是原始数据库,而第二个数据库是第一个数据库的精确副本。我这样做是为了在解密时保持原始数据库不变,以防止在解密过程中出现错误时数据损坏


解密数据库后,我可以正确运行迁移脚本,然后按照解密函数的相反方向再次加密数据库。

我发现有迹象表明,Laravel使用AES+HMAC进行完整性/身份验证,但还没有规范,好像他们不希望您故意找到它似的。可能它使用了。嗨@MaartenBodewes。是的,它使用了你链接的特征。根据您在那里读到的内容,您知道(如果)我如何在MySql Workbench中直接解密吗?我有点困惑,要么是
IV+CBC(纯文本)
,要么是
IV+CBC(纯文本)+MAC
。查看
AES\u DECRYPT
,它默认为使用系统变量的ECB模式,并且在参数中包含IV,而不是在密文中。与大多数DB加密功能一样,它有点难以置信的愚蠢;相对较少的数据库加密似乎是由专家设计的。但是,是的,将模式更改为CBC,从密文中提取IV(前16个字节),然后解密。如果它不起作用,可能是因为MAC仍然存在。再次感谢您的回答@MaartenBodewes。我试图在MySql中使用
SET block\u encryption\u mode='aes-256-CBC
将模式更改为CBC。顺便说一句,我得到了以下错误:
错误代码:1193。未知系统变量“块加密模式”
。这听起来真的很奇怪,因为如果我运行
SHOW变量,比如“%version%”我得到
'version',10.4.11-MariaDB'
,因此块加密模式应该出现在我的版本中。知道为什么会这样吗?不,也许在搜索后再问一个问题<代码>设置块加密模式='aes-256-cbc'从字面上看似乎出现在文档中。我试着远离DB编程,我更像是一个安全专家。我发现有迹象表明Laravel使用AES+HMAC进行完整性/身份验证,但还没有规范,好像他们不想让你故意找到它。可能它使用了。嗨@MaartenBodewes。是的,它使用了你链接的特征。根据您在那里读到的内容,您知道(如果)我如何在MySql Workbench中直接解密吗?我有点困惑,要么是
IV+CBC(纯文本)
,要么是
IV+CBC(纯文本)+MAC
。查看
AES\u DECRYPT
,它默认为使用系统变量的ECB模式,并且在参数中包含IV,而不是在密文中。与大多数DB加密功能一样,它有点难以置信的愚蠢;相对较少的数据库加密似乎是由专家设计的。但是,是的,将模式更改为CBC,从密文中提取IV(前16个字节),然后解密。如果它不起作用,可能是因为MAC仍然存在。再次感谢您的回答@MaartenBodewes。我试图在MySql中使用
SET block\u encryption\u mode='aes-256-CBC
将模式更改为CBC。顺便说一句,我得到了以下错误:
错误代码:1193。未知系统变量“块加密模式”
。这听起来真的很奇怪,因为如果我运行
SHOW变量,比如“%version%”我得到
'version',10.4.11-MariaDB'
,因此块加密模式应该出现在我的版本中。知道为什么吗