SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-27

Linux에서 sha256sum으로 파일 무결성 검증하는 방법

sha256sum 명령어를 사용하여 다운로드한 파일의 해시값을 검증하는 절차를 설명합니다. SHA256SUMS 파일을 생성하고 비교하는 방법부터 의도적인 파일 손상을 통해 체크섬 오류가 발생하는 상황까지 실습하며 무결성 확인의 원리를 정확히 이해할 수 있습니다.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 12, 2026.

2분 안에 체크섬으로 다운로드 파일 검증하기

체크섬으로 다운로드를 검증하려면, 받은 파일의 해시를 생성한 뒤 게시자가 공개한 해시값과 비교해야 합니다. sha256sum은 이 두 가지 작업을 모두 수행합니다. 단독으로 실행하면 다이제스트를 출력하고, -c 옵션을 사용하면 다이제스트 목록을 읽어 어떤 파일이 일치하는지 보고합니다. 이 가이드에서는 직접 파일을 생성하여 전체 과정을 수행한 뒤, 의도적으로 파일을 손상시켜 실패 상황을 직접 확인해 보겠습니다.

진행하는 동안 다음 문장을 항상 기억하십시오. 체크섬은 현재 보유한 바이트가 다이제스트를 생성한 원본 바이트와 일치하는지 여부만 알려줄 뿐, 누가 생성했는지는 알려주지 않습니다. 누가 생성했는지 확인하려면 서명과 신뢰할 수 있는 키가 필요합니다. 이 가이드의 마지막 부분에서 두 개념의 경계가 어디인지 명확히 설명합니다.

실습용 파일 생성

시스템의 다른 부분에 영향을 주지 않도록 작업 디렉터리에서 수행합니다. 아래의 모든 명령어는 모든 Ubuntu 또는 Debian 서버에 기본으로 포함된 GNU coreutils 패키지에 속하므로 별도의 설치가 필요 없습니다.

mkdir -p ~/checksum-demo
cd ~/checksum-demo
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum payload.txt

결과로 64자리의 16진수 문자열, 공백 두 칸, 그리고 파일 이름이 한 줄 출력됩니다. 이 64자리는 파일의 다이제스트(digest)입니다. 해싱은 결정론적이므로 명령어를 다시 실행해도 동일한 입력에 대해서는 항상 같은 결과가 나옵니다. 파일의 문자 하나만 바꿔도 다이제스트는 조금만 변하는 것이 아니라 완전히 다른 값으로 바뀝니다. 입력 비트 하나만 바뀌어도 출력 비트의 절반가량이 바뀌기 때문입니다. 이러한 특성 덕분에 64자리의 문자열을 4 GB 이미지 파일의 대용물로 사용할 수 있습니다.

SHA256SUMS 파일을 저장하고 검증하기

화면에 출력된 다이제스트는 하루만 지나도 쓸모가 없습니다. 나중에 도구가 다시 읽을 수 있도록 sha256sum이 작성하는 형식 그대로 파일에 기록하십시오.

sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMS

sha256sum -c는 목록의 각 줄을 읽고 해당 줄에 명시된 파일의 해시를 계산한 뒤 두 다이제스트를 비교합니다. 정상적으로 실행되면 파일당 한 줄씩 결과가 출력됩니다.

payload.txt: OK

스크립트는 텍스트를 읽지 않고 종료 상태 코드만 확인하므로 이 값도 함께 점검해야 합니다. echo $?는 정상 실행 후 0을 출력합니다. SHA256SUMS이라는 이름은 규칙이라기보다 관례에 가깝지만, 배포판과 대부분의 릴리스 페이지에서 사용하므로 동일하게 사용하여 다른 사람이 파일을 열어보지 않고도 내용을 파악할 수 있게 하십시오.

바이트 하나를 변경하여 검사 실패 확인하기

이제 의도적으로 파일을 손상시킵니다. 아래 명령은 오프셋 5 지점에 단일 바이트를 기록하며 다른 부분은 그대로 둡니다. 따라서 파일의 길이와 이름은 유지됩니다.

printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMS

conv=notrunc은 중요한 플래그입니다. 이 플래그가 없으면 dd는 쓰기가 중단된 지점에서 파일을 잘라내 버리므로, 훨씬 더 명백한 형태의 손상을 테스트하게 됩니다. 이제 검사를 수행하면 다음과 같이 출력됩니다.

payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

