コンテンツにスキップ
getnextpdf.com

Pro エディション

クラウド KMS 署名(AWS KMS、Azure Key Vault、GCP KMS)

NextPDF Pro は、クラウドの鍵管理サービス(KMS)に保持された鍵で PDF に署名します。サポートされるプロバイダーは、Amazon Web Services(AWS)KMS、Microsoft Azure Key Vault、Google Cloud Platform(GCP)Cloud KMS です。各プロバイダーは 1 つの署名コントラクトを実装するため、アプリケーションが依存するのはプロバイダークラスではなくコントラクトです。プロバイダーに送信されるのは署名属性のダイジェストのみで、署名操作のためにドキュメントがホストの外に出ることはありません。このページは振る舞いレベルの説明です。各プロバイダーが何を送信し何を受信するか、鍵バージョンがどのように解決されるか、そしてどこで鍵保管が NextPDF の責任ではなくなるかを示します。

このコントラクトは Core のハードウェアおよびクラウド署名コントラクトを拡張するため、クラウド KMS 戦略は Core 署名機能が使用するのと同じ署名経路に組み込まれます。

前提条件はフロントマターに記載されており、前提条件でも繰り返しています。

クラウド KMS 署名戦略は nextpdf/pro パッケージで提供され、pro ライセンス機能フラグでゲートされます。NextPDF Core はソフトウェア CMS 署名機能を提供し、NextPDF Enterprise は PKCS#11 を通じたハードウェア鍵保管を追加します。クラウド KMS 署名は Pro の機能であり、Enterprise は Pro に依存するため Enterprise でも利用できます。Pro エンタイトルメントが有効でないデプロイメントでは、これらの戦略クラスは読み込まれず、Core の署名コントラクトはそのまま変わらず動作し続けます。エディションを比較する

各クラウド KMS 署名機能は、Core の署名コントラクトを拡張する 1 つのプロバイダーコントラクトを実装します。このコントラクトは 3 つの要素を追加します。レジストリ検索用の安定したプロバイダー識別子、鍵バージョンを認識する署名メソッド、そしてオーケストレーターが署名前に互換性のあるプロバイダーを選択できるよう、プロバイダーがサポートするアルゴリズムの自己記述です。

署名フローはドキュメントをホスト上に保持します。

  1. Pro 署名セッションがドキュメントのダイジェストを計算し、CMS 署名属性を構築します。
  2. セッションは署名属性をハッシュ化し、そのダイジェストのみをプロバイダーに送信します。呼び出し元が提供したメッセージダイジェストを受け取って署名を返す外部署名サービスは、EU Digital Signature Service(DSS)リファレンスフレームワークに記述されているとおり、ドキュメントを自分の境界内に保つための確立されたパターンです。
  3. プロバイダーは解決した鍵バージョンでダイジェストに署名し、生の署名を返します。
  4. セッションは CMS SignedData を組み立て、PDF に埋め込みます。

各プロバイダーは純粋な PSR-18 Hypertext Transfer Protocol(HTTP)呼び出しで実装されており、クラウドベンダーのソフトウェア開発キット(SDK)への依存はありません。認証はアプリケーションに委ねられます。ベアラートークン(AWS、GCP)またはトークンもしくはサービスプリンシパルの資格情報(Azure)を提供します。各プロバイダーは出力を CMS 向けに正規化します。AWS と GCP は Rivest–Shamir–Adleman(RSA)署名を CMS にそのまま使える DER 形式で返します。プロバイダーが生の整数ペアとして返す楕円曲線デジタル署名アルゴリズム(ECDSA)署名(Azure)は DER エンコード形式に変換され、GCP は ECDSA をすでに DER エンコードされた形で返します。ECDSA の曲線とダイジェストは、RFC 5480 の推奨ペアリングに従って慣例どおりに対応付けられます。P-256 と SHA-256、P-384 と SHA-384、P-521 と SHA-512 です。

PSR-11 レジストリは識別子でプロバイダーを解決し、遅延ファクトリーをサポートします。Enterprise のセルフホスト顧客は、プロバイダーコントラクトを実装してレジストリにバインドすることで、NextPDF Pro をフォークすることなく独自の HSM または KMS ドライバーを登録できます。

