증분 PFX 서명 작업

sign 연산은 원본 PDF 리비전과 기존 암호화 서명 각각을 그대로 보존하면서 별도로 서명된 아티팩트를 돌려주는, 검증된 증분 프로필을 지원합니다

프로필 선택

{"schemaVersion":1,"type":"sign","profile":"pfx-incremental-document",
 "pfxFile":"C:/keys/signer.pfx","pfxPassword":"password",
 "fieldName":"ApprovalTwo","existingField":true,
 "budget":{"memoryBytes":268435456,"outputBytes":134217728,
           "resultBytes":16777216,"timeMilliseconds":60000,
           "objectCount":1000000,"pageCount":1024}}

기본 pfx-unsigned-document 프로필은 기존 동작을 유지하며 서명 필드가 전혀 없는 소스도 받습니다. page, x1, y1, x2, y2로 새 필드를 만들고 발행 전에 소스 그래프를 복원합니다

pfx-incremental-document가 새 프로필을 고릅니다. profile을 생략하면 incremental: true가 동등한 셀렉터이고, 명시적으로 다른 프로필과 함께 쓰면 충돌합니다

existingField: true는 이름이 같은 빈 서명 필드를 다른 필드를 추가하지 않고 채웁니다. 그렇지 않으면 연산이 새 필드를 만들고 page와 사각형이 위젯 위치를 정합니다

fieldName 기본값은 Signature1이고 1~1024 UTF-8 바이트를 받습니다. existingField에는 증분 프로필, 일치하는 서명 필드, 없거나 null인 V 값이 필요합니다

읽기 전용 Ff 비트 1과 형식이 틀렸거나 범위를 벗어난 정수 플래그는 준비 전에 거절됩니다. 상속된 SV와 Lock 사전은 고유한 의미 PDF 이름과 bounded 부모 순회로 해석됩니다

시드 값과 필드 잠금

digestMethod는 실제 SHA256, SHA384, SHA512 CMS 다이제스트를 고릅니다. 기본값은 SHA256이고, cades: true는 ETSI.CAdES.detached를 선택해 실제 서명 인증서를 묶는 signing-certificate-v2 속성을 포함합니다

reason, location, contactName은 PDF Unicode 텍스트 문자열로 기록되는 UTF-8 JSON 문자열입니다. 필수 시드 reason은 Unicode 값을 비교하며, reason 생략을 요구하는 특수한 점 하나 값도 포함합니다

필수 SV 제약은 실제 핸들러, CMS SubFilter, 지원되는 서명 버전, 다이제스트, reason, certification 권한, 법적 증명, LockDocument 모드를 검사합니다. 필수 timestamp는 Windows 서명 타임스탬프의 애플리케이션 전송과 명시적 신뢰 워크플로를 쓰고, 필수 서명 폐기 증거는 인증된 CRL 및 OCSP 서명을, 필수 이름 있는 appearance는 실제 생성된 서명 appearance 프리셋을 씁니다

필수 SVCert 속성은 서명 전에 실제 PFX 리프 인증서와 포함된 발급자 체인, 허용된 인증서 바이트, 인증서 정책 OID, 키 용도 비트, Unicode subject DN 속성을 검증합니다

credentialSourceURL은 필수 SVCert URL에 대해 애플리케이션이 단정하는 credential 출처를 공급합니다. 라이브러리는 선언된 URL과 지원되는 URLType을 비교할 뿐 그 엔드포인트를 열거나 전송 신원을 인증하지 않습니다

All, Include, Exclude 필드 잠금은 간접 SigFieldLock 사전과 문서 Catalog에 묶인 대응 FieldMDP 참조로 기록됩니다. 필드 이름은 PDF Unicode 텍스트 문자열을 쓰고 암호화된 문서에서는 암호화된 채로 유지됩니다

서명된 Lock P 값은 원본 서명 필드 정책으로 이후 리비전을 제한하며 DocMDP 권한과는 별개입니다. 허용된 두 번째 서명은 이전 리비전과 CMS를 그대로 보존하고, 잠긴 필드나 P1 변경은 발행 전에 거절됩니다

정책 조회는 상속된 Parent 이름을 포함해 PDF 이름 이스케이프를 정확히 한 번 디코딩합니다. 의미 이름이 중복된 사전과 잘못되었거나 순환하는 부모는 발행 전에 거절되고, 유효한 이스케이프 이름은 소스 바이트를 유지합니다