echo $?1을 출력합니다. FAILED는 파일을 읽었으나 해당 다이제스트가 목록에 있는 값과 일치하지 않음을 의미합니다. 원래 바이트로 되돌린 뒤 검사 결과가 OK으로 돌아오는지 확인하십시오.

printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMS

이것이 전체 습관입니다. 파일 내 어디든 바이트 하나만 달라도 FAILED가 발생합니다. 연결 끊김으로 인한 다운로드 중단, 어제 빌드된 파일을 제공하는 미러 서버, 전송 중 파일을 재작성한 프록시, 불량 블록을 반환한 디스크 등 모든 문제가 동일한 결과로 이어집니다.

목록에 다운로드하지 않은 파일이 포함된 경우

배포판에서 제공하는 실제 SHA256SUMS 파일에는 해당 프로젝트가 배포하는 모든 이미지 목록이 포함되어 있으며, 사용자는 그중 하나를 다운로드하게 됩니다. 이 상황을 여기서 재현해 봅니다.

printf 'a second file\n' > notes.txt
sha256sum payload.txt notes.txt > SHA256SUMS.all
rm notes.txt
sha256sum -c SHA256SUMS.all
payload.txt: OK
sha256sum: notes.txt: No such file or directory
notes.txt: FAILED open or read
sha256sum: WARNING: 1 listed file could not be read

FAILED open or readFAILED와는 다른 오류이며, 이 둘을 혼동하면 시간을 낭비하게 됩니다. FAILED은 데이터의 바이트가 일치하지 않음을 의미합니다. FAILED open or readsha256sum가 파일을 전혀 가져오지 못해 비교 자체가 수행되지 않았음을 의미합니다. 실제 다운로드 시 흔히 발생하는 원인은 작업 디렉터리 문제입니다. 목록에 기재된 파일명은 명령을 실행하는 위치를 기준으로 하는 상대 경로이기 때문입니다. 파일이 있는 디렉터리로 이동한 뒤 명령을 다시 실행하십시오. 실제로 보유한 파일만 확인하려면 다음과 같이 요청하십시오.

sha256sum --ignore-missing -c SHA256SUMS.all

이 명령은 payload.txt: OK을 출력하고 0을 반환하며 종료됩니다. 목록에 있는 파일이 하나도 존재하지 않는 경우, --ignore-missing은 파일이 없는데도 성공으로 처리하지 않습니다. 대신 no file was verified라는 메시지를 보고하고 0이 아닌 값으로 종료됩니다. 이는 사용자가 의도한 동작입니다. 아무것도 검사하지 않은 상태에서 성공하는 것은 결코 알아차릴 수 없는 실패이기 때문입니다.

눈으로 확인하지 않고 게시된 다이제스트 붙여넣기

64자 16진수 문자열을 눈으로 비교하는 습관은 보안상 매우 위험합니다. 사람들은 보통 앞의 네 글자와 뒤의 네 글자만 확인하고 일치한다고 판단하는데, 공격자는 바로 이 점을 노립니다. 비교 작업은 도구에 맡기십시오. 게시자로부터 복사한 다이제스트를 EXPECTED에 설정하고, EXPECTED= 뒤에 붙여넣은 값을 입력한 다음, -c가 요구하는 한 줄의 형식을 만듭니다.

printf '%s  %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256

다이제스트와 파일 이름 사이에는 공백 두 개가 들어갑니다. 이것이 형식 문자열에 공백 두 개가 포함된 이유입니다. 이 형식이 sha256sum이 기록하는 방식이자 -c이 해석하는 방식입니다. 다이제스트만 들어 있는 파일은 체크섬 라인이 아니므로, 검사 도구는 어떤 파일을 의도했는지 추측하지 않고 no properly formatted checksum lines found 오류를 반환하며 전체 파일을 거부합니다. 일부 프로젝트는 SHA256 (payload.txt) = 뒤에 다이제스트가 오는 BSD 태그 스타일을 게시하기도 합니다. GNU coreutils는 sha256sum --tag payload.txt으로 이 형식을 기록하고 -c로 읽어 들이므로, 두 형식 모두 저장하기에 적합합니다.

