Enterprise 에디션
신뢰 목록(TSL)
한눈에 보기
섹션 제목: “한눈에 보기”EU 서명 검증은 공표된 사실에서 출발합니다: 어떤 제공자가 적격 상태를 보유하는가. 그 사실은 신뢰 목록(TSL)에 담깁니다 — 각 회원국이 공표하는 서명된 XML 문서로, EU의 신뢰 목록 목록(LOTL)이 색인합니다. NextPDF\Enterprise\Security\Tsl\TslPolicyEnforcer는 TSL URL 또는 원시 XML을 신뢰할 수 있는 TslDocument로 바꿔줍니다. 이 클래스는 보호된 HTTPS를 통해 페치하고, 고정한 앵커에 대해 XMLDSig 서명을 검증하며, 강화된 XML을 파싱하고, 오래된 목록을 거부합니다. 한 번 더 호출하는 TslTrustAnchorProvider::buildBundle()은 활성 CA/QC 서비스를 버전 관리 신뢰 앵커 번들로 변환합니다. 모든 게이트는 fail-closed로 동작하며, 모든 거부는 타입이 지정된 예외입니다.
이 페이지는 목록 수집과 앵커 파생을 담당합니다. 인증서 경로 검증은 서명 검증에서 다룹니다. eIDAS 보증 수준 매핑은 eIDAS 보증 수준에서 다룹니다. 컨테이너 신뢰 바인딩은 ASiC 신뢰 바인딩에서 다룹니다.
제공 여부 및 라이선스
섹션 제목: “제공 여부 및 라이선스”이 기능은 NextPDF Enterprise(nextpdf/enterprise)에 포함되며 Enterprise 티어 라이선스 봉투로 활성화됩니다. 해당 권한이 없는 배포 환경은 이 기능의 클래스를 로드하지 않습니다. 에디션 비교 및 라이선스 받기.
composer require nextpdf/enterprise활성화에는 Enterprise 라이선스 봉투가 필요합니다. 설치 및 인증을 참조하세요. 이 페이지의 클래스는 NextPDF\Enterprise\Security\Tsl 아래에 있으며, 네트워크 정책 타입은 NextPDF\Enterprise\Security 아래에 있습니다. 온라인 페치에는 추가로 PSR-18 클라이언트와 PSR-17 팩토리(예: guzzlehttp/guzzle)가 필요합니다.
개념 개요
섹션 제목: “개념 개요”eIDAS 제22조에 따라, 각 회원국은 자국의 적격 신뢰 서비스 제공자에 대한 신뢰 목록을 공표하며, 자동 처리를 위해 서명 또는 봉인합니다. ETSI TS 119 612는 XML 형식을 정의합니다. 이 목록은 세 가지 검사가 뒷받침하는 만큼만 신뢰할 수 있습니다: 서명, 구조, 그리고 신선도. NextPDF는 이를 그 순서대로, 하나의 파이프라인으로 실행합니다:
- 페치 —
TslFetcher는 XML을 HTTPS로만 가져옵니다. SSRF 가드가 모든 송신 이전에 호스트를 검증합니다. 응답은 크기가 제한되며, PSR-16 캐시는ETag재검증과 에어갭 읽기를 가능하게 합니다. - 검증 —
TslSignatureVerifier는 봉투형(enveloped) XMLDSig 서명을 확인합니다. 서명 인증서는 대역 외에서 고정한 신뢰 앵커까지 체인을 이뤄야 하며, 문서 내부의 어떤 것도 그 자체로는 신뢰되지 않습니다. - 파싱 —
TslXmlParser는 스킴 정보와 모든 TSP 서비스를 불변TslDocument로 추출합니다. DOCTYPE를 지닌 문서는 어떤 엔티티 테이블도 구축되기 전에 거부됩니다. - 집행 — 목록의
NextUpdate시점이 이미 지나지 않았어야 합니다. 오래된 목록은 소비되지 않고 폐기됩니다.
TslPolicyEnforcer는 이 네 단계를 모두 조합합니다. 여기서 나온 TslDocument는 모든 게이트를 통과한 것입니다. 그다음 TslTrustAnchorProvider::buildBundle()은 granted 상태이면서 CA/QC 유형인 서비스를 필터링하여 EnterpriseCaTrustAnchorBundle을 방출합니다: 고정된 PEM 앵커, tsl-<territory>-seq<N> 버전, 그리고 SHA-256 무결성 다이제스트. 그 번들이 경로 검증과 ASiC 신뢰 바인딩이 소비하는 대상입니다.
동일한 메커니즘이 LOTL 워크플로도 처리합니다. LOTL을 수동으로 고정한 앵커에 대해 검증한 다음, 각 회원국 TSL을 LOTL이 해당 목록에 대해 선언하는 서명 인증서에 대해 검증합니다.
왜 이런 방식으로 작동하는가
섹션 제목: “왜 이런 방식으로 작동하는가”핵심을 이루는 결정은 일반적인 XMLDSig 대신 고정된 최소 검증 프로파일을 쓰는 것입니다. 유연한 XML 서명 처리 — 임의의 변환 체인, 공격자가 선언하는 ID 참조, 알고리즘 민첩성 — 는 역사적으로 검증기가 무너지는 지점입니다. 그래서 검증기는 정확히 하나의 처리 모델만 받아들입니다: 배타적 C14N, 루트를 포괄하는 참조, 그리고 두 단계 변환 파이프라인 [enveloped-signature, exclusive-C14N]이며, 그 밖의 모든 것은 fail-closed로 거부됩니다. 신뢰는 결코 문서 자체에서 부트스트랩되지 않습니다: KeyInfo 인증서는 오직 당신이 구성한 앵커까지만 체인을 이룹니다. 신선도는 TslDocument 자체에 존재하므로, 하나의 선택적 협력자가 아니라 모든 소비자 경로가 이를 집행합니다. 그 결과는 테스트 가능하고, 결정론적이며, 무엇을 거부하는지에 대해 정직한 작은 커널입니다.
설계 배경: 적격 서명, 설명.
API 표면
섹션 제목: “API 표면”TslPolicyEnforcer
섹션 제목: “TslPolicyEnforcer”오케스트레이션된 진입점: 페치, 검증, 파싱, 신선도 검사를 한 번의 호출로 수행합니다.
public function __construct( private readonly TslFetcher $fetcher, private readonly TslSignatureVerifier $verifier, private readonly TslXmlParser $parser,) {}public function fetchAndVerify(string $url): TslDocumentpublic function verifyXml(string $xml): TslDocument던지거나 실패하는 경우: 페치 단계에서 TslFetchException 및 NextPDF\Enterprise\Security\NetworkPolicyViolation; 서명 검증에서 TslSignatureException; 파싱, 비정규 NextUpdate 값, 또는 오래된 목록에서 TslParseException. 두 메서드 모두 모든 게이트를 통과한 경우에만 TslDocument를 반환합니다. 여기서 신선도 게이트는 NextUpdate를 현재 시스템 시계와 비교합니다.
TslFetcher
섹션 제목: “TslFetcher”ETag 기반 캐싱과 네트워크 정책 게이트를 갖춘 HTTP 페처.
public function __construct( private readonly ClientInterface $httpClient, private readonly RequestFactoryInterface $requestFactory, private readonly ?CacheInterface $cache = null, private readonly int $defaultTtlSeconds = 3600, private readonly int $maxBytes = 16_777_216, private readonly NetworkPolicy $networkPolicy = NetworkPolicy::ONLINE,) {}public function fetch(string $url): string던지거나 실패하는 경우: 비HTTPS URL, 거부된(SSRF) 호스트, HTTP 오류 상태, 초과 크기 응답, 또는 빈 본문에서 TslFetchException; NetworkPolicy::STRICT_OFFLINE이 활성화되어 있고 캐시된 본문이 없을 때 NetworkPolicyViolation. 캐시된 본문은 304 Not Modified 재검증을 충족하며, STRICT_OFFLINE 하에서 제공되는 유일한 본문입니다. 캐시 항목은 $defaultTtlSeconds 동안 유지됩니다.
TslSignatureVerifier
섹션 제목: “TslSignatureVerifier”서명된 신뢰 목록을 위한 XMLDSig 검증기.
public function __construct( private readonly array $trustAnchorsPem, private readonly int $clockTolerance = 0,)public function verify(string $xml): stringverify()는 $trustAnchorsPem 중 하나까지 체인을 이룸이 증명된 서명 인증서의 PEM을 반환합니다. 앵커 목록이 비어 있으면 생성자가 InvalidArgumentException을 던집니다. $clockTolerance는 인증서 유효 기간 창을 초 단위로 대칭적으로 넓힙니다.
허용되는 프로파일은 고정되어 있습니다. 서명 알고리즘: ALLOWED_SIG_ALG 허용 목록(rsa-sha256/384/512, ecdsa-sha256/384/512). 다이제스트: ALLOWED_DIGEST_ALG 허용 목록(SHA-256, SHA-384, SHA-512). 정규화: 배타적 C14N 1.0만 허용. SHA-1과 MD5는 unsupported_algorithm으로 거부됩니다.
던지거나 실패하는 경우: 기계 판독 가능한 reason을 담은 TslSignatureException:
| 사유 코드 | 의미 |
|---|---|
missing_signature | 문서에 ds:Signature 요소가 없습니다. |
untrusted_signer | KeyInfo 인증서가 구성된 앵커까지 체인을 이루지 못합니다. |
invalid_signature | 구조적 결함, 또는 RSA/ECDSA 검사 실패. |
digest_mismatch | 참조 다이제스트가 정규화된 문서와 일치하지 않습니다. |
unsupported_algorithm | 허용 목록을 벗어난 서명 또는 다이제스트 알고리즘. |
unsupported_transform | 고정 프로파일을 벗어난 정규화 또는 변환 파이프라인. |
expired_anchor | 체인 인증서가 유효 기간 창을 벗어났거나, 그 유효 기간을 파싱할 수 없습니다. |
TslXmlParser
섹션 제목: “TslXmlParser”서명에 무관한 구조 파서. 호출자는 그 출력을 신뢰하기 전에 반드시 검증해야 합니다. TslPolicyEnforcer는 그 순서를 대신 집행해 줍니다.
public function parse(string $xml): TslDocument던지거나 실패하는 경우: XML이 DOCTYPE를 선언하거나(XXE 및 엔티티 확장 강화), 파싱할 수 없거나, TrustServiceStatusList 루트가 없거나, 무효한 TSLSequenceNumber를 지닐 때 TslParseException. 이 클래스는 네임스페이스 상수 NS_TSL, NS_DSIG, NS_TSL_X를 노출합니다.
TslDocument와 TspService
섹션 제목: “TslDocument와 TspService”TslDocument는 불변 값 객체입니다: schemeTerritory, schemeOperatorName, tslType, sequenceNumber, issueDateTime, nextUpdate, tspServices, 그리고 rawXmlSha256(원시 바이트에 대한 증거 해시).
public function isStale(DateTimeImmutable $now): boolpublic function assertFresh(DateTimeImmutable $now): voidpublic function servicesOfType(string $serviceTypeIdentifier): arraypublic function activeServices(): array던지거나 실패하는 경우: nextUpdate가 명시적 Z 또는 숫자 오프셋을 갖춘 정규 UTC dateTime이 아닐 때 isStale()과 assertFresh()는 TslParseException을 던지며, 오래된 목록은 assertFresh()가 던지게 만듭니다. activeServices()는 granted 상태의 서비스만 반환합니다. servicesOfType()은 ETSI 서비스 유형 URI로 필터링합니다.
각 TspService 항목은 tspName, serviceName, serviceTypeIdentifier, serviceStatus, statusStartingTime, serviceCertificatePem, qualifiers, additionalServiceInformation를 노출하며, 추가로:
public function isGranted(): boolpublic function isQualifiedCa(): bool유용한 상수: TspService::STATUS_GRANTED, TspService::STATUS_WITHDRAWN, TspService::TYPE_CA_QC, TspService::TYPE_OCSP_QC, TspService::TYPE_TSA_QTST. 한정자 URI(예: TspServiceQualifier::FOR_ESIG, FOR_ESEAL, QSCD_STATEMENT, NO_QSCD)는 eIDAS 매핑 계층을 위해 TspServiceQualifier에 노출됩니다.
TslTrustAnchorProvider와 앵커 번들
섹션 제목: “TslTrustAnchorProvider와 앵커 번들”public function buildBundle(TslDocument $tsl, DateTimeImmutable $now): EnterpriseCaTrustAnchorBundle던지거나 실패하는 경우: TSL이 $now 시점에 오래되었을 때, nextUpdate가 정규 UTC 값이 아닐 때, 또는 목록에 활성 CA/QC 서비스가 없을 때 TslParseException.
BC 참고 —
buildBundle($now)신선도 규칙.buildBundle()은 검증 시점을 요구하며, 앵커를 하나라도 추출하기 전에TslDocument::assertFresh($now)를 호출합니다. 이전 리비전은 아무런 신선도 검사 없이 파서가 생성한TslDocument에서 앵커를 파생할 수 있었습니다. 캐시되었거나 보관된 목록을 공급하던 호출자는 이제 자신의 검증이 실행되는 시점을 전달해야 합니다. 해당 시점에 오래된 목록은 신뢰 앵커를 조용히 심는 대신 던집니다.
반환된 EnterpriseCaTrustAnchorBundle은 읽기 전용 값 객체입니다: anchorsPem(PEM 앵커), bundleVersion(tsl-<territory>-seq<N>), 그리고 bundleSha256(정규화된 PEM 연결에 대한 무결성 다이제스트). 이는 buildBundle()에서 얻으세요. 직접 손으로 구성하지 마십시오 — 생성자는 다이제스트 불일치 또는 잘못된 형식의 PEM에서 InvalidArgumentException을 던집니다.
public function containsFingerprint(string $anchorDerSha256Hex): boolpublic static function computeBundleSha256(array $anchorsPem): string코드 예제 — 빠른 시작
섹션 제목: “코드 예제 — 빠른 시작”로컬에 미러링한 신뢰 목록을 인증하고 소비합니다. 이 경로에는 HTTP 의존성이 필요 없습니다: 검증하고, 파싱한 다음, 검증 시점에 신선도를 게이팅합니다.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Tsl\TslParseException;use NextPDF\Enterprise\Security\Tsl\TslSignatureException;use NextPDF\Enterprise\Security\Tsl\TslSignatureVerifier;use NextPDF\Enterprise\Security\Tsl\TslXmlParser;
// The list-signing certificate, pinned OUT-OF-BAND. Never take it from the list itself.$pinnedAnchorPem = (string) file_get_contents(__DIR__ . '/tsl-signer-anchor.pem');
// A trusted-list XML document you mirrored locally.$tslXml = (string) file_get_contents(__DIR__ . '/member-state-tsl.xml');
try { // 1. Authenticate: XMLDSig must verify AND the signer must chain to the pinned anchor. (new TslSignatureVerifier(trustAnchorsPem: [$pinnedAnchorPem]))->verify($tslXml);
// 2. Parse the now-authenticated bytes. $tsl = (new TslXmlParser())->parse($tslXml);
// 3. Freshness: refuse a list whose NextUpdate has passed. $tsl->assertFresh(new DateTimeImmutable('now', new DateTimeZone('UTC')));} catch (TslSignatureException $e) { fwrite(STDERR, "TSL rejected ({$e->reason}): {$e->getMessage()}" . PHP_EOL); exit(1);} catch (TslParseException $e) { fwrite(STDERR, 'TSL unusable: ' . $e->getMessage() . PHP_EOL); exit(1);}
echo "Territory: {$tsl->schemeTerritory}\n";echo "Sequence: {$tsl->sequenceNumber}\n";echo 'Active services: ' . count($tsl->activeServices()) . "\n";예상 출력(값은 목록에 따라 달라집니다):
Territory: DESequence: 127Active services: 143코드 예제 — 프로덕션
섹션 제목: “코드 예제 — 프로덕션”전체 온라인 파이프라인을 연결합니다: 캐싱을 갖춘 보호된 페치, 서명 검증, 파싱, 신선도, 그리고 앵커 번들 파생. 각 실패 클래스는 개별적으로 포착되고 보고됩니다.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client;use GuzzleHttp\Psr7\HttpFactory;use NextPDF\Enterprise\Security\NetworkPolicy;use NextPDF\Enterprise\Security\NetworkPolicyViolation;use NextPDF\Enterprise\Security\Tsl\TslFetchException;use NextPDF\Enterprise\Security\Tsl\TslFetcher;use NextPDF\Enterprise\Security\Tsl\TslParseException;use NextPDF\Enterprise\Security\Tsl\TslPolicyEnforcer;use NextPDF\Enterprise\Security\Tsl\TslSignatureException;use NextPDF\Enterprise\Security\Tsl\TslSignatureVerifier;use NextPDF\Enterprise\Security\Tsl\TslTrustAnchorProvider;use NextPDF\Enterprise\Security\Tsl\TslXmlParser;use Symfony\Component\Cache\Adapter\FilesystemAdapter;use Symfony\Component\Cache\Psr16Cache;
// Any PSR-18 client, PSR-17 factory, and PSR-16 cache work; these are examples.$enforcer = new TslPolicyEnforcer( fetcher: new TslFetcher( httpClient: new Client(), requestFactory: new HttpFactory(), cache: new Psr16Cache(new FilesystemAdapter('tsl')), defaultTtlSeconds: 3600, maxBytes: 16_777_216, networkPolicy: NetworkPolicy::ONLINE, ), verifier: new TslSignatureVerifier( trustAnchorsPem: [(string) file_get_contents(__DIR__ . '/tsl-signer-anchor.pem')], clockTolerance: 300, ), parser: new TslXmlParser(),);
// Use the official publication URL for your scheme territory (HTTPS required).$tslUrl = 'https://trusted-lists.example.eu/member-state-tsl.xml';$now = new DateTimeImmutable('now', new DateTimeZone('UTC'));
try { $tsl = $enforcer->fetchAndVerify($tslUrl); $bundle = (new TslTrustAnchorProvider())->buildBundle($tsl, $now);} catch (NetworkPolicyViolation $e) { // Air-gapped posture: egress forbidden and no cached body available. fwrite(STDERR, 'Network policy: ' . $e->getMessage() . PHP_EOL); exit(75);} catch (TslFetchException $e) { // Transport layer: SSRF-rejected URL, HTTP error, oversized or empty body. fwrite(STDERR, 'Fetch failed: ' . $e->getMessage() . PHP_EOL); exit(1);} catch (TslSignatureException $e) { // Authentication layer: treat as a potential attack, not a retry case. fwrite(STDERR, "Signature rejected ({$e->reason}): {$e->getMessage()}" . PHP_EOL); exit(1);} catch (TslParseException $e) { // Structure or freshness: stale list, malformed NextUpdate, no active CA/QC services. fwrite(STDERR, 'List unusable: ' . $e->getMessage() . PHP_EOL); exit(1);}
printf( "Anchor bundle %s: %d anchors (sha256 %s...)\n", $bundle->bundleVersion, count($bundle->anchorsPem), substr($bundle->bundleSha256, 0, 12),);예상 출력(값은 목록에 따라 달라집니다):
Anchor bundle tsl-de-seq127: 96 anchors (sha256 4b0e2a9f31c8...)번들에 대해 수행하는 모든 검증마다 bundleVersion과 bundleSha256을 기록하세요. 이들은 각 판정의 이면에 있는 정확한 앵커 집합을 명명합니다.
예외 상황 및 유의점
섹션 제목: “예외 상황 및 유의점”- 집행기의 신선도 게이트는 현재 시계를 사용합니다.
fetchAndVerify()와verifyXml()은NextUpdate가 이미 지난 목록을 거부합니다. 보관된 목록에 대한 과거 시점 검증에는TslSignatureVerifier와TslXmlParser를 직접 구동한 다음, 증거가 뒷받침하는 과거 시점으로assertFresh()를 호출하세요. buildBundle()은 당신의$now에서 신선도를 재차 단언합니다. 집행기를 통과한 목록이라도 검증 시점이 더 나중이면 여기서 거부될 수 있습니다. 위의 BC 참고를 보세요.- 검증 중인 목록에서
trustAnchorsPem을 절대 시드하지 마십시오. 앵커는 대역 외에서 고정한 출처(LOTL의 경우)나 이미 검증된 상위 목록(회원국 TSL의 경우)에서 와야 합니다. 그 외의 것은 검증을 순환적으로 만듭니다. - 어디에든 있는 DOCTYPE는 치명적입니다. 규격을 따르는 TSL은 결코 DTD를 지니지 않으므로, 파서는 libxml이 엔티티 테이블을 구축하기 전에 모든 DOCTYPE를 거부합니다. 이는 파서의 한계가 아니라 의도된 강화입니다.
- 누락된 구조 필드는 안전하게 저하됩니다. 판독 가능한 상태가 없는 서비스는 철회된 것으로 취급되므로, 결코 앵커가 될 수 없습니다. 누락된 스킴 영역은
unknown으로 파싱됩니다. Fail-closed 기본값이 잘못된 형식의 항목을 신뢰 자료에서 배제합니다. - 중간자는 실제 CA여야 합니다. 체인 구축 중,
basicConstraints cA=TRUE가 없는(또는keyCertSign없이keyUsage를 단언하는) 후보 발급자는 건너뜁니다.KeyInfo에 몰래 넣은 최종 개체 인증서는 경로 중간자 역할을 할 수 없습니다. 체인은 깊이 8로 제한됩니다. NextUpdate는 정규 UTC여야 합니다. 명시적Z또는 숫자 오프셋이 없는 값은TslParseException을 던집니다. 이는 결코 서버의 로컬 시간대로 재해석되지 않습니다.- 큰 목록과 바이트 제한. 응답은
$maxBytes(기본값 16 MiB)까지 읽힙니다. 스킴의 목록이 더 크면 생성자에서 제한을 올리세요. 잘림은 조용한 수용이 아니라 언제나 서명 실패로 드러납니다. clockTolerance는 넓히기만 합니다. 이는 인증서 유효성 검사에 대칭적 여유를 더합니다. 목록 수준 신선도 게이트를 느슨하게 하지는 않습니다.
보안 참고
섹션 제목: “보안 참고”- 항상 파싱보다 검증을 먼저.
TslXmlParser는 설계상 서명에 무관합니다.TslPolicyEnforcer는 검증을 먼저 정렬합니다. 조각들을 직접 조합한다면 그 순서를 유지하세요. - 다층 SSRF 방어.
fetch()는https://를 요구하고, 사설, 루프백, 링크 로컬, CGN, 클라우드 메타데이터 범위에 대해 호스트를 검증하며, 리바인딩을 완화하기 위해 A 및 AAAA DNS 해석을 수행합니다. 거부된 URL은 어떤 송신 이전에 던집니다. - XXE 및 엔티티 확장 강화. DOCTYPE를 지닌 문서는 엔티티 테이블이 존재하기 전에, 그리고 로드 후에 다시 거부됩니다. 네트워크 엔티티 로딩은 비활성화되어 있으며, 외부 엔티티는 결코 치환되지 않습니다.
- 엄격한 XMLDSig 프로파일. 배타적 C14N만; 정확히
[enveloped-signature, exclusive-C14N]변환 쌍만; 검증된 참조는 문서 루트를 포괄해야 하며; enveloped 변환은 형제 서명을 보존한 채 검증된 서명만 제거합니다. 폐기된 알고리즘(SHA-1, MD5)은 거부됩니다. - 체인 규율. 모든 체인 링크 — 서명자, 중간자, 그리고 직접 앵커 사례 — 는 시간적 유효성이 검사되며, 파싱 불가한 유효 기간 경계에서는 fail-closed입니다. 루프가 감지되고, 깊이가 제한됩니다.
- 에어갭 태세.
NetworkPolicy::STRICT_OFFLINE하에서 페치 경로는 어떠한 외부 송신도 수행하지 않습니다. 이전에 캐시된 본문만 제공될 수 있으며, 그 외의 것은NetworkPolicyViolation으로 즉시 실패(fail-fast)합니다. - 번들 다이제스트는 훼손이 아니라 손상을 감지합니다.
bundleSha256은 구성 시 검증되며 전사 편차를 감지합니다. 다이제스트가 그것이 보호하는 동일한 앵커에서 파생될 때, 이는 독립적인 변조 증거가 아닙니다. 시스템 간에 번들을 전송할 때는 다이제스트를 대역 외에서 고정하세요.
이 파이프라인은 ETSI TS 119 612가 정의하는 대로 신뢰 목록을 소비합니다: 스킴 운영자의 서명을 인증하고(§5.7), 스킴 정보 및 제공자 목록 구조를 파싱하며(§5.3, §5.4, §5.5), UTC dateTime 규칙을 집행하고(§5.1.3), NextUpdate가 지난 목록을 폐기합니다(§5.3.15). 이는 서명되고 기계 처리 가능한 신뢰 목록이라는 eIDAS 제22조 모델을 지원합니다. 체인 구축은 후보 발급자에 RFC 5280 기본 제약 및 키 사용 게이트를 적용합니다.
지원은 준수가 아니며, 준수는 인증이 아닙니다. NextPDF는 이 페이지가 설명하는 검사를 구현합니다. 그러나 어떤 기관에 의해서도 ETSI TS 119 612, eIDAS, 또는 그 밖의 어떤 표준에 대해 인증받지 않았으며, NextPDF는 어떤 인증도 보유하지 않고 어떤 인증도 부여하지 않습니다. 이 API를 통해 신뢰 목록을 소비한다고 해서 그 자체로 서명이 “적격”이 되거나 법적 효력을 갖게 되는 것은 아닙니다. 당신의 전체 검증 프로세스가 법적 또는 조달 요건을 충족하는지는 당신의 평가자가 판단할 사안입니다.
FIPS 모드 동작
섹션 제목: “FIPS 모드 동작”TSL 서명 검증은 번들된 암호화 라이브러리를 통해 프로세스 내에서 RSA 및 ECDSA 검사를 실행합니다. 이는 Enterprise FIPS 모드 런타임 가드를 경유하지 않으며, FIPS 모드를 활성화해도 그 동작은 바뀌지 않습니다. 이는 FIPS 검증 암호화 서비스가 아니며, 어떤 FIPS 140 인증도 주장하지 않습니다. FIPS 의무가 있는 배포 환경은 이 API의 범위를 그에 맞게 설정하고 FIPS 140-2/3 암호화 정책을 참조해야 합니다.
동작 계약
섹션 제목: “동작 계약”fetch()는 SSRF 검증을 통과한 HTTPS URL에 대해서만 송신을 수행하고, 최대$maxBytes까지 읽으며, 구성된NetworkPolicy를 준수합니다.STRICT_OFFLINE하에서는 오직 캐시된 본문만 반환됩니다.verify()가 성공하기 전에는 어떤 파서 출력도 신뢰 자료가 되지 않습니다.TslPolicyEnforcer가 그 순서를 보장합니다.verify()는 다이제스트와 서명이 고정 프로파일 하에서 확인되고, 서명자가 깊이 8 이내에서 모든 링크가 시간적으로 유효한 채 구성된 앵커까지 체인을 이룰 때에만 서명자 PEM을 반환합니다.- 집행기는 현재 시계에서
NextUpdate가 지난 모든 목록을 거부합니다.buildBundle()은 앵커를 파생하기 전에 호출자가 제공한 시점에서 신선도를 재차 단언합니다. - 앵커는 오직 CA/QC 서비스 유형의 granted 상태 서비스에서만 파생됩니다. 활성 집합이 비어 있으면 빈 번들을 산출하는 대신 던집니다.
- 모든 실패는 타입이 지정된 예외입니다(
TslFetchException,NetworkPolicyViolation, 사유 코드를 담은TslSignatureException,TslParseException). 어떤 메서드도 부분적이거나 미검증된 문서를 반환하지 않습니다.
Core 대체 방안
섹션 제목: “Core 대체 방안”NextPDF Core는 CaTrustAnchorBundle 계약을 통해 명시적으로 고정한 신뢰 앵커에 대해 PDF 서명을 검증합니다 — Core 보안을 보세요. Core에는 신뢰 목록 기능이 없습니다: TSL 페치, XMLDSig 목록 인증, ETSI TS 119 612 파싱, 그리고 적격 서비스 항목으로부터의 앵커 파생이 모두 없습니다. Core만으로는 앵커 집합을 손수 유지해야 합니다. 인증된 EU 신뢰 목록에서 이를 파생하려면 NextPDF Enterprise가 필요합니다.
공표 경계
섹션 제목: “공표 경계”이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만을 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 테이블, 런북 파일명, 티켓 접두사는 범위 밖입니다.
함께 보기
섹션 제목: “함께 보기”- ASiC 신뢰 바인딩 — 컨테이너 서명자를 이 페이지가 파생하는 앵커 번들에 바인딩합니다.
- eIDAS 보증 수준 —
TspService증거를 보증 수준(Levels of Assurance)에 매핑합니다. - 서명 검증 — 경로 검증을 위해 신뢰 앵커를 소비하는 검증 측면.
- 보안 — 심층 레퍼런스 — Enterprise 보안 모듈의 계약 수준 레퍼런스.
- 적격 서명, 설명 — 신뢰 목록이 EU 신뢰 모델을 어떻게 앵커링하는지.
- 장기 검증 — 검증 시점과 보존된 증거가 왜 중요한지.