contentsBytes 기본값은 16384이고 1024~1048576을 받습니다. reason, location, contactName은 새 서명 사전을 채웁니다

certification과 법적 증명

certificationPermission 기본값은 승인 서명용 0입니다. 1, 2, 3은 요청한 DocMDP 권한으로 certification 서명을 만들고 Catalog Perms DocMDP를 실제 간접 서명 사전에 묶으며, 독립적인 FieldMDP 변환이 있으면 유지합니다

certification은 첫 번째 서명이어야 하고 문서에는 certification 서명이 하나만 있을 수 있습니다. 형식이 틀린 Catalog 권한, 미해결 참조, 원본 서명 필드 바인딩이 없는 DocMDP 값은 거절됩니다

legalAttestation은 certification 서명용 선택적 Unicode 문자열이며 Catalog Legal Attestation에 기록됩니다. 필수 SV LegalAttestation 목록은 선택한 텍스트를 담아야 하고, 비어 있는 필수 목록은 생략을 요구합니다

기존 P2와 P3 certification 서명은 필드 잠금과 리비전 정책이 허용하면 이후 승인 서명을 허용합니다. P1 서명과 잠긴 필드는 바이너리 발행 전에 변경을 거절합니다

소스 계약

증분 작업 프로필은 지원되는 암호화 PDF를 포함해 유지 중인 원본 소스와 변경되지 않은 로드 객체 그래프를 받습니다. 암호화된 소스에는 pfxPassword와 별도로 sign 연산에 password를 넣으세요

소스 비밀번호는 독립적인 raw 스냅샷을 인증하고 원본 암호화 컨텍스트를 초기화하며 서명된 candidate를 다시 엽니다. 결과 증분 리비전은 원본 암호문 접두부, 보안 사전, 영구 문서 ID를 보존합니다

복호화는 내부적으로 객체를 dirty로 표시하거나 복호화된 그래프에서 보안 사전을 제거할 수 있습니다. 연산은 이런 상태와 bounded 객체 직렬화를 새로 인증한 소스 베이스라인과 대조하면서, 실제 그래프 변경과 모든 플러시된 객체 상태는 거절합니다

사용자 비밀번호에서는 기존 서명 필드에 폼 채우기나 어노테이션 권한이 필요하고 새 서명 위젯에는 어노테이션 권한이 필요합니다. 인증된 소유자 비밀번호는 기존 서명 정책의 제약 안에서 어느 쪽이든 허가합니다

SaveLoadedDocumentToStream은 직렬화 상태를 바꿀 수 있습니다. 저장했거나 편집한 그래프에 서명할 때는 저장된 바이트를 새 핸들로 다시 로드해서 그 리비전에 서명하세요

핸들 수명 동안 원본 소스 저장소를 안정적으로 유지하세요. 파일 작업은 스냅샷을 로드·준비하는 동안 쓰기 공유를 거부합니다

원본 핸들은 필드 개수, 기존 필드 신원, 폼 값, 소스 바이트, 이전 실행·디코드 설정을 유지합니다. 서명 성공은 항상 documentUpdated: false를 반환하고, 서명 실패 후에도 핸들은 조회, 저장, 이후 유효한 요청에 계속 쓸 수 있습니다

파일 작업은 하드링크를 포함해 입력 파일과 같거나 별칭인 출력 경로를 거절합니다. 직접 스트림 API는 인식 가능한 소스 스트림·소스 파일 별칭을 거절하고, 호출자는 불투명한 콜백 출력 저장소도 입력 저장소와 구분해야 합니다

준비와 검증

연산은 raw 소스 바이트를 단독 생성한 임시 스냅샷으로 복사하고 독립적인 증분 클론을 연 뒤 bounded SaveIncrementalUpdate로 플레이스홀더를 덧붙이고, 네이티브 PFX 스트림 서명기로 분리 CMS를 채웁니다

PFX는 크기 사전 점검부터 서명까지 쓰기 공유가 거부된 채 열려 있고, 임시 파일은 CREATE_NEW로 만들며 연산이 직접 만든 경우에만 제거됩니다

서명된 candidate는 정확한 소스 바이트 접두부와 예상 폼·서명 필드 개수를 담아야 합니다. 새 서명은 선택된 필드에서 검증되어야 하고, 이전에 채워진 모든 서명은 여전히 검증되어야 하며, 모든 기존 서명의 리비전 분석은 DocMDP, FieldMDP, 사용 권한, 신원 제약을 받아들여야 합니다

