常にgo-mssqldbで暗号化

go-mssqldbドライバーはクライアント側の機密データの暗号化および復号のためにAlways Encryptedをサポートしています。 有効化されると、ドライバーは暗号化された列から自動的にデータを復号し、暗号化された列に送られたパラメータ値を暗号化します。

Always Encryptedを有効にする

columnencryption接続パラメータをtrueに設定します:

sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&columnencryption=true

また、少なくとも1つのカラムマスターキー(CMK)プロバイダーパッケージをインポートする必要があります。 プロバイダーがいなければ、ドライバーは暗号鍵にアクセスできません。

列マスター キー プロバイダー

ドライバーは3つの主要なストアプロバイダーをサポートしています。 プロバイダーパッケージを副産物インポートとしてインポートして登録してください。

ローカル証明書(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 Identityライブラリでサポートされているその他の方法で認証情報を設定できます。 詳細については、「 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)
    }
}

パラメータの種類を正確に一致させる

常に暗号化されたパラメータ暗号化は通常のパラメータバインディングよりも厳格です。 ドライバーは値を送る前にSQL Serverに暗号化メタデータを求めるため、Goパラメータの型はSQL Serverの列型と密接に一致しなければなりません。

  • Go string パラメータはデフォルトで nvarchar として送信されます。
  • 暗号化された列がより特定のSQL Serverタイプを使う場合は、mssql.NVarCharMaxmssql.DateTime1mssql.DateTimeOffsetなどのドライバー固有のタイプを使いましょう。
  • パラメータ型が暗号化された列型と一致しない場合、パラメータ暗号化メタデータ発見中に型の不一致エラーが発生してクエリが失敗することがあります。

例えば、暗号化された列が 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 列を推奨します。
  • セキュアエンクレーブはサポートされていません。