.NET / EF Core
.NET で Crypto Agility Plane を導入します。インテントを解決し、解決されたアルゴリズムで処理を実行し、実際に実行された内容を観測します。
前提条件
- .NET 6 以上(リファレンスクライアントは BCL のみを使用します: System.Net.Http、System.Text.Json、AesGcm)。
- 呼び出し元テナントの CAP API キー(dke_cap_…) — はじめにを参照してください。
- アクティブなテナントポリシー(テンプレートからブートストラップしてください)。
インストール
.NET クライアントは、Cockpit からダウンロードする単一の自己完結型クラス
DuoKey.Cap.CapClient です。NuGet の依存関係はありません — 基底クラスライブラリ
のみを使用します。ダウンロードエンドポイントは JSON エンベロープ(language、
filename、content)を返すため、レスポンスボディをそのまま保存するのではなく、
content フィールドを — 例えば jq で — 抽出してください。
curl -H "Authorization: Bearer $COCKPIT_SESSION_JWT" \
"https://cockpit.example.com/api/cap/sdk/download/dotnet" \
| jq -r '.content' > Cap/CapClient.csクライアントのインターフェース
| メンバー | 目的 |
|---|---|
new CapClient(string baseUrl, string capKey) | クライアントを作成します。baseUrl は Cockpit API のルート(…/api)、capKey は dke_cap_… キーです。 |
new CapClient(baseUrl, capKey, byte[]? dataKey) | 任意: ローカルのデモ用 Protect/Reveal に使う 32 バイトの鍵を指定します(以下の注意点を参照)。 |
Task<CapDecision> ResolveAsync(string dataClass, string purpose) | インテントを決定に解決します。 |
Task ObserveAsync(string dataClass, string purpose, string observedAlgorithm, string source) | 実際に実行されたアルゴリズムを報告します(ドリフト検出)。 |
Task<string> ProtectAsync(string value, string dataClass, string purpose) | 便利メソッド: resolve + 適用(デモ用ヘルパー — 注意点を参照)。 |
string Reveal(string tagged) | Protect で生成された値を元に戻します(デモ用ヘルパー)。 |
CapDecision は record であり、Algorithm、Posture、QuantumResistant、Backend を持ちます。
CapDecision d = await cap.ResolveAsync("pan", "storage");
d.Algorithm; // e.g. "aes256-gcm"
d.Posture; // "classical" | "hybrid" | "pqc_only"
d.QuantumResistant; // false for classical, true otherwise
d.Backend; // "software" | "fips1403_hsm" | "pqc_capable" | "local_tokenizer"依存性注入への登録
{
"Cap": {
"BaseUrl": "https://cockpit.example.com/api"
}
}builder.Services.AddSingleton(sp =>
{
var cfg = sp.GetRequiredService<IConfiguration>();
var baseUrl = cfg["Cap:BaseUrl"]!;
var capKey = Environment.GetEnvironmentVariable("CAP_KEY")!;
return new DuoKey.Cap.CapClient(baseUrl, capKey);
});キーは環境変数(CAP_KEY)またはシークレットマネージャーからバインドしてください。
dke_cap_… キーをコミットしないでください。
解決して署名を実行する
public class SignatureService
{
private readonly CapClient _cap;
public SignatureService(CapClient cap) => _cap = cap;
public async Task<byte[]> SignAsync(byte[] payload)
{
// 1) Resolve WHAT (pii + sign) -> HOW
CapDecision d = await _cap.ResolveAsync("pii", "sign");
// 2) Run the signature with d.Algorithm using the referenced key.
string algorithm = d.Algorithm; // e.g. "hybrid-ml-dsa65-ecdsa-p256"
byte[] signature = _signer.Sign(payload, algorithm);
// 3) Close the loop: report what actually ran.
await _cap.ObserveAsync("pii", "sign", algorithm, "payments-svc");
return signature;
}
}EF Core でフィールドを保護する
よくあるパターンは、CAP に委譲する EF Core の値コンバーターで機密性の高い列を保護すること です。インテント(データクラス+目的)は列ごとに固定され、アルゴリズムはポリシーによって 解決されます。
public class Customer
{
public int Id { get; set; }
// The plane resolves HOW; this column just declares it is a PAN to be tokenized.
public string Pan { get; set; } = default!;
}
// A converter that tokenizes on save and reveals on read via CAP.
public sealed class CapTokenizeConverter : ValueConverter<string, string>
{
public CapTokenizeConverter(CapClient cap)
: base(v => cap.ProtectAsync(v, "pan", "tokenize").GetAwaiter().GetResult(),
v => cap.Reveal(v)) { }
}
protected override void OnModelCreating(ModelBuilder b) =>
b.Entity<Customer>().Property(c => c.Pan).HasConversion(new CapTokenizeConverter(_cap));ダウンロードしたリファレンスクライアントでは、ProtectAsync/Reveal は
aes256-gcm をローカルのデモ用鍵と代用のトークナイザーで実行します。配線と
動作確認のためのものであり、本番用ではありません。本番のトークン化と vault に裏付けられた
暗号化は、ポリシーの key_ref に対してサーバー側で実行されます。デモ用のヘルパーを本物の
トークン化として出荷しないでください。
観測とドリフト
ObserveAsync(...) は、実際に実行されたアルゴリズムを報告します。それが解決された決定より
弱い場合、CAP はドリフト検出結果を記録し(耐量子性が保たれていれば warning、
クラシックに低下していれば critical)、Cockpit で確認できます。
await _cap.ObserveAsync("pii", "sign", "ecdsa-p256", "legacy-batch");
// -> CAP flags a drift finding: declared hybrid, observed classicalポスチャの切り替え — コード変更ゼロ
現在
ハイブリッドポリシーの下では、ResolveAsync("pii","sign") は hybrid-ml-dsa65-ecdsa-p256 を返します。
セキュリティが基準を引き上げる
新しいポリシーバージョンが pqc_only ポスチャを設定します(または cnsa_2_0 をブートストラップします)。
次回の resolve
同じコードが今度は ml-dsa65 を受け取ります。再コンパイルも再デプロイも不要です。
エラー処理
| 状況 | 返される内容 | 対処方法 |
|---|---|---|
| テナントにアクティブなポリシーがない | resolved: false、理由は "no active CAP policy…" | テンプレートからポリシーをブートストラップします。 |
| ポスチャの下限を満たせない | resolved: false と理由 | ポリシールール、または要求された所在地を修正します。 |
| 不明なデータクラス / 目的 | バリデーションエラー | 有効なデータクラスと、storage / transport / tokenize / sign のいずれかを使用します。 |
| 無効または失効したキー | /cap/sdk/* からの HTTP 401/403 | 新しい dke_cap_ キーを発行します。 |
| cap.enabled 機能が無効 | アクセス拒否 | テナントには Enterprise または Free Trial エディションが必要です。 |