You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP解密SQL Server加密数据?解密返回bool(false)求助

问题分析与解决方案

你遇到的openssl_decrypt返回bool(false)的问题,核心原因是SQL Server的EncryptByKey加密逻辑与PHP openssl扩展的标准AES加密不兼容,具体问题点如下:

  • EncryptByKey生成的加密数据包含额外元数据(密钥GUID、版本号等),并非纯AES加密字节流;
  • 你错误地将对称密钥名称MySymmetricKey作为加密密钥使用,实际加密的是SQL Server内部生成的对称密钥值,该值无法直接获取;
  • 随机生成IV不符合SQL Server的加密逻辑,EncryptByKey的IV已自动嵌入加密数据中,无需手动指定。

以下提供两种可行解决方案:

方案一:SQL Server端解密后返回数据(最简单安全)

直接在SQL查询中完成解密,避免客户端处理复杂的加密格式:

<?php
$serverName = "LAPTOP-7A7MOGOK\MSSQLSERVER2";
$connectionInfo = array("Database" => "testen", "UID" => "sa", "PWD" => "04052002");
$conn = sqlsrv_connect($serverName, $connectionInfo);

// 先打开对称密钥,再解密数据
$query = "
OPEN SYMMETRIC KEY MySymmetricKey DECRYPTION BY PASSWORD = 'MyPassword';
SELECT CAST(DecryptByKey(Sensitive) AS VARCHAR(MAX)) AS DecryptedData 
FROM MyTable;
CLOSE SYMMETRIC KEY MySymmetricKey;
";
$result = sqlsrv_prepare($conn, $query);
sqlsrv_execute($result);

while ($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
    var_dump($row['DecryptedData']);
}

sqlsrv_free_stmt($result);
sqlsrv_close($conn);
?>

方案二:改用EncryptByPassphrase实现客户端解密

若必须在客户端解密,建议使用EncryptByPassphrase(直接用密码加密,无需对称密钥),其加密格式可在PHP中模拟解析:

修改后的SQL脚本

CREATE DATABASE testen
go

USE testen
go

CREATE TABLE MyTable (
    Ma INT IDENTITY(1,1) PRIMARY KEY,
    Sensitive VARBINARY(256)
)

-- 使用密码直接加密数据
INSERT INTO MyTable (Sensitive)
VALUES (EncryptByPassphrase('MyPassword', 'Sensitive Data'));
SELECT * FROM MyTable

PHP解密代码

<?php
$serverName = "LAPTOP-7A7MOGOK\MSSQLSERVER2";
$connectionInfo = array("Database" => "testen", "UID" => "sa", "PWD" => "04052002");
$conn = sqlsrv_connect($serverName, $connectionInfo);

$query = "SELECT Sensitive FROM MyTable";
$result = sqlsrv_prepare($conn, $query);
sqlsrv_execute($result);

$password = 'MyPassword';
while ($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
    $encryptedData = $row['Sensitive'];
    
    // 拆分EncryptByPassphrase的加密结构:前16字节是密码SHA-1哈希前缀,中间16字节是IV,剩余是密文
    $iv = substr($encryptedData, 16, 16);
    $ciphertext = substr($encryptedData, 32);
    
    // 生成AES-256密钥:对密码做SHA-1哈希后取前32字节
    $key = substr(hash('sha1', $password, true), 0, 32);
    
    // AES-256-CBC模式解密,去除PKCS7填充
    $decryptedData = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
    $padding = ord(substr($decryptedData, -1));
    $decryptedData = substr($decryptedData, 0, -$padding);
    
    var_dump($decryptedData);
}

sqlsrv_free_stmt($result);
sqlsrv_close($conn);
?>

注:若坚持使用EncryptByKey实现客户端解密,需先导出SQL Server内部对称密钥的明文(需通过证书等方式,存在安全风险),同时手动解析加密数据中的元数据,步骤复杂且不推荐。

内容的提问来源于stack exchange,提问作者Anh Kiệt Nguyễn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:32:06