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

SQL Server Always Encrypted:CEK的ENCRYPTED_VALUE生成及非SSMS方式探讨

嘿,我来帮你把SQL Server Always Encrypted里CEK的ENCRYPTED_VALUE相关问题掰扯清楚,分点给你讲明白:

一、怎么生成CEK的ENCRYPTED_VALUE?

先理清楚核心逻辑:ENCRYPTED_VALUE其实是**列加密密钥(CEK)被列主密钥(CMK)**加密后的产物。Always Encrypted的加密链路是:用AES-256对称密钥(也就是CEK明文)加密业务数据,再用非对称的CMK(比如RSA密钥)加密这个CEK明文——所以ENCRYPTED_VALUE就是加密后的CEK二进制数据,一般会转成十六进制字符串方便在SQL语句里使用。

生成的核心步骤就两步:

  1. 生成一个随机的32字节AES-256密钥(这就是CEK的明文,绝对不能泄露给SQL Server)
  2. 用CMK的公钥,通过指定的算法(比如RSA_OAEP)加密这个CEK明文,得到的结果就是ENCRYPTED_VALUE
二、除了SSMS,还有其他方式生成吗?

当然有!SSMS只是把底层操作做了可视化封装,你完全可以用脚本或者代码手动实现,这里给你两种常用方案:

1. PowerShell脚本(官方推荐的自动化方式)

先确保安装了SqlServer模块,然后按步骤来:

# 安装并导入模块(如果没装过的话)
Install-Module -Name SqlServer -Force
Import-Module SqlServer

# 获取已有的CMK对象(这里假设你的CMK已经在SQL Server里注册了)
$cmk = Get-SqlColumnMasterKey -Name "MyCMK" -ServerInstance "你的SQL服务器地址" -Database "目标库"

# 生成随机的AES-256 CEK明文
$cekPlaintext = New-Object byte[] 32
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($cekPlaintext)

# 用CMK加密CEK明文
$encryptedCek = Invoke-SqlColumnMasterKeyEncrypt -ColumnMasterKey $cmk -Plaintext $cekPlaintext

# 转成带0x前缀的十六进制字符串(符合SQL语法要求)
$encryptedValueHex = "0x" + [System.BitConverter]::ToString($encryptedCek).Replace("-", "")

最后把$encryptedValueHex的值直接填到CREATE语句里就行。

2. C#/.NET自定义实现

如果需要更灵活的逻辑,直接用.NET的加密API写代码也可以:

using System;
using System.Security.Cryptography;

// 第一步:获取CMK的公钥(这里以Azure Key Vault为例,也可以从本地证书存储取)
RSA cmkPublicKey = GetCmkPublicKeyFromYourKeyStore("你的密钥存储地址/名称");

// 第二步:生成随机AES-256 CEK明文
byte[] cekPlaintext = new byte[32];
RandomNumberGenerator.Fill(cekPlaintext);

// 第三步:用RSA_OAEP算法加密CEK
byte[] encryptedCek = cmkPublicKey.Encrypt(cekPlaintext, RSAEncryptionPadding.OaepSHA256);

// 第四步:转成带0x前缀的十六进制字符串
string encryptedValueHex = "0x" + BitConverter.ToString(encryptedCek).Replace("-", "");

要是你的CMK存在本地Windows证书存储,直接用X509Certificate2类加载证书就能拿到公钥,完全不用碰AKV。

注意:SQL Server本身不会帮你做这个操作,因为Always Encrypted是客户端加密设计——密钥操作全在客户端完成,绝对不会把明文密钥传到SQL Server实例里,避免泄露风险。

三、能不能用“未知密钥”加密数据?以及不用AKV解密的可能?

先纠正一个认知:Always Encrypted的核心是客户端加密,数据在客户端加密后才会传到SQL Server,SQL Server自始至终看不到任何明文密钥和明文数据。

关于“未知密钥”:

  • 不存在用完全未知的密钥加密数据的情况,因为加密数据必须用到CEK的明文,而CEK明文只能通过CMK的私钥解密ENCRYPTED_VALUE才能拿到——你连密钥是什么都不知道,根本没法加密数据。

关于脱离AKV解密:

  • 完全可以!AKV只是CMK的一种存储方式,你可以把CMK存在本地证书存储、本地HSM(硬件安全模块),甚至自己管理的密钥服务里,只要你的客户端能访问到CMK的私钥,就能解密CEK,进而解密数据,完全不需要依赖AKV。

举个实际例子:如果你的CMK是客户端机器上的自签名证书,只要运行解密程序的机器能访问到这个证书的私钥,就能直接解密数据,连网络都不用开。

四、完整的CREATE COLUMN ENCRYPTION KEY示例

用上面生成的十六进制字符串,执行下面的SQL语句就能创建CEK:

CREATE COLUMN ENCRYPTION KEY MyCEK
WITH VALUES (
    COLUMN_MASTER_KEY = MyCMK,
    ALGORITHM = 'RSA_OAEP',
    ENCRYPTED_VALUE = 0xABCDEF123456... -- 这里填你生成的十六进制字符串
);

内容的提问来源于stack exchange,提问作者sglogowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:54:54