검사가 이상하게 동작한다면 cat -A SHA256SUMS를 사용하여 목록 자체를 확인하십시오. 이 명령은 모든 줄의 끝을 $으로 표시하여 눈에 보이지 않는 문자를 보여줍니다. 줄 끝에 ^M$가 있다면 Windows 편집기에서 생성된 캐리지 리턴이 포함된 것입니다. GNU sha256sum는 이 끝 문자를 무시하고 OK을 출력하므로, CRLF 형식의 목록 자체가 검사를 실패하게 만드는 원인은 아닙니다. 하지만 coreutils 외의 다른 도구들은 이 문자에 더 민감할 수 있습니다. 보관 중인 복사본은 tr -d '\r' < SHA256SUMS > SHA256SUMS.clean을 사용하여 정규화하십시오.

체크섬은 무엇을 증명하며, 무엇을 증명하지 못하는가?

체크섬은 단 한 가지 사실을 증명합니다. 디스크에 있는 바이트가 게시된 다이제스트를 생성한 바로 그 바이트와 동일하다는 점입니다. 이는 우발적인 데이터 손상을 완벽하게 방지합니다. 또한 다운로드 미러에서 파일을 교체했으나 다이제스트가 게시된 페이지는 수정하지 못한 부주의한 공격자의 시도도 막아낼 수 있습니다.

체크섬은 작성자에 대해서는 아무것도 증명하지 않습니다. 다이제스트는 바이트에 대한 사실일 뿐, 사람에 대한 사실이 아니기 때문입니다. 만약 한 페이지에서 파일과 다이제스트를 모두 제공한다면, 어느 하나를 변경할 수 있는 사람은 다른 하나도 변경할 수 있습니다. 이 경우 귀하의 OK 라인은 미러 서버가 자기 자신과 일치한다는 사실만을 의미할 뿐입니다. 따라서 체크섬을 실행할 가치가 있게 만드는 규칙은 다음과 같습니다. 파일을 가져온 곳과 다른 곳에서 다이제스트를 가져오십시오. 예를 들어, 이미지는 미러나 토렌트에서 가져오고, 다이제스트는 TLS(전송 계층 보안)를 통해 프로젝트의 공식 도메인에서 가져오는 방식입니다. 이제 공격자는 한 곳이 아닌 두 곳을 모두 통제해야만 합니다. 또한 체크섬은 검증된 바이트가 실행될 때 어떤 동작을 할지에 대해서는 아무것도 알려주지 않습니다. 이는 설치 스크립트부터 에이전트 권한으로 실행되는 dsh 플러그인에 이르기까지, 귀하를 대신하여 실행되는 모든 것에 대해 반드시 던져야 할 별개의 질문입니다.

알고리즘 또한 중요합니다. SHA-256(보안 해시 알고리즘, 256비트 출력)은 2026년 8월 기준으로 알려진 충돌 사례가 없으며, 이것이 게시자들이 이 알고리즘을 사용하는 이유입니다. MD5(메시지 다이제스트 5)와 SHA-1은 더 이상 안전하지 않습니다. 동일한 MD5 다이제스트를 가진 서로 다른 두 파일은 2004년부터 생성 가능해졌으며, 선택된 접두사 SHA-1 충돌은 2020년에 발표되었습니다. MD5SUMS 파일은 여전히 다운로드 중단 현상을 잡아낼 수 있는데, 이는 무작위적인 손상은 의도적으로 조작된 충돌이 아니기 때문입니다. 하지만 누군가 귀하를 속이려 할 때는 이를 막을 수 없습니다. 프로젝트에서 두 가지를 모두 게시한다면, SHA-256 라인을 선택하십시오.

서명이 역할을 대신하는 경우

서명은 다이제스트가 남겨둔 빈틈을 메웁니다. 게시자는 개인 키로 다이제스트 파일을 서명하고, 사용자는 게시자의 공개 키인 gpg --verify SHA256SUMS.asc SHA256SUMS으로 이를 검증합니다. 검증이 통과되면 해당 다이제스트 목록은 그 키를 보유한 주체가 작성한 것임을 알 수 있습니다. 이후 sha256sum -c SHA256SUMS은 디스크에 있는 파일과 목록을 연결하며, 이로써 키에서부터 실제 바이트 데이터까지 신뢰의 사슬이 이어집니다.

