Enterprise 에디션
FIPS 140 — 심층 참조
한눈에 보기
섹션 제목: “한눈에 보기”이 페이지는 NextPDF Enterprise FIPS 140 모듈에 대한 심층 레퍼런스입니다. 이 모듈은 정책 및 자체 시험 기능입니다. 암호 선택을 FIPS 정렬 허용 목록으로 제한하고, 전원 인가 기지 응답 시험(known-answer-test) 배터리를 실행하며, 배터리가 실패하면 암호 출력을 억제합니다. NextPDF는 FIPS 140 검증 암호 모듈이 아니며, 어떠한 인증도 보유하지 않고, 어떠한 인증도 부여하지 않습니다. 지원은 준수와 동일하지 않으며, 준수는 인증과 동일하지 않습니다. FIPS 호환 배포에는 운영자가 제공하는 FIPS 검증 암호 제공자가 추가로 필요합니다.
가용성 및 라이선싱
섹션 제목: “가용성 및 라이선싱”이 기능은 NextPDF Enterprise(nextpdf/enterprise)에 포함되어 있으며 Enterprise 등급 라이선스 봉투로 활성화됩니다. 해당 엔타이틀먼트가 없는 배포는 이 기능의 클래스를 로드하지 않습니다. 에디션 비교 및 라이선스 받기.
공개 API 표면
섹션 제목: “공개 API 표면”모든 심볼은 NextPDF\Enterprise\Security\Fips에 있으며, NextPDF\Enterprise\Bootstrap에 있는 FipsBootstrap만 예외입니다.
| 심볼 | 매개변수 | 기본 동작 | 반환 | 예외 또는 실패 | 비고 |
|---|---|---|---|---|---|
FipsBootstrap::boot() | ?CryptoPolicyInterface $policy, ?FipsSelfTest $selfTest, ?LoggerInterface $auditLogger (모두 기본값 null) | 시작 시 전원 인가 배터리를 한 번 실행; 기본값은 엄격 정책 | FipsModeGuard | 전원 인가 시험 실패 시 FipsModuleErrorStateException | 컴포지션 루트; $auditLogger가 null이면 감사 추적 꺼짐 |
FipsBootstrap::lazy() | boot()과 동일 | 배터리를 첫 경계 단언까지 지연 | FipsModeGuard | 호출 시점에는 없음; 첫 단언이 FipsModuleErrorStateException을 던질 수 있음 | 첫 단언 전까지 모듈은 PRE_OPERATIONAL 상태 유지 |
FipsBootstrap::signatureEnforcer() | ?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null | 모듈을 부팅한 뒤 서명자 초크포인트를 위해 가드를 래핑 | FipsSignatureEnforcer | 전원 인가 시험 실패 시 FipsModuleErrorStateException | boot()에 위임 |
FipsBootstrap::selfTestReport() | ?FipsSelfTest $selfTest = null | 요청 시 배터리를 실행하고 요약 | array{status: FipsSelfTestStatus, operational: bool, failed: list<string>} | 던지지 않음; 실패는 failed에 나타남 | 관리자 헬스 엔드포인트 및 CLI 용도 |
FipsCryptoPolicy::strict() | ?FipsSelfTest $selfTest = null | FIPS 140-3 프리셋: SHA-256/384/512; 승인된 RSA, RSASSA-PSS, ECDSA OID; aes-256-cbc, aes-256-gcm; RSA >= 2048, EC >= 256 | self | 없음 | 생성자는 private; 프리셋이 유일한 진입점 |
FipsCryptoPolicy::standard() | ?FipsSelfTest $selfTest = null | FIPS 140-2 프리셋: 엄격 집합에 aes-128-cbc 추가 | self | 없음 | 레거시 상호운용성 전용 |
FipsCryptoPolicy::assertPreOperational() | 없음 | 전원 인가 배터리를 실행하거나 래치된 결과를 재생 | void | 전원 인가 시험 실패 시 FipsModuleErrorStateException | 첫 연산 전에 Core 강제 이음새가 구동 |
FipsCryptoPolicy 조회 표면 | string / int 입력 | 허용 목록 소속 검사; 알 수 없는 키 유형은 거부 | bool / string | 없음 | isHashAlgorithmAllowed, isSignatureAlgorithmAllowed, isEncryptionAlgorithmAllowed, isKeyStrengthAllowed, getPreferredHashAlgorithm, getName |
FipsModeGuard::__construct() | CryptoPolicyInterface $policy, ?FipsBootGuard $bootGuard = null, ?FipsAuditLogger $auditLogger = null | 정책을 단언식 경계로 래핑 | — | 없음 | $bootGuard가 없으면 자체 시험 게이트가 없음; 프로덕션 컴포지션이 이를 제공 |
FipsModeGuard::assertHashAllowed() | string $algorithm | 먼저 거부 카탈로그, 그다음 허용 목록 | void | FipsViolationException; 부트 가드가 연결된 경우 FipsModuleErrorStateException | 감사 레코드가 어떤 FipsViolationException보다 먼저 기록 |
FipsModeGuard::assertSignatureAlgorithmAllowed() | string $oid | 먼저 거부 카탈로그, 그다음 허용 목록 | void | 위와 동일 | OID는 정확히 일치해야 함 |
FipsModeGuard::assertEncryptionAllowed() | string $algorithm | 먼저 거부 카탈로그, 그다음 허용 목록 | void | 위와 동일 | 이름은 소문자로 비교 |
FipsModeGuard::assertKeyStrengthAllowed() | string $keyType, int $bitLength | 먼저 거부 카탈로그, 그다음 정책 최소값 | void | 위와 동일 | 알 수 없는 키 유형은 거부 |
FipsModeGuard::getPolicy() | 없음 | 래핑된 정책을 반환 | CryptoPolicyInterface | 없음 | — |
FipsBootGuard::__construct() | FipsSelfTest $selfTest | 배터리를 보유; 실행하지 않음 | — | 없음 | 인스턴스당 전원 인가 사이클 한 번 |
FipsBootGuard::report() | 없음 | 배터리를 한 번 실행하고 리포트를 캐시하며 오류 시 래치 | FipsSelfTestReport | 없음 | 첫 호출이 시험을 실행 |
FipsBootGuard::rerun() | 없음 | 새 실행을 강제; 오류 실행은 프로세스를 래치 | FipsSelfTestReport | 없음 | 요청 시 자체 시험; 오류 복구 경로가 아님 |
FipsBootGuard::assertOperational() | 없음 | 모듈이 운영 중임을 단언; 프로세스 전체에 걸쳐 고정 | void | FipsModuleErrorStateException | 프로세스가 오류를 래치했다면 깨끗한 인스턴스도 여전히 던짐 |
FipsBootGuard::status() | 없음 | 캐시된 상태를 보고 | FipsSelfTestStatus | 없음 | 래치되면 ERROR; 한 번도 실행되지 않았으면 PRE_OPERATIONAL |
FipsSelfTest::__construct() | ?callable $randomBytesProvider = null, ?callable $hashProvider = null | 플랫폼 hash()와 random_bytes()를 사용 | — | 없음 | 결정론적 실패 시험을 위한 오버라이드가 존재 |
FipsSelfTest::run() | 없음 | 전체 배터리를 실행; 절대 단락하지 않음 | FipsSelfTestReport | 없음 | 실패는 예외가 아니라 리포트에 담김 |
FipsSelfTestReport | FipsSelfTestStatus $status, array $results, array $failedResults | 한 번의 실행에 대한 불변 집합체 | — | 오류 상태에서 assertOperational()이 FipsModuleErrorStateException을 던짐 | isOperational(), isError()도 있음 |
FipsSelfTestResult | string $algorithm, string $kind, bool $passed, string $message = '' | 시험별 불변 결과 | — | 없음 | kind는 KAT, PWCT, 또는 HEALTH; isPassed(), isFailed()도 있음 |
FipsSelfTestStatus | — | 문자열 기반 열거형 | — | 없음 | 케이스 PRE_OPERATIONAL, OPERATIONAL, ERROR |
FipsSignatureEnforcer::__construct() | FipsModeGuard $guard | 서명 초크포인트를 위해 부트 게이트된 가드를 래핑 | — | 없음 | — |
FipsSignatureEnforcer::assertSignatureGenerationAllowed() | string $algorithm, string $certificatePem | OID와 키 강도를 확인한 뒤 가드에 위임 | void | FipsViolationException(알 수 없는 알고리즘, 미승인 PSS 다이제스트, 증명 불가한 키, 또는 정책 거부); 가드를 통한 FipsModuleErrorStateException | 생성 경로 전용; 검증은 절대 여기로 라우팅되지 않음 |
FipsAuditLogger::__construct() | CryptoPolicyInterface $policy, LoggerInterface $logger | PSR-3 로거와 가드가 강제하는 동일 정책을 래핑 | — | 없음 | 기록된 결정은 강제된 결정에서 벗어날 수 없음 |
FipsAuditLogger::logHashOperation() / logSignatureOperation() / logEncryptionOperation() / logKeyStrengthCheck() | 결정별 string / int 입력 | ALLOW는 INFO로, DENY는 WARNING으로 로깅 | bool (허용 시 true) | 없음 | 구조화된 컨텍스트: 정책 이름, 항목, 결정 |
FipsTransitioningAlgorithms | string / int 입력 | 정적 SP 800-131A Rev.2 거부 카탈로그 | bool / list<string> | 없음 | isHashDisallowed, isSignatureOidDisallowed, isEncryptionDisallowed, isKeyStrengthDisallowed, 그리고 disallowedHashes, disallowedSignatureOids, disallowedEncryption |
FipsViolationException | string $policyName, string $violatingItem, string $reason | 공개 readonly 필드를 가진 타입 지정 정책 위반 | — | — | NextPDF\Exception\NextPdfException의 하위 유형 |
FipsModuleErrorStateException | array $failedResults, ?string $message = null | 실패한 시험 결과를 담은 오류 상태 거부 | — | — | NextPDF\Exception\NextPdfException의 하위 유형 |
public static function boot(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuardpublic static function lazy(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuardpublic static function signatureEnforcer(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null): FipsSignatureEnforcerpublic static function selfTestReport(?FipsSelfTest $selfTest = null): arraypublic static function strict(?FipsSelfTest $selfTest = null): selfpublic static function standard(?FipsSelfTest $selfTest = null): selfpublic function assertPreOperational(): voidpublic function isHashAlgorithmAllowed(string $algorithm): boolpublic function isSignatureAlgorithmAllowed(string $oid): boolpublic function isEncryptionAlgorithmAllowed(string $algorithm): boolpublic function isKeyStrengthAllowed(string $keyType, int $bitLength): boolpublic function getPreferredHashAlgorithm(): stringpublic function getName(): stringpublic function __construct(private CryptoPolicyInterface $policy, private ?FipsBootGuard $bootGuard = null, private ?FipsAuditLogger $auditLogger = null)public function assertHashAllowed(string $algorithm): voidpublic function assertSignatureAlgorithmAllowed(string $oid): voidpublic function assertEncryptionAllowed(string $algorithm): voidpublic function assertKeyStrengthAllowed(string $keyType, int $bitLength): voidpublic function getPolicy(): CryptoPolicyInterfacepublic function __construct(private readonly FipsSelfTest $selfTest)public function report(): FipsSelfTestReportpublic function rerun(): FipsSelfTestReportpublic function assertOperational(): voidpublic function status(): FipsSelfTestStatuspublic function __construct(?callable $randomBytesProvider = null, ?callable $hashProvider = null)public function run(): FipsSelfTestReportpublic function __construct(private readonly FipsModeGuard $guard)public function assertSignatureGenerationAllowed(string $algorithm, string $certificatePem): voidpublic function __construct(private CryptoPolicyInterface $policy, private LoggerInterface $logger)public function logHashOperation(string $algorithm): boolpublic function logSignatureOperation(string $oid): boolpublic function logEncryptionOperation(string $algorithm): boolpublic function logKeyStrengthCheck(string $keyType, int $bitLength): boolpublic static function isHashDisallowed(string $algorithm): boolpublic static function isSignatureOidDisallowed(string $oid): boolpublic static function isEncryptionDisallowed(string $algorithm): boolpublic static function isKeyStrengthDisallowed(string $keyType, int $bitLength): boolpublic static function disallowedHashes(): arraypublic static function disallowedSignatureOids(): arraypublic static function disallowedEncryption(): arraypublic function __construct(public FipsSelfTestStatus $status, public array $results, public array $failedResults)public function isOperational(): boolpublic function isError(): boolpublic function assertOperational(): void
// FipsSelfTestResultpublic function __construct(public string $algorithm, public string $kind, public bool $passed, public string $message = '')public function isPassed(): boolpublic function isFailed(): bool
// FipsSelfTestStatusenum FipsSelfTestStatus: string{ case PRE_OPERATIONAL = 'pre_operational'; case OPERATIONAL = 'operational'; case ERROR = 'error';}동작 계약
섹션 제목: “동작 계약”- 정책 허용 목록이 권위 있는 결정입니다.
FipsTransitioningAlgorithms는 감사에 명확한 거부 메시지를 위해 그 위에 명시적인 SP 800-131A Rev.2 거부 계층을 추가합니다. 거부 계층은 절대 허용 목록을 넓히거나 재정의하지 않습니다. FipsCryptoPolicy::strict()는 SHA-256, SHA-384, SHA-512를 허용합니다; RSA PKCS#1 v1.5,RSASSA-PSS, 그리고 그 해시들에 바인딩된 ECDSA 서명 OID;aes-256-cbc와aes-256-gcm; 그리고 RSA 2048, EC 256, Ed25519 256의 키 하한을 허용합니다.standard()는 추가로aes-128-cbc를 허용합니다.- 전원 인가 배터리는 다음을 다룹니다: SHA-256/384/512 다이제스트 KAT, HMAC-SHA-256 KAT, AES-256-CBC 암호화-복호화 KAT, AES-256-GCM 태그 KAT, ECDSA P-256 쌍별 일관성 시험, 그리고 DRBG 헬스 체크.
FipsSelfTest::run()은 항상 모든 시험을 실행하고 절대 단락하지 않으므로, 리포트는 감사 증거로서 완전합니다. - DRBG 행은 기지 응답 시험이 아니라 연속 헬스 시험(추출 길이 및 구별되는 연속 추출)입니다. DRBG 기지 응답 의무는 운영자가 제공하는 기반 FIPS 검증 제공자에게 위임됩니다.
- 오류 상태는 프로세스 고정입니다. 어떤
FipsBootGuard가 관측한 첫ERROR리포트가 프로세스 전체를 래치합니다. 새 가드나 정책 인스턴스는 오류를 세탁할 수 없으며, 이후의 통과 재실행도 이를 지우지 못합니다. 오직 프로세스 재시작(진정한 전원 재투입)만이 상태를 재설정합니다. FipsCryptoPolicy는NextPDF\Contracts\CryptoPolicyInterface와NextPDF\Contracts\PreOperationalSelfTestInterface를 구현합니다. Core 암호 정책으로 구성되면, Core 강제 이음새가 첫 서명이나 암호문이 생성되기 전에assertPreOperational()을 구동합니다.FipsSignatureEnforcer는 생성 경로만 게이트합니다. 이미 생성된 서명의 검증은 SP 800-131A Rev.2에서 레거시 사용에 해당하며 절대 강제기를 통해 라우팅되지 않습니다.- 감사 로거가 연결되면, 모든 단언 경계는 정책 위반 던지기 전에 하나의 ALLOW(INFO) 또는 DENY(WARNING) 레코드를 방출합니다. 따라서 모든
FipsViolationException거부는 추적에 증거로 남습니다. 부트 가드 게이트가 먼저 실행되므로, 오류 상태 거부는 감사 레코드보다 먼저 발생합니다.FipsAuditLogger는 가드가 강제하는 동일한 정책을 참조하므로, 기록된 결정은 강제된 결정에서 벗어날 수 없습니다.
엣지 케이스 및 실패 모드
섹션 제목: “엣지 케이스 및 실패 모드”- 알 수 없는 키 유형은 두 계층 모두에서 거부됩니다: 정책은
false를 반환하고 카탈로그는 이를 비허용으로 취급합니다. - 강제기가 서명 OID로 매핑할 수 없는 서명 알고리즘 식별자는
FipsViolationException으로 페일 클로즈드 거부됩니다. - 모든
RSASSA-PSS변형은 OID1.2.840.113549.1.1.10을 공유하므로, OID만으로는 다이제스트를 증명할 수 없습니다. 강제기는 유효 다이제스트를 명시적으로 바인딩하고, 다이제스트가 SHA-256/384/512가 아닌 PSS 토큰은 모두 거부합니다. - 파싱할 수 없거나 공개 키 비트 길이를 얻을 수 없는 인증서는
key:unprovable로 거부됩니다. - OpenSSL 비대칭 프리미티브가 없는 런타임에서는, ECDSA 쌍별 일관성 시험이 건너뛰기가 아니라 실패를 기록하고, 모듈은
ERROR에 진입합니다. - 동일한 두 개의 연속된 32바이트 무작위 추출은 DRBG 헬스 체크(고착 출력 감지)에 실패하고
ERROR를 강제합니다. - 부트 가드 없이 생성된
FipsModeGuard는 정책 검사만 수행하며 자체 시험 게이트가 없습니다. 프로덕션 컴포지션은 항상 게이트를 연결하는FipsBootstrap을 통합니다. - 해시와 암호 이름은 소문자로 비교되며; 서명 OID는 정규화 없이 정확히 일치해야 합니다.
FipsBootstrap::lazy()이후, 모듈은 첫 단언 경계가 배터리를 실행할 때까지PRE_OPERATIONAL상태를 유지합니다.PRE_OPERATIONAL은 단언 시점에 운영 중이 아닌 것으로 취급됩니다.
FIPS 모드 동작
섹션 제목: “FIPS 모드 동작”이 모듈은 FIPS 모드 표면 그 자체입니다. 모듈이 오류 상태에 있는 동안, 그리고 운영 전 자체 시험이 실행되는 동안, 암호 출력이 억제됩니다: 모든 단언 경계는 서명이나 암호문이 생성되기 전에 FipsModuleErrorStateException을 던집니다(ISO/IEC 19790:2025 §7.3.3 b), AS03.07). FipsBootGuard::status()와 FipsBootstrap::selfTestReport()는 상태를 노출하여 운영자가 모듈이 오류 상태에 진입했음을 판단할 수 있게 합니다(ISO/IEC 19790:2025 §7.10.3). 이 동작들은 NextPDF 코드에 대한 기능 주장이지 검증 주장이 아닙니다: FIPS 140이 검증하는 모듈 경계는 NextPDF가 아니라 운영자가 제공하는 암호 제공자입니다.
| 주장 | 표준 | 조항 |
|---|---|---|
| FIPS 140-3은 ISO/IEC 19790과 ISO/IEC 24759에 기반하므로, 이 페이지는 ISO/IEC 19790 조항을 인용합니다. | FIPS 140-3 | Introduction (fips_140_3#x26.x2) |
| 출력은 오류 상태 및 운영 전 자체 시험 동안 억제됩니다. | ISO/IEC 19790:2025 | §7.3.3 b) [AS03.07] |
| 기지 응답 시험은 계산된 결과를 알려진 예상 출력과 비교합니다; 배터리는 이 형태를 구현합니다. | ISO/IEC 19790:2025 | §7.10.4 |
| 운영자는 상태 출력을 통해 오류 상태를 판단할 수 있습니다. | ISO/IEC 19790:2025 | §7.10.3 [AS10.10] |
운영자는 주기적 시험을 위해 요청 시 자체 시험을 개시할 수 있습니다; rerun()과 selfTestReport()가 이를 제공합니다. | ISO/IEC 19790:2025 | §7.10.5 [AS10.54] |
| SHA-1은 새로운 디지털 서명 생성에 비허용됩니다; 거부 카탈로그가 이를 거절합니다. | NIST SP 800-131A Rev.2 | §9 |
| 112비트 강도 미만의 서명 생성(RSA < 2048, ECDSA order < 224)은 비허용됩니다; 키 하한이 이를 강제합니다. | NIST SP 800-131A Rev.2 | §3 Table 2 |
| 이미 생성된 SHA-1 서명의 검증은 레거시 사용입니다; 생성 게이트를 통해 라우팅되지 않습니다. | NIST SP 800-131A Rev.2 | Change summary (9.x4.p12) |
모든 조항은 의역되었으며; 규범 텍스트는 재현되지 않았습니다. NextPDF는 어떠한 FIPS 140 인증 주장도 하지 않습니다. 모듈은 컴플라이언스 지원 기능으로서 인용된 조항에 자신의 동작을 정렬합니다. 배포가 FIPS 준수인지는 운영자의 검증 제공자, 모듈 경계 정의, 그리고 컴플라이언스 프로그램에 달려 있으며 — NextPDF 단독으로 결정되지 않습니다.
개발 노트
섹션 제목: “개발 노트”- 결정론적 실패 시험은
FipsSelfTest생성자를 통하거나,FipsCryptoPolicy::strict(),standard(), 그리고FipsBootstrap메서드의$selfTest매개변수를 통해 손상된 제공자를 주입합니다. - 프로세스 고정 오류 래치에는 내부의 시험 전용 재설정 훅이 있습니다. 이는 지원되는 API의 일부가 아니며, 프로덕션 코드는 이를 호출해서는 안 됩니다.
- 각 PHP 워커 프로세스는 자체 전원 인가 배터리를 실행합니다. 리포트는 인스턴스별로 캐시되므로, 핫패스 단언은 상수 시간 상태 검사입니다.
FipsModuleErrorStateException을 잡아서 계속 진행하지 마십시오. 이 예외는 모듈이 암호 서비스를 거부한다는 의미이며; 올바른 대응은 개선 조치 후 프로세스를 중단하고 재시작하는 것입니다.FipsBootstrap::selfTestReport()는 헬스 엔드포인트와 같은 요청 시 및 주기적 자체 시험 요구를 지원합니다. 통과하는 요청 시 실행은 절대 래치된 오류를 지우지 않습니다.
관련 항목
섹션 제목: “관련 항목”- FIPS 140-2/3 암호 정책 및 자체 시험 — 설정과 예제가 있는 기능 페이지.
- 보안 — 심층 레퍼런스 — 통합된 Enterprise 보안 제어.
- 서명 — 심층 레퍼런스 — PAdES 장기 생산자와 그 FIPS 모드 노트.
- 보안 — NextPDF Core — 정책이 바인딩되는 Core 암호화 및 서명 표면.
발행 경계
섹션 제목: “발행 경계”이 페이지는 외부에서 관측 가능한 동작과 지원되는 공개 API 표면만 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 그리고 티켓 접두어는 범위 밖입니다.