기술 가이드

펌웨어 배포 파일 검증: CRC·SHA-256·전자서명·버전의 역할

펌웨어 배포에서 파일 내용, 서명, 대상 보드와 버전을 각각 확인해야 하는 이유를 설명하고 SHA-256 비교 실습을 제공합니다.

목차

펌웨어 배포 과정에서 “파일 검증이 끝났다”는 말은 확인 대상을 구체적으로 나눠야 의미가 있습니다. 전송 중 바이트가 달라졌는지, 승인된 키로 서명했는지, 대상 보드에 맞는지, 설치가 허용된 버전인지는 서로 다른 질문입니다.

이 글은 CRC, SHA-256, 전자서명과 버전 검증의 역할을 정리하고, 배포 기록에 무엇을 남길지 제안합니다. 예제는 PC에서 텍스트 샘플을 읽는 실습이며 실제 장치 설정을 바꾸지 않습니다.

1. CRC와 SHA-256은 확인 목적을 구분합니다

CRC는 통신이나 저장 과정의 우발적 오류를 찾는 데 널리 쓰이는 체크섬입니다. CRC 값이 맞는다는 사실을 송신자 인증으로 해석하면 안 됩니다. Python 공식 문서도 crc32를 인증이나 전자서명에 사용하지 않도록 설명합니다. Python zlib 문서

SHA-256은 배포 파일 전체에 대한 암호학적 해시를 계산할 때 사용할 수 있습니다. 해시와 파일 크기를 남기면 다운로드한 파일이 기록된 배포물과 일치하는지 점검하기 쉽습니다. 다만 해시 계산 자체에는 배포자의 비밀키가 들어가지 않으므로, 계산값 하나만으로 제작자를 확인할 수는 없습니다. Python hashlib 문서

확인 수단 주로 확인하는 것 별도로 확인할 것
CRC 전송·저장 중 오류 탐지 출처와 승인 여부
SHA-256 비교 기준 해시와 바이트 내용의 일치 기준 해시의 신뢰성
전자서명 검증 신뢰한 키에 대응하는 서명과 서명 대상의 무결성 키의 승인 상태, 대상 모델과 설치 정책
버전·모델 검사 배포 정책상 설치 가능한 대상인지 실제 파일의 무결성과 서명

해시가 같다는 것은 실무에서 같은 배포물인지 판단하는 강한 근거가 됩니다. 모든 가능한 파일에 수학적으로 서로 다른 해시가 배정된다는 뜻은 아닙니다.

2. 서명은 신뢰할 공개키와 함께 검증합니다

서명 파일이 존재한다는 사실만 확인해서는 충분하지 않습니다. 장치나 검증 도구가 신뢰하는 공개키를 기준으로 배포 규격이 정한 서명 대상을 검증해야 합니다. 이미지, 헤더, 패딩, 메타데이터 중 어디까지 보호하는지는 사용하는 형식에 따라 다릅니다.

구체적인 사례로 ESP32 리비전 v3.0 이후의 Secure Boot v2는 부트로더와 애플리케이션 이미지의 서명을 검증하는 절차를 제공합니다. 이 문서의 지원 범위와 설정은 다른 ESP32 계열 칩에 일괄 적용할 수 없으므로 대상 칩의 문서를 선택해야 합니다. Espressif Secure Boot v2 공식 문서

팀의 배포 절차에는 승인된 키 식별자, 서명 도구의 검증 결과, 검증 대상 파일의 해시를 함께 남기는 방식을 권합니다. 비밀키를 배포 ZIP이나 일반 검증 로그에 넣을 필요는 없습니다. 서명 성공이 프로그램의 기능상 결함까지 없음을 보장하지도 않습니다.

3. 정상 서명된 이전 버전도 설치 정책에서는 거절할 수 있습니다

과거에 승인한 펌웨어는 지금도 서명 검증에 성공할 수 있습니다. 따라서 서명 확인과 별개로 설치 대상 모델, 보드 리비전, 최소 허용 버전 등 제품의 정책을 검사해야 합니다.

