PDFiumPas는 SaveAsEncrypted를 통해 ISO/TS 32003 암호화를 작성합니다. Revision을 erR7로 설정하면 모든 문자열과 스트림이 GCM 모드의 AES-256으로 보호되는데, 이는 PDF 2.0이 2023년에 얻은 인증 암호입니다. EnableIntegrityProtection도 함께 설정하면 문서에 독립형 PDF MAC 토큰도 담기며, 읽는 쪽에서는 ValidatePdfMac이 이를 검사합니다
이 둘은 사람들이 흔히 혼동하는 서로 다른 두 가지 보호입니다. GCM은 각 암호화된 값을 인증합니다. MAC은 문서 전체를 인증합니다. 서로 다른 이유로 여러분에게는 둘 다 필요합니다
GCM이 CBC에는 없던 무엇을 더해주는가?
암호문에 대한 인증입니다. ISO 32000-2의 AESV3 방식인 CBC 모드의 AES-256은 내용을 기밀로 유지할 뿐, 그것이 수정 없이 도착했는지에 대해서는 아무것도 말해주지 않습니다. CBC는 잘 연구된 특정한 방식으로 가단성(malleable)을 지닙니다. 암호문의 비트를 뒤집을 수 있는 공격자는 다음 블록의 평문에 예측 가능한 변화를 일으키지만, 형식 자체는 이를 전혀 알아채지 못합니다
GCM은 이 틈을 닫습니다. 암호화된 값마다 ISO/TS 32003이 요구하는 대로 전체가 직렬화된 16바이트 인증 태그가 붙으며, 태그가 일치하지 않으면 변조된 평문을 반환하는 대신 복호화가 실패합니다. PDF 용어로 말하면, AESV4 문서에서 변조된 문자열이나 스트림은 여러분의 애플리케이션으로 전파되는 이상한 값이 아니라 사용 시점에서 발생하는 확실한 오류입니다. Encrypt 딕셔너리는 이를 /CFM /AESV4와 V 6 / R 7로 표시하며, /ExtensionLevel 32003과 /ExtensionRevision (:2023)을 선언하는 확장 항목도 함께 둡니다
세 가지 리비전, 세 가지 생태계
TPdfEncryptionRevision은 erR5, erR6, erR7을 제공하며, 이 선택은 암호학적 결정이라기보다는 호환성 결정에 가깝습니다. R5는 PDF 1.7 확장으로 발표된 원조 AES-256 방식으로, 단일 SHA-256 비밀번호 해시를 사용하며 지난 15년간의 거의 모든 것에서 열립니다. R6은 알고리즘 2.B의 반복적인 SHA-256/384/512 구성을 사용하는, ISO 32000-2에 표준화된 강화된 키 유도 방식이며, 현재의 PDF 2.0이나 PDF/A-4 워크플로가 기대하는 방식입니다. R7은 ISO/TS 32003으로, 같은 2.B 유도 방식에 AES-GCM을 암호로 사용합니다
리더 지원 범위는 정확히 그 순서를 따르며, R7 지원은 현재의 주류 뷰어를 벗어나면 아직 얇습니다. 이는 어떤 PDF 2.0 기능에서든 마찬가지인 트레이드오프입니다. 가장 새로운 옵션이 가장 뛰어난 엔지니어링이면서 가장 좁은 대상을 가집니다. 누가 그 파일을 열어야 하는지를 기준으로 결정하십시오. 그 답이 "2019년 이후로 아무도 업데이트하지 않은 기록 시스템"이라면, 보안 정책이 무엇을 선호하든 답은 R5입니다
uses
PDFium, FPdfEncrypt;
var
Pdf: TPdf;
Opts: TPdfEncryptOptions;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'quarterly-report.pdf';
Pdf.LoadDocument;
Opts := TPdfEncryptOptions.Default;
Opts.UserPassword := 'open-secret';
Opts.OwnerPassword := 'admin-secret';
Opts.EncryptMetadata := True;
Opts.Revision := erR7; // ISO/TS 32003 AESV4-GCM
Opts.EnableIntegrityProtection := True; // 독립형 PDF MAC 토큰
if not Pdf.SaveAsEncrypted('quarterly-report.enc.pdf', Opts) then
raise Exception.Create('Encrypted save failed');
finally
Pdf.Free;
end;
end;
인증된 암호 위에 왜 문서 MAC이 필요한가?
GCM 태그는 값들의 배치가 아니라 값 자체를 보호하기 때문입니다. AESV4 문서의 모든 문자열과 스트림은 개별적으로 인증되지만, 상호 참조 테이블과 객체 번호 매기기, 트레일러는 구조이지 암호화된 내용이 아닙니다. 공격자는 스트림을 위조할 수는 없지만, 암호 자체만으로는 문서가 가리키는 객체를 재배치하거나 같은 파일의 이전 리비전에서 가져온 객체를 이어붙이는 것을 막지 못합니다
독립형 PDF MAC 토큰은 바로 그 계층을 다룹니다. PDFiumPas는 이를 Encrypt 딕셔너리에 기록된 전용 32바이트 /KDFSalt를 사용해 파일 암호화 키로부터 유도하므로, 비밀번호를 가지고 있다는 사실이 리더가 그 토큰을 확인할 수 있게 해주는 조건이 됩니다. 그 결과는 하나의 질문에 대한 하나의 답입니다. 이 문서는 전체적으로 실제로 기록되었던 그 문서인가
var
Pdf: TPdf;
Mac: TPdfMacValidationResult;
begin
Pdf := TPdf.Create(nil);
try
Pdf.Password := 'open-secret';
Pdf.FileName := 'quarterly-report.enc.pdf';
Pdf.LoadDocument;
Mac := Pdf.ValidatePdfMac('open-secret');
case Mac.Status of
pmvsValid: ProcessDocument(Pdf);
pmvsNotPresent: ProcessWithWarning(Pdf); // 이 파일에 토큰이 없음
pmvsInvalid: Quarantine(Mac.MessageText); // 변조되었거나 잘림
pmvsUnsupported: RouteForManualReview(Mac.MessageText);
end;
finally
Pdf.Free;
end;
end;
네 가지 상태 값은 네 가지 다른 대응을 필요로 하며, 이를 불리언 하나로 뭉뚱그리면 중요한 구분을 잃게 됩니다. pmvsNotPresent는 파일에 단순히 토큰이 없다는 뜻이며, 이는 2024년 이전에 작성된 거의 모든 암호화 PDF에 해당하는 상황일 뿐 아무런 증거도 아닙니다. pmvsInvalid는 토큰이 존재하지만 검증되지 않는다는 뜻으로, 실제로 유의미한 발견이며 처리를 멈춰야 합니다. pmvsUnsupported는 토큰이 이 빌드가 구현하지 않은 형태로 존재한다는 뜻으로, 공격이 아니라 호환성의 공백입니다. "없음"을 "무효"로 취급하면 첫날부터 여러분의 기존 자료 전체가 격리될 것입니다
암호화가 여전히 하지 못하는 것
권한 플래그는 예나 지금이나 마찬가지입니다. 통제가 아니라 규격을 준수하는 소프트웨어에 대한 요청일 뿐입니다. 인쇄나 추출을 금지하는 ISO 32000-1 표 22의 /P 비트는 잘 만들어진 뷰어에서는 존중되지만 그 외의 모든 곳에서는 무시되며, 사용자 비밀번호를 가진 사람은 이미 복호화된 내용을 가지고 있습니다. 암호화는 경계이고, 권한은 그 안에서의 의도를 서술합니다
운영상 계획해 둘 만한 세부 사항이 두 가지 있습니다. 첫째, 암호화와 이후의 수정은 서로 얽힙니다. 암호화된 문서에 증분 업데이트를 덧붙이는 데는 그 자체의 규칙이 있으며, 암호화된 PDF의 증분 업데이트에서 다룹니다. MAC 토큰은 문서 수준의 진술이므로 부주의한 추가 작업은 이를 무효화합니다. 둘째, GCM 구성은 결정론적 IV 카운터를 사용하며, 그 공간이 소진될 경우 PDFiumPas는 카운터 값을 재사용하는 대신 예외를 일으킵니다. GCM에서 nonce 재사용은 조용한 랩어라운드가 감춰버릴 만큼 치명적이기 때문입니다
실무에서 세 리비전 중 고르기
누가 그 파일을 여는지 적어본 뒤 선택하십시오. 모든 리더가 여러분이 통제하는 최신 뷰어인 내부 배포용이라면, 무결성 보호를 갖춘 R7이 사용 가능한 가장 강력한 옵션이며 쓰지 않을 이유가 없습니다. 조직 밖으로 나가는 문서라면 R6이 방어 가능한 기본값입니다. 그 위에 얹힌 기술 명세가 아니라 ISO 32000-2 자체에 표준화되어 있고 지원 범위도 넓습니다. 아카이브와 레거시 소비자를 위해서는 R5만이 확실히 열리는 유일한 선택이며, 그 이유는 여러분의 나머지 보존 정책을 기록하는 것과 같은 곳에 함께 기록해 두어야 합니다
무엇을 고르든, 호출이 성공했다고 믿는 대신 출력을 검증하십시오. 암호화된 파일을 다시 열어 ValidatePdfMac을 확인하고, 정확한 PDF 버전 규격 준수에서 다루는 버전 규격 준수 검사를 사용해 선언된 버전이 여러분이 기대한 것인지 확인하십시오. 신뢰할 수 없는 문서에 대한 더 폭넓은 수집 체크리스트는 PDF 보안 위험 감사에 있습니다
PDFiumPas는 PDFium 엔진을 감싸는 Delphi와 Lazarus용 컴포넌트로, PDF 2.0 암호화 스택을 네이티브 Pascal로 구현했기 때문에 AES-256, GCM, MAC 토큰 모두 외부 암호화 DLL이 필요 없습니다. 암호화 API는 PDFium Delphi 컴포넌트 페이지에 문서화되어 있습니다