驅動 go-mssqldb 程式支援 Always Encrypted ,用於用戶端加密與解密敏感資料。 啟用後,驅動程式會自動解密加密欄位的資料,並加密傳送到加密欄位的參數值。
啟用「始終加密」
將連線參數設 columnencryption 為 true:
sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&columnencryption=true
你還需要至少匯入一個欄位主金鑰(CMK)提供者套件。 沒有服務提供者,駕駛者無法存取加密金鑰。
欄位主金鑰提供者
驅動程式支援三個主要的商店供應商。 以副作用匯入的方式匯入提供者套件,以註冊它。
本地證書(PFX)
localcert提供者會從本機檔案系統中的 PFX(PKCS #12)檔案讀取私密金鑰。 CMK 元資料中的提供者名稱為 pfx。
import (
_ "github.com/microsoft/go-mssqldb"
_ "github.com/microsoft/go-mssqldb/aecmk/localcert"
)
在 SQL Server 中設定 CMK 時,將金鑰路徑設定為 PFX 檔案位置:
CREATE COLUMN MASTER KEY MyCMK
WITH (
KEY_STORE_PROVIDER_NAME = 'pfx',
KEY_PATH = '/path/to/certificate.pfx'
);
如果 PFX 檔案有密碼保護,請將密碼設為環境變數或透過 pfxpassword 連線參數。
Windows 憑證存放區
MSSQL_CERTIFICATE_STORE提供者會存取 Windows 憑證商店中的憑證。 此服務提供者僅支援 Windows。
import (
_ "github.com/microsoft/go-mssqldb"
_ "github.com/microsoft/go-mssqldb/aecmk/localcert"
)
Note
匯入 localcert 也會在 Windows 上註冊 Windows 憑證存放區提供者。 不需要另外的匯入。
CMK 金鑰路徑格式為 CurrentUser/My/<thumbprint> 或 LocalMachine/My/<thumbprint>:
CREATE COLUMN MASTER KEY MyCMK
WITH (
KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE',
KEY_PATH = 'CurrentUser/My/<CERTIFICATE_THUMBPRINT>'
);
Azure Key Vault
akv提供者會從 Azure Key Vault 取得欄位主金鑰。
import (
_ "github.com/microsoft/go-mssqldb"
_ "github.com/microsoft/go-mssqldb/aecmk/akv"
)
CMK 金鑰路徑是 Azure Key Vault 金鑰識別碼 URL:
CREATE COLUMN MASTER KEY MyCMK
WITH (
KEY_STORE_PROVIDER_NAME = 'AZURE_KEY_VAULT',
KEY_PATH = 'https://<VAULT_NAME>.vault.azure.net/keys/<KEY_NAME>/<KEY_VERSION>'
);
Azure Key Vault 提供者用於azidentity.DefaultAzureCredential認證。 透過環境變數、管理身份、Azure CLI 或其他 Azure 身份函式庫支援的方法來設定憑證。 欲了解更多資訊,請參閱 Microsoft Entra ID 認證。
查詢加密欄位
啟用 Always Encrypted 並註冊服務提供者後,查詢運作透明:
import (
"context"
"database/sql"
"fmt"
"log"
_ "github.com/microsoft/go-mssqldb"
_ "github.com/microsoft/go-mssqldb/aecmk/localcert"
)
func main() {
db, err := sql.Open("sqlserver",
"sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&columnencryption=true")
if err != nil {
log.Fatal(err)
}
defer db.Close()
ctx := context.Background()
// Reads automatically decrypt encrypted columns
var ssn string
err = db.QueryRowContext(ctx,
"SELECT SSN FROM Patients WHERE Id = @p1",
sql.Named("p1", 1)).Scan(&ssn)
if err != nil {
log.Fatal(err)
}
fmt.Println("SSN:", ssn)
// Parameters are automatically encrypted for encrypted columns
_, err = db.ExecContext(ctx,
"INSERT INTO Patients (Name, SSN) VALUES (@p1, @p2)",
sql.Named("p1", "Alice"),
sql.Named("p2", "123-45-6789"))
if err != nil {
log.Fatal(err)
}
}
匹配參數類型精確
Always Encrypted 參數加密比一般參數綁定更嚴格。 驅動程式在傳送值前會向 SQL Server 詢問加密元資料,因此 Go 參數型別必須與 SQL Server 的欄位型別非常匹配。
- Go
string參數預設會以nvarchar傳送。 - 使用驅動程式特定的類型,例如
mssql.NVarCharMax、mssql.DateTime1,或mssql.DateTimeOffset當加密欄位使用更特定的 SQL Server 類型時。 - 如果參數類型與加密欄位類型不符,查詢在參數加密中繼資料發現時可能會因類型不匹配而失敗。
例如,若加密欄位為 nvarchar(max),則偏好 mssql.NVarCharMax 在需要精確大字串匹配時:
_, err := db.ExecContext(ctx,
"INSERT INTO Patients (Notes) VALUES (@p1)",
sql.Named("p1", mssql.NVarCharMax("Sensitive note text")))
關於一般參數型別的指引,請參見 資料型別映射。
Limitations
- Always Encrypted 不支援批量複製操作。
-
azuresql驅動程式和 Always Encrypted 可搭配使用,但您必須同時匯入azuread和金鑰提供者套件。 - 對
char和varchar的加密插入與更新目前受到限制。 對於必須使用 Always Encrypted 的文字資料,建議使用加密nchar或nvarchar欄位。 - 不支援安全飛地。