メインコンテンツまでスキップ
適用対象:
Java 17 以上Spring BootDuoKey Cockpit

前提条件

  • JDK 17 以上(リファレンスクライアントは `java.net.http.HttpClient` と Java の record を使用するため、JDK 16 以上が必要です)。
  • 呼び出し元テナントの CAP API キー(dke_cap_…) — はじめにを参照してください。
  • アクティブなテナントポリシー(テンプレートからブートストラップしてください)。

インストール​

Java クライアントは、Cockpit からダウンロードする単一の自己完結型クラス ch.duokey.cap.CapClient です。依存関係は JDK の HTTP クライアントと、JSON 用の Jackson のみです。

ダウンロードエンドポイントは JSON エンベロープ(language、filename、content)を 返すため、レスポンスボディをそのまま保存するのではなく、content フィールドを — 例えば jq で — 抽出してください。

ダウンロードBASH
curl -H "Authorization: Bearer $COCKPIT_SESSION_JWT" \
"https://cockpit.example.com/api/cap/sdk/download/java" \
| jq -r '.content' > src/main/java/ch/duokey/cap/CapClient.java
pom.xml (Jackson)XML
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.8</version>
</dependency>

クライアントのインターフェース​

メンバー目的
new CapClient(String baseUrl, String capKey)クライアントを作成します。baseUrl は Cockpit API のルート(…/api)、capKey は dke_cap_… キーです。
new CapClient(baseUrl, capKey, byte[] dataKey)任意: ローカルのデモ用 protect/reveal に使う 32 バイトの鍵を指定します(以下の注意点を参照)。
CapDecision resolve(String dataClass, String purpose)インテントを決定に解決します。
void observe(String dataClass, String purpose, String observedAlgorithm, String source)実際に実行されたアルゴリズムを報告します(ドリフト検出)。
String protect(String value, String dataClass, String purpose)便利メソッド: resolve + 適用(デモ用ヘルパー — 注意点を参照)。
String reveal(String tagged)protect で生成された値を元に戻します(デモ用ヘルパー)。

CapDecision は record であり、algorithm()、posture()、quantumResistant()、 backend() を持ちます。

CapDecision fieldsJAVA
CapDecision d = cap.resolve("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"

Spring での設定​

application.propertiesPROPERTIES
cap.base-url=https://cockpit.example.com/api
cap.key=${CAP_KEY}
CapConfig.javaJAVA
@Configuration
public class CapConfig {
  @Bean
  CapClient capClient(
          @Value("${cap.base-url}") String baseUrl,
          @Value("${cap.key}") String capKey) {
      return new CapClient(baseUrl, capKey);
  }
}
キーをソースコードに含めないでください

cap.key は環境変数またはシークレットマネージャーからバインドしてください。dke_cap_… キーをコミットしないでください。

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

アルゴリズムをハードコードすることは決してありません。インテントを解決し、解決された アルゴリズムとポリシーが参照する鍵で処理を実行し、その後に観測します。

SignatureService.javaJAVA
@Service
public class SignatureService {

  private final CapClient cap;

  public SignatureService(CapClient cap) { this.cap = cap; }

  public byte[] sign(byte[] payload) {
      // 1) Resolve WHAT (pii + sign) -> HOW (algorithm, posture, key, backend)
      CapDecision d = cap.resolve("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.
      cap.observe("pii", "sign", algorithm, "payments-svc");
      return signature;
  }
}
CAP が行うことと行わないこと

CAP は決定(アルゴリズム、ポスチャ、鍵参照、バックエンド)を解決します。 鍵のバイト列を保持することはありません。署名や暗号化そのものは、d が参照する鍵を用いて、 お使いのプロセス内または解決されたバックエンド上で実行されます。PQC およびハイブリッドの アルゴリズムでは、本番環境において暗号処理は DuoKey のバックエンドで実行されます。

便利メソッド(protect / reveal)​

対称鍵によるストレージとトークン化のために、クライアントはワンライナーを提供しています。

protect / revealJAVA
String tagged = cap.protect("4111111111111111", "pan", "tokenize");
String pan    = cap.reveal(tagged);
リファレンス実装のヘルパーは例示目的です

ダウンロードしたリファレンスクライアントでは、protect/reveal は aes256-gcm をローカルのデモ用鍵と代用のトークナイザーで実行します。これらは 配線と動作確認のためのものであり、本番用ではありません。本番のトークン化と vault に裏付けられた 暗号化は、ポリシーの key_ref に対してサーバー側で実行されます。デモ用の protect() を本物のトークン化として出荷しないでください。

観測とドリフト​

observe(...) は、実際に実行されたアルゴリズムを報告します。それが解決された決定より弱い 場合、CAP はドリフト検出結果を記録します(耐量子性が保たれていれば warning、 クラシックに低下していれば critical)。セキュリティチームは Cockpit(GET /api/cap/drift) で検出結果を確認します。

Reporting drift-honest telemetryJAVA
// Suppose a legacy path signed with plain ECDSA while policy resolved to hybrid:
cap.observe("pii", "sign", "ecdsa-p256", "legacy-batch");
// -> CAP flags a drift finding for pii.sign (declared hybrid, observed classical)

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

1

現在

ハイブリッドポリシーの下では、resolve("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 エディションが必要です。