콘텐츠로 이동
getnextpdf.com

Pro 에디션

Cloud 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입니다. 각 공급자는 하나의 서명 계약을 구현하므로, 애플리케이션은 공급자 클래스가 아니라 계약에 의존합니다. 서명된 속성 다이제스트만 공급자로 전송되며, 서명 작업을 위해 문서가 호스트를 벗어나는 일은 없습니다. 이 페이지는 동작 수준입니다. 즉, 각 공급자가 무엇을 전송하고 수신하는지, 키 버전이 어떻게 해석되는지, 키 보관이 어디에서 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. Pro 서명 세션이 문서 다이제스트를 계산하고 CMS 서명된 속성을 빌드합니다.
  2. 세션은 서명된 속성을 해시하고 해당 다이제스트만 공급자로 전송합니다. 호출자가 제공한 메시지 다이제스트를 받아 서명을 반환하는 외부 서명 서비스는 문서를 경계 내부에 유지하기 위한 확립된 패턴으로, EU 디지털 서명 서비스(DSS) 레퍼런스 프레임워크에 기술되어 있습니다.
  3. 공급자는 해석한 키 버전으로 다이제스트를 서명하고 원시 서명을 반환합니다.
  4. 세션은 CMS SignedData를 조립하고 이를 PDF에 포함합니다.

공급자는 순수 PSR-18 Hypertext Transfer Protocol(HTTP) 호출 위에 구현됩니다 — 클라우드 벤더 소프트웨어 개발 키트(SDK) 의존성이 없습니다. 인증은 애플리케이션에 위임됩니다. 즉, 베어러 토큰(AWS, GCP) 또는 토큰이나 서비스 주체 자격 증명(Azure)을 제공합니다. 각 공급자는 출력을 CMS에 맞게 정규화합니다. AWS와 GCP는 CMS에 바로 사용할 수 있는 DER 형식의 Rivest–Shamir–Adleman(RSA) 서명을 반환합니다. 공급자가 원시 정수 쌍으로 반환하는 타원 곡선 디지털 서명 알고리즘(ECDSA) 서명(Azure)은 DER 인코딩 형식으로 변환되며, GCP는 이미 DER 인코딩된 ECDSA를 반환합니다. ECDSA 곡선과 다이제스트는 관례적으로 짝지어집니다 — P-256은 SHA-256, P-384는 SHA-384, P-521은 SHA-512 — RFC 5480의 권장 짝짓기에 따릅니다.

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의 경우 볼트 및 키 이름, GCP의 경우 프로젝트, 위치, 키 링, 암호 키, 버전).
  3. PSR-18 HTTP 클라이언트와 PSR-17 요청 및 스트림 팩토리를 제공하십시오.
  4. 애플리케이션에서 공급자 자격 증명을 획득하십시오. AWS 또는 GCP의 경우 베어러 토큰, Azure의 경우 사전 획득한 토큰 또는 서비스 주체 자격 증명입니다. 토큰 획득은 애플리케이션의 책임입니다. 비밀은 소스가 아니라 비밀 관리자에서 제공하십시오.

각 공급자는 식별자와 자격 증명으로부터 빌드된 불변 구성 객체를 가집니다. 공통 구성 고려 사항은 다음과 같습니다.

  • 공급자 식별자aws-kms, azure-keyvault, 또는 gcp-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 검증 KMS 또는 HSM에 대해 구성된 경우에만 FIPS 호환이며, 그 자체가 FIPS 검증 암호화 모듈은 아니고 어떠한 FIPS 인증 주장도 하지 않습니다.

  • 알 수 없거나 비활성화된 키 버전. 공급자는 not-found 또는 비활성화된 버전 응답을 공급자와 키를 명시하는 키 관리 예외로 매핑합니다.
  • 고정된 버전이 없는 GCP. 비대칭 서명 엔드포인트는 특정 버전에서만 작동하므로, 구성과 호출 모두 버전을 제공하지 않으면 GCP 서명자는 키 관리 오류를 발생시킵니다.
  • 미지원 알고리즘. 공급자가 지원하지 않는 알고리즘을 요청하면 어떤 네트워크 호출도 하기 전에 미지원 알고리즘 예외를 발생시킵니다.
  • 전송 실패. PSR-18 클라이언트 오류는 서명 실패 예외로 매핑됩니다. 세션은 부분 결과를 생성하지 않습니다.
  • 누락된 자격 증명. 토큰도 서비스 주체 자격 증명도 없는 서명자는 인증 없이 공급자를 호출하는 대신 타입이 지정된 오류를 발생시킵니다.