대부분의 PDF Redaction은 망가졌다. ‘진짜’ Redaction에 실제로 필요한 것.
Source: Dev.to
가짜 레드랙션의 문제점
텍스트 위에 검은 사각형을 그리는 것만으로는 레드랙션이 되지 않습니다. 해당 텍스트는 PDF의 콘텐츠 스트림에 그대로 남아 있기 때문에 누구든지 다음을 할 수 있습니다:
- 전체 선택 → 복사 → 일반 텍스트 편집기에 붙여넣기.
- 숨겨진 정보를 드러내기.
이 실수 때문에 정부 기관의 기밀 문서가 여러 차례 유출된 사례가 있습니다.
가짜 레드랙션 예시
Page content stream: "Salary: $120,000" ← 아직 여기 있음
Annotation layer: [black rectangle] ← 단지 가리고 있을 뿐
콘텐츠 스트림은 손대지 않았으며, 어떤 PDF 파서라도 원본 데이터를 읽을 수 있습니다.
실제 레드랙션에 필요한 것
- 대상 텍스트를 콘텐츠 스트림에서 찾는다.
- 스트림에서 완전히 제거한다.
- 제거된 영역을 검은색 채워진 사각형으로 직접 콘텐츠에 그린다.
- 원본 데이터가 남지 않도록 페이지를 재직렬화한다.
구현 예시 (Rust)
pub fn redact_text(
doc: &mut Document,
page_id: ObjectId,
target: &str,
) -> Result {
let page = doc.get_object_mut(page_id)?;
if let Ok(stream) = page.as_stream_mut() {
let content = stream.decode_content()?;
// Remove text operators containing target
let cleaned = remove_text_from_content(content, target);
// Replace with black filled rectangle at same position
let redact_op = format!(
"q 0 0 0 rg {} {} {} {} re f Q\n",
x, y, width, height
);
stream.set_content(cleaned + redact_op.as_bytes());
}
Ok(())
}
PDF 콘텐츠 스트림 이해하기
PDF 콘텐츠 스트림은 텍스트를 단순한 형식으로 명시적 좌표와 함께 저장하지 않습니다. 텍스트 위치 지정은 다음에 따라 달라집니다:
- 현재 변환 행렬 (CTM)
- 텍스트 행렬 (Tm)
- 폰트 메트릭
이 모든 요소는 상태를 유지하므로, 스트림을 올바르게 파싱하고 수정하려면 전체 콘텐츠‑스트림 인터프리터가 필요합니다. 단순히 원시 바이트에 정규식 검색을 적용하는 것으로는 충분하지 않습니다. lopdf 크레이트는 원시 스트림만 제공하며, 이를 해석하는 작업은 개발자에게 맡겨집니다.
레드랙션 전 PII 탐지
일반적인 워크플로는 레드랙션을 수행하기 전에 패턴 매칭을 통해 개인 식별 정보(PII)를 찾아냅니다. 아래는 전화번호와 일본의 마이넘버(12자리)를 탐지하는 Rust 예시입니다:
pub fn detect_pii(text: &str) -> Vec {
let mut findings = Vec::new();
// Phone numbers (e.g., 123-456-7890)
let phone_re = Regex::new(r"\d{2,4}-\d{2,4}-\d{4}").unwrap();
for m in phone_re.find_iter(text) {
findings.push((m.start(), m.end(), PiiType::Phone));
}
// Japanese MyNumber (12 digits)
let mynumber_re = Regex::new(r"\b\d{12}\b").unwrap();
for m in mynumber_re.find_iter(text) {
findings.push((m.start(), m.end(), PiiType::MyNumber));
}
findings
}
탐지된 결과는 레드랙션을 적용하기 전에 수동으로 검토됩니다. 자동화된 레드랙션을 검토 없이 수행하면 또 다른 위험을 초래할 수 있기 때문입니다.
참고 자료
- Hiyoko PDF Vault – 안전한 PDF 처리를 위한 도구 (작성자: @hiyoyok)