비어 있는 기존 필드는 preservedSignatures에 세지 않고 유지됩니다. 형식이 틀렸거나 잘못되었거나 정책을 어기는 기존 서명은 바이너리 발행 전에 거절을 유발합니다

기존 서명 검증은 서명된 바이트와 네이티브 리비전 정책에 대해 CMS 무결성을 검사합니다. 새 서명에 timestamp를 요청하면 그 응답은 발행 전에 명시적 TSA 신뢰와 구성된 폐기 증거를 따로 검증합니다

예산과 발행

실제 출력 상한은 min(outputBytes, memoryBytes / 8)이고 소스 접두부 전체, 덧붙인 객체, xref, 서명 예약을 포함합니다. 적용된 상한은 effectiveOutputLimit가 보고합니다

서명 전 candidate와 서명된 출력은 각각 그 상한으로 묶이고, PFX 바이트는 memoryBytes / 8로 제한되며, 소스 베이스라인·클론·candidate 디코드 예산은 각각 memoryBytes / 8로 제한되고 파일 스플 임계값은 1 MiB 이하입니다

이것들은 엄격한 프로세스 RSS 보장이 아니라 연산·버퍼 예산입니다. 암호화, 객체 메타데이터, 리비전 분석, 호출자가 이미 로드한 소스는 추가 상주 메모리를 요구할 수 있습니다

취소와 경과 시간 검사는 소스 복사, 델타 직렬화·복사, candidate 읽기, 서명 검증 읽기, 리비전 분석 읽기, 콜백 발행에 적용됩니다. 고정된 네이티브 스트림 실패는 작업 경계에서 자신의 예산·취소 범주를 유지합니다

바이너리 출력은 첫 출력 콜백 전에 스테이징·검증되고 결과 JSON 크기는 바이너리 발행 전에 검사합니다. 콜백 출력 자체는 원자적이지 않아서 실패한 바이너리·결과 콜백은 호출자가 버려야 하는 바이트를 남길 수 있습니다

파일 작업은 소유한 같은 디렉터리 candidate에 쓰고 플러시한 뒤 소스·출력 핸들을 닫고, 검증이 성공한 후에 별개 대상을 원자적으로 교체합니다. 실패하면 기존 대상을 보존합니다

성공 시 mediaType: application/pdf, fieldName, profile, incremental, existingField, certificationPermission, revocationInfo, appearanceProfile, preservedSignatures, effectiveOutputLimit, outputBytes, documentUpdated: false를 반환합니다

재생 인수 검증

$env:HOTPDF_SUPPRESS_AUTO_LAUNCH = '1'
./Tests/CABI/Run-IncrementalSigningAcceptance.ps1 -BuildDLL -CheckFPC

러너는 레지스트리 RootDir로 RAD Studio를 찾고 RADStudioRoot와 PythonExecutable 오버라이드를 받으며, CheckFPC를 고르면 구성된 FPC 툴체인을 씁니다. FPCOnly는 그 네이티브 대상만 재생하고, OpenSSLWin32Library와 OpenSSLWin64Library는 아키텍처별로 맞는 런타임 라이브러리를 고릅니다

비 GUI 러너는 부분 콜백, 기존 빈 필드, 기존 서명, 필수 시드 값, 실제 SHA384와 SHA512 CAdES, Unicode 메타데이터, 허용·잠긴 두 번째 서명, 실제 PFX 인증서 속성, AES-128과 AES-256 필드 잠금 변환, 권한 제한과 소유자 자격, 잘못된 비밀번호, dirty 복호화 그래프, 정확한 암호화 소스 스냅샷, 암호화 인플레이스 라이터 복구, 실제 DocMDP P1·P2 CMS 픽스처, 예산, 취소, 콜백 실패, 실패 후 소스 재사용을 Win32와 Win64 네이티브 API와 실제 C ABI DLL 양쪽에서 검사합니다

독립적인 pypdf, MuPDF, OpenSSL 검사는 정확한 이전 접두부와 바이트 범위, 변하지 않는 암호화와 영구 ID, 검색 가능한 원본 텍스트, 유효한 기존·신규 CMS 값, 서명 Contents 암호화 예외, 수정된 서명 콘텐츠 거부를 증명합니다. independent-proof.json이 바이트 범위와 증명 결과를 기록합니다

관련 항목

문서 연산, CopyLoadedSourceToStream, SaveIncrementalUpdate, EHPDFIncrementalOutputBudget