各プロバイダーは異なる「アクティブバージョン」のプリミティブを公開しているため、デフォルトの鍵バージョンの振る舞いは異なります。

  • AWS KMSnull の鍵バージョンは鍵エイリアスを使用し、AWS はこれをプロバイダー側で現在の鍵バージョンに解決します。
  • Azure Key Vaultnull の鍵バージョンはバージョン指定なしの鍵 URL を使用し、Azure はこれを最新の有効なバージョンに解決します。明示的なオーバーライドは 32 文字の 16 進識別子でなければならず、それ以外の値は URL セグメントインジェクションを防ぐために拒否されます。
  • GCP Cloud KMS — 非対称署名エンドポイントは特定の暗号鍵バージョンのみで動作し、サーバー側の「アクティブバージョン」は存在しません。構成でバージョンを固定するか、明示的に渡す必要があります。どちらも設定されていない場合、署名機能は推測する代わりに鍵管理エラーを発生させます。

デプロイメントがどのモードを使用するかを文書化し、振る舞いが決定論的になるようにしてください。

  1. NextPDF Core と Pro パッケージをインストールし、有効な Pro ライセンスを保持します。
  2. 選択したプロバイダーで署名鍵をプロビジョニングし、その識別子を控えます(AWS の場合は鍵エイリアスまたは Amazon Resource Name、Azure の場合は Vault 名と鍵名、GCP の場合はプロジェクト、ロケーション、キーリング、暗号鍵、バージョン)。
  3. PSR-18 HTTP クライアントと、PSR-17 のリクエストファクトリーおよびストリームファクトリーを提供します。
  4. アプリケーションでプロバイダーの資格情報を取得します。AWS または GCP の場合はベアラートークン、Azure の場合は取得済みのトークンまたはサービスプリンシパルの資格情報です。トークンの取得はアプリケーションの責任であり、シークレットはシークレットマネージャーから供給し、決してソースコードからは供給しないでください。

各プロバイダーには、識別子と資格情報から構築される不変の構成オブジェクトがあります。共通の構成上の検討事項は次のとおりです。

  • プロバイダー識別子aws-kmsazure-keyvaultgcp-kms のいずれかで、レジストリの検索キーとして使用されます。
  • アルゴリズム — 署名セッションが渡すアルゴリズム名から呼び出しごとに選択されます。プロバイダーはサポートしていないアルゴリズムを拒否します。
  • 鍵バージョン — 構成で固定するか呼び出しごとに渡します。前述のプロバイダーごとのセマンティクスが適用されます。
  • 資格情報 — アプリケーションがシークレットマネージャーから供給するベアラートークンまたはサービスプリンシパルの資格情報です。
  1. 識別子と、シークレットマネージャーから読み込んだ資格情報からプロバイダーの構成を構築します。
  2. 構成、DER 形式の署名者証明書、証明書チェーン、PSR-18 クライアント、PSR-17 ファクトリーを用いてプロバイダー署名機能を構築します。
  3. 必要に応じて、オーケストレーターが名前で解決できるよう、PSR-11 レジストリにプロバイダーをその識別子で登録します。
  4. Pro 署名セッションを実行します。ダイジェストを計算し、署名属性を構築し、ダイジェストのみを渡してプロバイダーを呼び出します。
  5. 最も具体的な失敗(鍵管理、サポート外アルゴリズム、署名失敗)をキャッチし、シークレットを含まない構造的なメッセージをログに記録し、再スローします。