취약점은 키로 옮겨갑니다. 파일과 키를 동일한 페이지에서 가져오면 공격자에게 양쪽 모두를 넘겨주는 꼴이 됩니다. GnuPG는 이 점을 명확히 하며, 최초 검증 시 WARNING: This key is not certified with a trusted signature!과 함께 Good signature를 출력합니다. Good signature는 수학적 검증이 성공했음을 의미할 뿐, 해당 키가 의도한 프로젝트의 소유임을 보장하지는 않습니다. 프로젝트의 다른 도메인 문서나 이미 키를 포함하고 있는 배포 패키지 등 제2의 경로에서 지문(fingerprint)을 확인하십시오. 이때 마지막 8자리만 확인하지 말고 전체 지문을 비교해야 합니다. 이는 SSH 개인 키를 다룰 때와 같은 주의가 필요한 작업이며, 그 이유는 동일합니다. 키는 신뢰를 결정하는 핵심 요소이며, 그 이후의 모든 과정은 이 키를 상속받기 때문입니다.

재현 가능한 빌드(reproducible builds)는 이 개념을 한 단계 더 발전시킵니다. 게시된 다이제스트는 여전히 특정 서버에서 빌드된 바이너리에 의존하게 만듭니다. 프로젝트의 빌드가 재현 가능하다면, 누구나 동일한 소스 코드를 컴파일하여 바이트 단위까지 일치하는 결과물을 얻을 수 있습니다. 따라서 특정 서버의 말만 믿는 대신, 독립적인 빌더들이 게시된 다이제스트를 직접 검증할 수 있습니다. 자동화된 파이프라인과 기계가 작성한 패치를 통해 코드가 유입되는 비중이 늘어남에 따라, 이러한 검증의 중요성은 매년 커지고 있습니다. 빌드에 무엇을 포함할지 결정하는 것은 정책의 영역이며, AI 지원 코드를 위한 오픈 소스 정책은 동일한 공급망의 반대편에서 이 문제를 다룹니다.

패키지 관리자가 이미 이 작업을 수행합니다

Debian 및 Ubuntu에서는 apt가 설치할 때마다 별도의 요청 없이 이 체인을 실행합니다. 패키지 인덱스에는 각 .deb 파일에 대한 SHA-256 다이제스트가 포함되어 있습니다. Release 파일은 해당 인덱스 파일들의 다이제스트를 담고 있으며, InReleaseRelease에 대한 서명을 포함합니다. 이 서명은 /usr/share/keyrings/etc/apt/trusted.gpg.d에 있는 키와 대조하여 검증됩니다. 체인이 끊어지면 apt는 이를 알립니다. 서드 파티 저장소의 키가 누락된 경우 The following signatures couldn't be verified because the public key is not available: NO_PUBKEY가 발생하며, 가져온 인덱스가 서명된 Release와 일치하지 않는 경우 Hash Sum mismatch이 발생합니다. 이는 보통 캐싱 프록시가 오래된 파일을 제공했거나 미러 서버가 동기화 중일 때 발생합니다.

프로젝트 홈페이지에서 curl의 스크립트를 파이프를 통해 셸로 바로 실행하라고 안내할 때, 이 기준을 적용해야 합니다. 바이트를 검증하는 과정이 전혀 없으며 내용을 확인할 수도 없습니다. 서버는 브라우저에는 정상적인 파일을 보내고 스크립트에는 다른 내용을 보낼 수 있으며, 나중에 검사할 사본도 남지 않습니다. curl -fsSL <url> -o install.sh을 사용하여 파일로 다운로드하고, 해시값을 확인하고, less로 내용을 읽은 뒤에만 실행하십시오. 이 습관을 들이는 데는 약 20초 정도 소요됩니다. 이는 새로운 VPS를 처음 10분 동안 설정할 때 다른 어떤 소프트웨어를 설치하기 전부터 시작해야 할 중요한 습관입니다.

수동으로 설치한 파일의 다이제스트 목록 유지하기

apt로 설치한 패키지는 시스템이 추적합니다. 사용자가 직접 /usr/local/bin에 복사한 바이너리는 추적 대상이 아니며, 시스템의 어떤 도구도 이를 감시하지 않습니다. 다이제스트 목록을 만들면 필요할 때마다 파일의 무결성을 검사할 수 있습니다.

printf 'a second file\n' > notes.txt
sha256sum *.txt > inventory.sha256
sha256sum -c --quiet inventory.sha256