ESP-IDF의 anti-rollback은 보안 버전을 이용해 이전 이미지로의 복귀를 제한하는 기능입니다. 제품 화면에 표시하는 버전 문자열과 같은 개념으로 취급하지 말고, 해당 플랫폼의 보안 버전 규칙과 복구 설계를 함께 확인해야 합니다. Espressif OTA anti-rollback 문서

다음은 배포 기록에 넣을 항목의 예입니다. 파일 이름만 보고 보드 호환성을 추정하는 대신, 검증되는 메타데이터와 실제 장치 정보를 대조하는 절차를 마련합니다.

  • 대상 제품과 하드웨어 리비전.
  • 사용자용 버전, 빌드 식별자, 필요한 경우 보안 버전.
  • 검증한 파일의 이름·크기·SHA-256.
  • 서명 키 식별자와 검증 결과.
  • 업데이트 후 자체 점검 결과와 실패 시 복구 경로.

이 목록은 팀 운영을 위한 제안이며 특정 MCU가 요구하는 메타데이터 형식은 아닙니다.

4. 파일명 변경과 내용 변경을 직접 비교합니다

자료실의 실습 ZIP에는 원본, 이름만 다른 동일 내용 파일, 한 바이트를 바꾼 파일이 들어 있습니다. 아래 코드를 hash_demo.py로 저장하거나 첨부 파일을 그대로 실행하면 결과를 확인할 수 있습니다.

from hashlib import sha256
from pathlib import Path


def file_sha256(path):
    digest = sha256()
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(65536), b""):
            digest.update(chunk)
    return digest.hexdigest()


if __name__ == "__main__":
    folder = Path(__file__).resolve().parent / "sample"
    original = file_sha256(folder / "demo-original.txt")
    renamed = file_sha256(folder / "demo-renamed.txt")
    changed = file_sha256(folder / "demo-changed.txt")
    print("original:", original)
    print("renamed:", renamed)
    print("changed:", changed)
    print("renamed_matches:", original == renamed)
    print("changed_matches:", original == changed)

마지막 두 줄은 다음과 같습니다.

renamed_matches: True
changed_matches: False

파일을 rb로 열어 디코딩 없이 원시 바이트를 읽습니다. 65,536바이트씩 나눠 같은 해시 객체를 갱신하므로 파일 전체를 한꺼번에 메모리에 올리지 않습니다. 읽기 청크 크기는 해시 대상의 경계를 바꾸지 않으며, 같은 바이트 순서를 모두 처리하면 같은 SHA-256이 나옵니다. hashlib의 update와 digest 설명

이 결과는 파일 내용 비교를 보여줍니다. 샘플 파일과 함께 제공된 해시 목록은 실습의 기준값이며, 독립된 배포자 인증 수단이 아닙니다.

5. 실패 지점별로 다음 조치를 정합니다

확인 결과 다음 확인
SHA-256 불일치 파일·버전·압축 전후 비교 대상과 다운로드 상태 확인
SHA-256 일치, 서명 실패 신뢰 키·서명 형식·서명 대상 범위 확인
서명 성공, 모델 불일치 대상 제품에 맞는 배포물 선택
서명 성공, 보안 버전 거절 제품의 최소 허용 버전 정책과 복구 절차 확인
모든 검증 통과, 부팅 후 이상 초기화·주변장치·데이터 마이그레이션과 자체 점검 로그 확인

배포 파일 검증 이후의 전원 중단과 첫 부팅 실패 처리는 ESP32 OTA 복구 설계에서 이어서 읽을 수 있습니다. 장치 통신과 업데이트 기능 개발은 ESP32 IoT 개발 안내를 참고하세요.

작성 기준: 2026-09-17. PC 실습은 PowerShell과 Python 해시를 교차 확인했으며, 이 글에서 실제 장치의 Secure Boot·eFuse·보안 버전 설정을 수행하지는 않았습니다.

관련 글

처리 중입니다...

잠시만 기다려주세요.