HotXLS는 Agile 암호화된 XLSX 패키지에 규격에 맞는 dataIntegrity 블록을 기록하고, 파일을 열 때 이를 검증합니다. HMAC-SHA-512는 8바이트 StreamSize 접두부를 포함해 EncryptedPackage 스트림 전체를 대상으로 하며, 어떤 세그먼트도 복호화되기 전에 암호문에 대해 검사가 이루어지므로, 잘못된 비밀번호나 변조된 패키지는 쓰레기 값으로 복호화되는 대신 곧바로 탐지됩니다
무결성이 없는 암호화는 절반짜리 답이며, Office 파일 형식은 겉보기에 암호화가 워낙 철저해 보여서 그 빈틈을 놓치기 쉽게 만듭니다. 각 계층이 무엇을 보장하는지 이해하는 것이 보안 검토를 짧게 끝내는 비결입니다
암호화된 통합 문서가 실제로 보장하는 것은 무엇인가?
[MS-OFFCRYPTO]에 정의된 Agile 암호화는 반복된 SHA-512 비밀번호 해시로 유도한 키를 사용하는 CBC 모드의 AES를 통해 기밀성을 제공합니다. 기밀성이 이 구성의 보장 전부입니다. CBC는 인증 모드가 아닙니다. 여러분이 복호화하는 암호문이 실제로 기록되었던 암호문인지에 대해서는 아무것도 말해주지 않습니다
실제로 벌어지는 결과는 구체적입니다. 암호화된 패키지의 비트를 뒤집으면 CBC는 아무렇지 않게 그것을 다른 평문으로 복호화합니다. 손상된 deflate 스트림은 살아남는 경우가 드물기 때문에 대개는 다운스트림 어딘가에서 ZIP 파싱 오류를 만나게 되지만, 이 문장에서 "대개는"이라는 말이 짊어지는 무게가 상당하며, 파일이 변조되었다는 사실을 다운스트림 파서 오류에서 알게 되는 것은 최악의 방식입니다. dataIntegrity 요소는 바로 이 질문에, 복호화 이전에, 정확한 바이트에 대한 MAC으로 직접 답하기 위해 존재합니다
검사는 어떤 순서로 실행되는가
흥미로운 부분은 그 순서입니다. HotXLS는 비밀번호로부터 중간 키를 유도하고, 블록 키에서 파생된 IV를 사용해 dataIntegrity 속성에서 암호화된 HMAC 키와 HMAC 값을 복호화한 다음, 저장된 그대로의 암호화 패키지에 대해 HMAC-SHA-512를 계산하고 비교합니다. 그런 뒤에야 세그먼트 복호화가 시작됩니다
평문이 아니라 암호문에 대해 MAC을 검사하는 것은 표준적인 encrypt-then-MAC 원칙이며, 바로 이것이 검사를 의미 있게 만듭니다. 공격자가 통제하는 바이트가 복호화와 압축 해제 경로를 거치지 않고도 변조된 패키지를 거부할 수 있습니다. 파일을 여는 경로에서 이루어지는 두 비교, 즉 비밀번호 검증기 해시와 HMAC 값 모두 첫 번째로 일치하지 않는 바이트에서 곧바로 반환하는 대신 다이제스트 전체에 걸쳐 XOR와 OR로 차이를 누적하므로, 어느 쪽도 타이밍을 통해 바이트 위치를 노출하지 않습니다
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
// 일반 파일, Standard 암호화 파일, Agile 암호화 파일 모두에 적용됨
if Book.OpenEncrypted('incoming.xlsx', PasswordFromVault) = 1 then
ProcessWorkbook(Book)
else
// 비밀번호가 틀렸거나, dataIntegrity HMAC이 일치하지 않는 패키지
Quarantine('incoming.xlsx');
except
on E: Exception do
Quarantine('incoming.xlsx: ' + E.Message);
end;
Book.Free;
end;
작성하는 쪽에서는 여러분의 코드가 달라질 것이 없습니다. SaveAsEncrypted가 이 블록을 자동으로 내보내며, 솔트와 검증기 입력, HMAC 키는 CryptGenRandom에서 나옵니다. 이 호출이 실패하면 HotXLS는 더 약한 소스로 폴백하는 대신 예외를 일으킵니다. 페일 클로즈드 CSPRNG는 과민 반응이 아닙니다. 예측 가능한 난수 소스로 조용히 격하되면 겉으로는 암호화된 것처럼 보이고 모든 기능 테스트를 통과하지만 아무 가치도 없는 파일이 만들어집니다
블록이 없는 파일은 왜 여전히 열리는가?
실제로 유통되는 수많은 Agile 암호화 통합 문서가 dataIntegrity를 아예 생략하는 생성기로 작성되었고, 이런 파일을 거부하면 보호하는 것보다 훨씬 많은 정당한 작업을 깨뜨리기 때문입니다. HotXLS는 암호화된 HMAC 키와 암호화된 HMAC 값, 이 두 속성이 모두 존재하고 형식이 올바를 때에만 무결성이 있는 것으로 취급합니다. 그렇지 않으면 검증은 건너뛰고 파일은 예전처럼 열립니다
이는 여러분의 위협 모델에서 명시적으로 짚어야 할 보안적 결과를 지닌 호환성 결정입니다. 블록이 없는 것과 공격자가 그것을 제거한 것은 구분할 수 없는데, 그 속성들 자체가 자신이 담을 MAC의 바깥에 있기 때문입니다. 파이프라인의 양 끝을 모두 통제한다면, 블록 누락을 애플리케이션 수준의 정책 위반으로 취급하십시오. 세상으로부터 파일을 받아들이는 입장이라면, 이 검사를 있는 그대로, 즉 존재할 때는 유의미한 신호이지만 없을 때는 아무런 신호도 아닌 것으로 취급하십시오
수정 암호는 경계가 아니라 관례다
고전적인 XLS 통합 문서는 암호화와 흔히 혼동되는 별개의 메커니즘, 즉 Excel의 "수정 암호" 프롬프트인 쓰기 예약을 지원합니다. HotXLS는 이를 SetModifyPassword로 노출하는데, 이 메서드는 비밀번호와 읽기 전용 권장 플래그, 예약한 사용자 이름을 인자로 받고 IsWriteReserved로 상태를 보고합니다. 빈 비밀번호를 전달하면 예약이 해제됩니다
실제로 기록되는 것은 읽기 전용 권장 플래그, 레거시 16비트 비밀번호 해시, BIFF8 유니코드 문자열로 된 사용자 이름을 담은 WRITEPROT와 FILESHARING 레코드 쌍입니다. 그 16비트 해시는 암호학적 다이제스트가 아니라 체크섬이며, 문서 내용은 전혀 암호화되지 않습니다. 다른 어떤 도구로 파일을 열더라도 누구나 모든 것을 읽을 수 있습니다. 이 기능의 진짜 역할은 조율입니다. 누군가 이 파일을 자신이 편집할 것으로 여기고 있다는 사실을 다음 사람에게 알려주는 것이며, XLSX 시트 보호와 허용 옵션에서 다루는 시트 수준 제어와 같은 범주에 속합니다
var
Book: IXLSWorkbook; // 인터페이스 참조 카운트: Free 호출 불필요
begin
Book := TXLSWorkbook.Create;
if Book.Open('shared-model.xls') = 1 then
begin
// 읽기 전용 권장, 리포팅 서비스가 예약함
Book.SetModifyPassword('edit-me', True, 'Reporting Service');
if Book.IsWriteReserved then
Book.SaveAs('shared-model.xls', xlExcel97);
end;
end;
두 계층을 각자 잘하는 일에 맞게 사용하십시오. 진짜 기밀성은 대상 밖의 누구도 가지고 있지 않은 비밀번호로 SaveAsEncrypted를 사용하는 데서 나오며, 이는 AES로 보호된 XLSX 출력에서 설명하는 AES-256 출력을 만들어냅니다. 통합 문서가 공유 편집 산출물이고 누군가 덮어쓰기 전에 Excel이 물어보길 원할 때는 그 위에 쓰기 예약을 얹으십시오
신뢰할 수 없는 수집 경로에서 확인해야 할 것
무결성 검증은 암호화된 페이로드를 보호할 뿐, 그것을 감싸는 컨테이너는 보호하지 않습니다. XLSX 파일은 ZIP 아카이브이며, 어떤 암호화 로직이 실행되기도 전에 아카이브 구조가 파싱되므로, 컨테이너 수준의 검증이 체인에서 가장 먼저 와야 합니다. 구체적인 실패 양상은 신뢰할 수 없는 XLSX에 대한 ZIP EOCD 검증에서 다룹니다. 그 뒤로는 무결성 실패와 잘못된 비밀번호를 같은 운영상의 사건으로 취급하십시오. 여러분 입장에서는 설계상 이 둘을 구분할 수 없으며, 둘 다 그 파일을 발신자가 생각하는 그대로라고 신뢰할 수 없다는 뜻이기 때문입니다
애초에 dataIntegrity 블록을 가지고 있었던 파일이 어느 것인지 로그로 남기십시오. 수천 건의 문서에 걸쳐 이 통계는 발신자들의 도구 체계에 대해 유용한 사실을 알려주며, 파일 단위 검사를 여러분이 실제로 조치할 수 있는 전체 규모의 관측으로 바꿔줍니다
HotXLS는 Excel 설치 없이 Delphi와 C++Builder에서 XLS, XLSX, ODS를 읽고 쓰며, [MS-OFFCRYPTO]의 Standard와 Agile 암호화 경로를 Pascal로 구현합니다. 암호화, 보호, 통합 문서 API는 HotXLS Delphi 스프레드시트 컴포넌트 페이지에 문서화되어 있습니다