--quiet은 모든 파일이 일치하면 아무것도 출력하지 않으며, 일치하지 않는 경우에만 실패한 행을 출력합니다. 따라서 아무런 출력이 없는 것이 곧 통과를 의미하며, echo $?0를 사용하여 이를 확인합니다. 이 형식을 예약된 작업(scheduled job)에 사용하면 됩니다. --status은 한 걸음 더 나아가 아무것도 출력하지 않고 종료 상태(exit status)만 반환합니다. sha256sum /usr/local/bin/* > ~/local-bin.sha256를 사용하여 실제 파일들을 대상으로 동일한 패턴을 적용하면 기준점(baseline)을 확보할 수 있습니다. 경로는 입력한 그대로 목록에 저장되므로, 절대 경로를 사용해야 어떤 디렉터리에서든 검사가 정상적으로 작동합니다.

이 기준점이 갖는 가치를 명확히 이해해야 합니다. 이 방식은 파일이 변경되었음을 탐지할 뿐입니다. 이미 root 권한을 획득한 공격자는 탐지할 수 없습니다. 공격자는 바이너리를 수정하는 것만큼 쉽게 inventory.sha256도 수정할 수 있기 때문입니다. 목록의 신뢰성을 확보하려면 해당 파일을 시스템 외부의 안전한 곳에 보관해야 합니다. 이는 VPS를 얼마나 신뢰할 수 있는지 그리고 디스크에 접근할 수 있는 다른 주체가 누구인지에 관한 더 넓은 보안 문제의 일부입니다.

FAQ

체크섬이 일치하면 다운로드 파일이 안전한가요?

아니요. 체크섬이 일치한다는 것은 사용자가 가진 바이트가 비교 대상인 다이제스트와 일치한다는 의미일 뿐입니다. 공격자가 다이제스트를 게시한 페이지를 제어하고 있다면, 공격자는 자신의 파일에 대한 다이제스트를 게시할 것이고 사용자의 검사 결과는 OK을 출력할 것입니다. 일치는 데이터의 무결성을 보장할 뿐입니다. 안전성을 보장하려면 다른 경로에서 획득한 키로 검증된 서명이 필요하며, 그 서명이 확인된 후에야 다이제스트가 신뢰를 얻을 수 있습니다.

sha256sum -cFAILED open or read을 출력하나요?

파일을 읽지 못했기 때문입니다. 바로 윗줄에 No such file or directory와 함께 찾으려는 파일 이름이 표시됩니다. SHA256SUMS 파일 내의 이름은 명령을 실행하는 디렉터리를 기준으로 하므로, 다운로드한 파일이 있는 디렉터리로 이동한 뒤 다시 실행하십시오. 목록에 다운로드하지 않은 파일이 포함되어 있다면 --ignore-missing을 추가하십시오. open or read 없이 단순히 FAILED이 출력되는 경우는 정반대의 상황입니다. 즉, 파일은 읽었으나 다이제스트가 일치하지 않는 경우입니다.

다운로드 검증에 MD5를 사용해도 충분한가요?

우발적인 데이터 손상을 확인하는 용도로는 충분합니다. 전송 중 파일이 잘리거나 디스크 블록에 오류가 발생했을 때 우연히 MD5 다이제스트가 일치할 확률은 거의 없습니다. 하지만 공격자를 방어하는 용도로는 부족합니다. 2004년부터 동일한 MD5 다이제스트를 가진 서로 다른 두 파일을 생성할 수 있게 되었으며, SHA-1 역시 2020년에 충돌 공격이 가능해졌습니다. 프로젝트에서 두 가지를 모두 제공한다면 SHA-256을 사용하십시오. MD5만 제공하는 프로젝트는 릴리스 프로세스가 오래되었음을 의미합니다.

sha256sum -cgpg --verify의 차이점은 무엇인가요?

sha256sum -c는 파일이 다이제스트와 일치함을 증명합니다. gpg --verify은 다이제스트 파일이 특정 개인 키 소유자에 의해 서명되었음을 증명합니다. 두 명령은 서로 다른 질문에 답하므로, 프로젝트에서 둘 다 제공한다면 모두 실행하십시오. 서명은 다이제스트 목록을 신뢰할 수 있게 만들고, 다이제스트 목록은 다운로드한 파일을 신뢰할 수 있게 만듭니다.

웹 페이지에 표시된 다이제스트로 파일을 어떻게 검증하나요?

눈으로 직접 문자를 비교하지 마십시오. 다이제스트와 파일 이름을 공백 두 개로 구분하여 한 줄로 저장한 뒤, 해당 파일에 대해 sha256sum -c을 실행하고 출력되는 OK 또는 FAILED를 확인하십시오. printf '%s %s\n'을 사용하여 줄을 구성하면 sha256sumno properly formatted checksum lines found 오류를 발생시키는 서식 오류를 방지할 수 있습니다.

#checksums#sha256sum#integrity#supply-chain#security