2026. 8. 12.
ZIP 파일을 압축 해제 없이 해시값으로 무결성 확인하기
ZIP 파일을 다루다 보면 묘한 딜레마에 부닥칠 때가 있다. 외부에서 전달받은 압축 파일의 무결성을 확인하거나 감사 증적을 남겨야 하는데, 파일을 실제로 압축 해제해버리면 원본 상태를 보존했다고 보기 어려워지는 상황이다. 수백 개의 파일이 들어있는 아카이브를 풀면 디스크에 수많은 파일이 흩어지고, 그중 하나라도 실수로 덮어쓰거나 메타데이터가 바뀌면 원본 증거로서의 가치가 훼손될 수 있다. 그래서 "zip 파일 압축 풀지 않고 해시값 추출"이라는 주제는 단순한 편의의 문제가 아니라, 디지털 포렌식과 증거 보존 관점에서 매우 중요한 실무 요구사항이다. 압축 파일 자체의 지문을 확보하고, 필요하다면 내부 항목들의 지문까지도 원본 아카이브를 건드리지 않은 채로 산출해내면, 나중에 "이 파일이 당시에 전달된 그 파일 그대로냐"는 질문에 암호학적으로 답할 수 있다.
해시값이라는 것은 파일의 바이트를 특정 알고리즘(SHA-256, MD5, CRC32 등)에 넣어 나온 고정 길이의 문자열이다. 파일 내용이 한 비트라도 바뀌면 전혀 다른 값이 나오기 때문에, 파일 동일성이나 변조 여부를 확인하는 데 있어 거의 확정에 가까운 증거로 쓰인다. ZIP 파일 전체에 대한 해시를 구하면, 누군가가 압축 파일 안의 문서를 수정한 뒤 다시 압축했거나, 압축 파일에 다른 파일을 끼워 넣었거나, 코멘트를 수정했을 때 그 사실을 즉시 포착할 수 있다. 반대로 ZIP 파일 자체의 해시가 동일하다면, 최소한 압축 파일 전체는 바이트 단위까지 동일하다는 뜻이 된다. 물론 여기서 "ZIP 파일의 해시가 같다면 그 안의 파일들도 모두 원본이다"라고 단정하면 안 된다. 압축 방식이나 코멘트, 타임스탬프 메타데이터만 바뀌고 내부 파일은 그대로인 경우에 ZIP 전체 해시는 달라질 수 있고, 이론적으로는 같은 내부 파일을 다른 압축 파라미터로 재구성해도 전체 해시는 달라지기 때문이다. 그래서 정확한 검증을 하려면 ZIP 전체 해시뿐 아니라 내부 항목별 해시까지 함께 확보하는 것이 바람직하다.
내부 항목별 해시를 구할 때 한 가지 주의할 점은, ZIP 포맷이 파일을 "저장" 또는 "축소(deflate)" 등의 방식으로 압축해서 담는다는 것이다. 흔히 압축 파일 안의 파일 해시를 구한다고 할 때 우리가 원하는 것은 "압축된 바이트 스트림"의 해시가 아니라 "압축을 풀었을 때 나오는 원래 파일"의 해시다. 그런데 어떤 도구는 압축된 상태의 바이트에 대해 해시를 계산하고, 어떤 도구는 압축을 해제한 원래 바이트에 대해 해시를 계산한다. 이 둘은 엄연히 다른 값이기 때문에, 감사 보고서나 재판 증거에서는 "이 해시가 압축 해제 후 원본 파일의 해시인지, 압축 상태 스트림의 해시인지"를 명확히 적어두는 것이 좋다. 그렇지 않으면 나중에 상대방이 "우리가 구한 해시와 값이 다르다"며 이의를 제기할 여지를 주게 된다. FilesAudit 같은 플랫폼은 ZIP 파일을 비밀번호 없이 압축 해제하지 않고도 내부 항목의 메타데이터와 해시 정보를 추출해 보고서 형태로 정리해주기 때문에, "내가 봤을 때 이 ZIP 안에는 이런 파일들이 있었고 각각의 지문은 이랬다"는 사실을 남기는 데 유용하다.
실무에서 가장 자주 마주치는 시나리오를 하나 들어보자. 법무팀이나 외부 감사자가 "2024년 3월에 거래처에서 받은 증빙 자료.zip"의 무결성을 1년 뒤에 확인해야 한다고 하자. 그때 받은 ZIP 파일을 그대로 보관하고 있었다면, SHA-256 한 줄이면 충분하다. 파일을 업로드하거나 로컬에서 해시를 구한 뒤, 당시에 기록해둔 해시와 비교하면 된다. 이때 주의할 것은, 파일을 클라우드에 올렸다 내려받는 과정에서 한 글자도 바뀌지 않았는지 확인해야 한다는 점이다. 드물지만 클라우드 동기화 도구가 파일을 변환하거나, 메일 첨부 시 인코딩이 바뀌는 경우가 있다. 이런 일이 없도록 ZIP 파일은 원본 받은 그 자리에서 곧바로 해시를 구해두고, 가능하면 전자증거용 파일 메타데이터 보고서 같은 형태로 타임스탬프와 함께 기록해두는 것이 안전하다. 보고서에는 파일 크기, 생성/수정 시각, 파일 시스템 메타데이터, 그리고 해시값이 함께 남기 때문에 "이 해시를 이 시점에 이 파일에서 구했다"는 사실을 문서로 증명할 수 있다.
좀 더 까다로운 케이스는 ZIP 안의 특정 파일만 검증해야 할 때다. 예를 들어, 아카이브 안에 "계약서_최종.pdf", "첨부1.jpg", "첨부2.xlsx"가 들어있는데, 분쟁이 된 건 계약서 PDF뿐이라고 해보자. 이때 ZIP 전체를 풀어 세 파일을 로컬에 꺼내면, 원본 아카이브에 손을 대지 않았더라도 디스크에 풀린 파일들은 새로운 생성/수정 시각을 가지게 된다. 포렌식적으로 깔끔하게 일으키려면 ZIP을 읽기 전용으로 마운트하거나, 내부 항목을 메모리에서만 압축 해제해서 해시를 구하는 도구를 써야 한다. 전문 도구를 쓰면 ZIP 파일을 실제로 압축 해제하지 않고도 내부 파일의 CRC나 압축 해제 후 해시를 구할 수 있고, ZIP 아카이브 자체의 구조(중앙 디렉터리, 각 엔트리의 오프셋, 압축 방식, 플래그)도 함께 덤프할 수 있다. 이런 구조 정보는 나중에 "누군가가 ZIP 안에 파일을 추가했다"거나 "숨겨진 엔트리가 있다"는 의심을 다룰 때 결정적인 단서가 된다.
개발자나 엔지니어 입장에서는 빌드 산출물 검증에도 같은 원리가 적용된다. CI/CD 파이프라인에서 산출된 ZIP 산출물을 배포할 때, "배포된 ZIP이 빌드 서버에서 만들어진 그 ZIP인지"를 확인하려면 빌드 시점에 ZIP 전체 해시를 기록해두고, 배포 시점에 다시 구해서 비교하면 된다. 내부 파일 개별 해시까지 기록해두면, 나중에 "이 ZIP 안의 특정 라이브러리만 바뀌었는지"도 추적할 수 있다. 이것은 소프트웨어 공급망 보안에서 점점 중요해지는 영역이다. 패키지 저장소나 아티팩트 저장소에서 ZIP을 내려받을 때, 저장소가 제공하는 체크섬과 직접 계산한 체크섬이 일치하는지 확인하는 습관을 들이면, 중간자 공격이나 저장소 오염으로 인한 위험을 크게 줄일 수 있다. 다만 ZIP 안의 파일을 개별적으로 검증하려면, 앞서 말한 대로 "압축 상태 스트림의 해시"인지 "압축 해제 후 원본 파일의 해시"인지를 명확히 구분해서 기록해야 한다.
ZIP 파일에 비밀번호가 걸려 있는 경우는 또 다른 이야기다. 비밀번호로 보호된 ZIP은 내부 파일의 메타데이터(파일명, 크기, CRC)는 중앙 디렉터리에 평문으로 남아있는 경우가 많지만, 파일 내용 자체는 암호화되어 있어서 비밀번호 없이는 압축 해제 후 해시를 구할 수 없다. 일부 도구는 비밀번호 없이도 압축된 상태의 바이트 스트림에 대한 해시는 구해주지만, 그것은 원본 파일의 해시가 아니라 암호문의 해시라서 사실상 검증 의미가 제한적이다. 그래서 암호 걸린 ZIP을 다루는 재판 증거에서는 "비밀번호를 알고 있는 상태에서 압축 해제 후 해시를 구했고, 그 과정에서 원본 아카이브는 변경하지 않았다"는 절차를 명확히 기록하는 것이 바람직하다. FilesAudit에 ZIP 파일을 올리면, 암호화 여부, 압축 방식, 내부 파일 목록, 각 항목의 크기와 CRC, 그리고 ZIP 전