빌드는 초록불이었는데 그 라이브러리는 누가 넣었나 · 서명은 멀쩡한데 그 키를 우리가 회수했다 · 실습
검증이 실패해야 하는 네 경우를 만든다
목표
릴리스 산출물에 직접 서명하고, 검증이 실패해야 하는 경우를 손으로 만들어 봅니다.
변조·다른 키·회수한 키·등록부에 없는 키 네 가지를 모두 거부하는 검증기를 만듭니다.
왜 중요한가
"서명을 붙였다" 는 문장은 아무것도 보장하지 않습니다. 보장은 검증이 실패하는 자리에서
생깁니다. 그래서 서명 체계를 도입할 때 먼저 할 일은 서명이 아니라, 실패해야 할 경우를
전부 적어 놓고 하나씩 실제로 실패시키는 것입니다. 특히 마지막 두 가지가 자주 빠집니다 —
서명 자체는 수학적으로 멀쩡한데 그 키를 우리가 더는 믿지 않는 경우입니다. 원시 키에는
만료가 없어서, 언제까지 믿을지는 바깥에 따로 적어야 합니다. sigstore 가 짧은 수명의
인증서와 투명성 로그를 쓰는 이유가 여기 있습니다 — 검증하는 쪽이 서명한 사람의 키 관리
습관에 기대지 않게 하려는 것입니다.
단계
1. 산출물을 /root/sign/dist 에 두고 지문을 /root/sign/01-digest.txt 에 적습니다.
2. P-256 키 쌍을 /root/sign/release.key 와 /root/sign/release.pub 에 만듭니다.
3. 산출물에 서명해 /root/sign/dist/paygate-1.4.2.js.sig 를 만듭니다.
4. 검증 출력을 /root/sign/04-verify.txt 에 남깁니다.
5. 변조본을 만들어 실패 출력을 /root/sign/05-tamper.txt 에 남깁니다.
6. 회수한 옛 키로 서명해 실패 출력을 /root/sign/06-oldkey.txt 에 남깁니다.
7. 두 키를 기한과 지문으로 /root/sign/keyring.json 에 등록합니다.
8. /root/sign/verify-release.sh 를 만들고 네 경우의 종료 코드를 /root/sign/08-checks.json 에 적습니다.
참고
- 이 이미지에는 cosign 이 없습니다. 키 없는 서명은 Fulcio·Rekor 라는 바깥 서비스를
- 서명 파일은 이진입니다.
cat으로 보지 말고-out으로 파일에 받으세요. - 검증 실패는 openssl 의 표준 오류로도 나갑니다. 기록할 때는
2>&1로 함께 받으세요. - 기준일은
2026-09-11로 고정합니다.date를 읽어 쓰면 내일 다른 답이 나옵니다. - 흔한 실수 — 서명할 때와 검증할 때 해시를 다르게 주는 것, 그리고 변조본을 만들었는데
- 실습 파드에는 볼륨이 없습니다. 여기서 만든 키는 세션이 끝나면 사라집니다.
전제하는데 파드는 DNS 만 열려 있습니다. 그래서 openssl 로 같은 뼈대를 만듭니다.
원본에 덮어써서 두 파일이 같아지는 것입니다.
단계 8개
- 서명할 물건을 한자리에 두고 지문을 뜬다
- 릴리스 키 쌍을 만든다
- 다이제스트에 서명한다
- 검증이 통과하는 것을 기록한다
- 산출물을 한 글자 고치면 어떻게 되는지 본다
- 작년에 쓰다 회수한 키로 서명된 것을 만든다
- 어떤 키를 언제까지 믿을지 적어 둔다
- 등록부를 보는 검증기를 만들고 네 경우를 판정한다