Java / Spring Boot
Java で Crypto Agility Plane を導入します。インテントを解決し、解決されたアルゴリズムで処理を実行し、実際に実行された内容を観測します。
前提条件
- 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 で — 抽出してください。
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<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 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 での設定
cap.base-url=https://cockpit.example.com/api
cap.key=${CAP_KEY}@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_…
キーをコミットしないでください。
解決して署名を実行する
アルゴリズムをハードコードすることは決してありません。インテントを解決し、解決された アルゴリズムとポリシーが参照する鍵で処理を実行し、その後に観測します。
@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 は決定(アルゴリズム、ポスチャ、鍵参照、バックエンド)を解決します。
鍵のバイト列を保持することはありません。署名や暗号化そのものは、d が参照する鍵を用いて、
お使いのプロセス内または解決されたバックエンド上で実行されます。PQC およびハイブリッドの
アルゴリズムでは、本番環境において暗号処理は DuoKey のバックエンドで実行されます。
便利メソッド(protect / reveal)
対称鍵によるストレージとトークン化のために、クライアントはワンライナーを提供しています。
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)
で検出結果を確認します。
// 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)ポスチャの切り替え — コード変更ゼロ
現在
ハイブリッドポリシーの下では、resolve("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 エディションが必要です。 |