メインコンテンツまでスキップ
適用対象:
.NET 6 以上EF CoreDuoKey Cockpit

前提条件

  • .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 で — 抽出してください。

ダウンロードBASH
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 fieldsCSHARP
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"

依存性注入への登録​

appsettings.jsonJSON
{
"Cap": {
  "BaseUrl": "https://cockpit.example.com/api"
}
}
Program.csCSHARP
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_… キーをコミットしないでください。

解決して署名を実行する​

SignatureService.csCSHARP
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 の値コンバーターで機密性の高い列を保護すること です。インテント(データクラス+目的)は列ごとに固定され、アルゴリズムはポリシーによって 解決されます。

Customer.cs + converterCSHARP
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 で確認できます。

Drift-honest telemetryCSHARP
await _cap.ObserveAsync("pii", "sign", "ecdsa-p256", "legacy-batch");
// -> CAP flags a drift finding: declared hybrid, observed classical

ポスチャの切り替え — コード変更ゼロ​

1

現在

ハイブリッドポリシーの下では、ResolveAsync("pii","sign") は hybrid-ml-dsa65-ecdsa-p256 を返します。

2

セキュリティが基準を引き上げる

新しいポリシーバージョンが pqc_only ポスチャを設定します(または cnsa_2_0 をブートストラップします)。

3

次回の 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 エディションが必要です。