examples/pro/kms-provider-registry.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Pro\Security\Signing\Kms\KeyManagementProviderRegistry;
use NextPDF\Pro\Security\Signing\Kms\KmsSignerInterface;
/**
* Register cloud-KMS providers behind one registry resolved by identifier.
*
* Each provider is supplied as a lazy factory so a provider is only
* constructed when first resolved. The caller depends on the registry and
* the provider contract, not on a concrete provider class.
*
* @param array<non-empty-string, callable(): KmsSignerInterface> $factories
* Provider factories keyed by provider identifier.
*
* @return KeyManagementProviderRegistry The populated registry.
*/
function buildKmsRegistry(array $factories): KeyManagementProviderRegistry
{
$registry = new KeyManagementProviderRegistry();
foreach ($factories as $providerId => $factory) {
$registry->registerFactory($providerId, $factory);
}
return $registry;
}
examples/pro/kms-sign-guarded.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Pro\Security\Signing\Kms\KmsSignerInterface;
use NextPDF\Pro\Security\Exception\KeyManagementException;
use NextPDF\Pro\Security\Exception\SignatureFailedException;
use NextPDF\Pro\Security\Exception\UnsupportedAlgorithmException;
use Psr\Log\LoggerInterface;
final readonly class KmsSigningService
{
public function __construct(
private KmsSignerInterface $provider,
private LoggerInterface $logger,
) {}
/**
* Sign a signed-attributes digest with a pinned key version.
*
* Only the digest is sent to the provider; the document stays on the
* host. Each failure mode is caught as its most specific type so the
* caller can distinguish a key-version problem from a transport failure.
*
* @param string $digest The signed-attributes digest to sign.
* @param string $algorithm The OpenSSL-style algorithm name.
* @param string|null $keyVersion The pinned key version, or null for the
* provider default (per-provider semantics).
*
* @throws KeyManagementException When the key version is unknown or required and absent.
* @throws UnsupportedAlgorithmException When the provider does not support the algorithm.
* @throws SignatureFailedException When the provider sign operation fails.
*
* @return string The raw signature bytes (DER for RSA and ECDSA per CMS rules).
*/
public function sign(string $digest, string $algorithm, ?string $keyVersion): string
{
try {
return $this->provider->signWithVersion($digest, $algorithm, $keyVersion);
} catch (KeyManagementException | UnsupportedAlgorithmException | SignatureFailedException $e) {
$this->logger->error('KMS signing failed', [
'provider' => $this->provider->providerId(),
'reason' => $e->getMessage(),
]);
throw $e;
}
}
}
  1. 署名前にプロバイダーが、使用しようとしているアルゴリズムを自己記述していることを確認します。これにより、サポート外のアルゴリズムはプロバイダー呼び出し時ではなく選択時に捕捉されます。
  2. ダイジェストのみが送信されることを確認します。プロバイダーのリクエストボディにドキュメントのバイト列が現れてはなりません。リクエストが運ぶのは base64 エンコードされたダイジェストであり、ファイルではありません。
  3. ECDSA の場合、埋め込まれた署名が DER エンコードされていることを確認します。署名機能が生の整数ペアの署名を自動的に変換します。
  4. 署名済み PDF を、自分のトラストアンカーで構成した検証ツールで開き、署名が暗号学的に無傷であると報告されることを確認します。生成された署名は検証済みの署名ではありません。信頼の判断は検証者に属します。
  5. アプリケーションのログにトークン、資格情報、鍵素材が一切現れないことを確認します。
  • 鍵はプロバイダーに留まります。 クラウド KMS 戦略は連携ポイントであり、鍵ストアではありません。NextPDF Pro は KMS 戦略の秘密鍵を保持しません。
  • 境界を越えるのはダイジェストのみです。 セッションが送信するのはドキュメントではなく署名属性のダイジェストであり、これは EU DSS リファレンスフレームワークに記述されたメッセージダイジェスト入力のパターンです。
  • バイトレンジはエンジンが計算します。 呼び出し元から受け取ることは決してありません。
  • フェイルクローズド。 プロバイダー、ネットワーク、鍵バージョン、またはサポート外アルゴリズムの失敗は型付き例外を発生させます。セッションは未署名のドキュメントを暗黙のうちに生成することはなく、より弱いアルゴリズムに置き換えることも決してありません。
  • 資格情報はシークレットです。 トークンとサービスプリンシパルの資格情報はシークレットマネージャーから供給され、ログから除外されます。

このページは暗号署名に関わります。すべての規範的な出典はパラフレーズされており、規範的なテキストは一切再現していません。### 鍵保管の境界

鍵の保護は、鍵の取り扱い、構成された KMS、およびデプロイメントに依存します。NextPDF Pro が提供するのは KMS との連携であり、鍵ストアではありません。NextPDF Pro が FIPS 互換となるのは FIPS 検証済みの KMS または HSM に対して構成された場合のみです。NextPDF Pro 自体は FIPS 検証済みの暗号モジュールではなく、FIPS 認証の主張も行いません。

  • 不明または無効化された鍵バージョン。 プロバイダーは not-found または無効化されたバージョンの応答を、プロバイダーと鍵を示す鍵管理例外にマッピングします。
  • バージョンを固定していない GCP。 GCP 署名機能は、構成にも呼び出しにもバージョンが指定されていない場合、鍵管理エラーを発生させます。非対称署名エンドポイントは特定のバージョンのみで動作するためです。
  • サポート外アルゴリズム。 プロバイダーがサポートしていないアルゴリズムを要求すると、ネットワーク呼び出しの前にサポート外アルゴリズム例外が発生します。
  • トランスポートの失敗。 PSR-18 クライアントのエラーは署名失敗例外にマッピングされます。セッションが部分的な結果を生成することはありません。
  • 資格情報の欠落。 トークンもサービスプリンシパルの資格情報も持たない署名機能は、未認証でプロバイダーを呼び出す代わりに型付きエラーを発生させます。