서버 없이 인증서를 지키는 법, 서명 64바이트가 하는 일

QR코드가 붙은 수료증을 받아본 적이 있다면 다들 한 번쯤 스캔해봤을 거다. 화면에 이름과 과정명이 뜨면 왠지 안심이 된다. 그런데 사실 그 QR이 하는 일은 대개 "이 URL을 열어라" 뿐이다. URL 뒤에 데이터베이스가 있고 조회 결과를 보여주는 구조라면, 그 QR 자체는 위조를 막지 못한다. 러시아 개발자 SurMaster가 Habr에 올린 글에서 든 예가 정확히 이 지점을 찌른다. 진짜 유효한 인증서의 QR을 복사해서 이름만 다른 위조 문서에 붙이면 스캔은 여전히 "유효함"으로 뜬다. QR 이미지 자체는 아무 것도 검증하지 않기 때문이다.
같이 보면 흐름이 이어지는 글
그래서 이 개발자가 택한 방법은 조회가 아니라 서명이다. 인증번호, 이름, 과정명, 날짜를 하나로 묶어 발급 기관의 개인키로 서명해 QR에 넣는다. 이러면 이름 한 글자만 바꿔도 서명이 깨진다. 개인키 없이는 새 서명을 만들 수 없으니 위조가 원천적으로 막힌다. 여기서 Ed25519를 고른 이유도 실용적이다.
| 항목 | RSA | Ed25519 |
|---|---|---|
| 서명 크기 | 256~512바이트 | 64바이트 |
| QR 밀도 | 큼 | 작음 |
| 대표 사례 | 구형 인증서·TLS | SSH 신규 키, Signal |
표에서 보듯 QR에 담을 데이터가 짧아야 QR 자체도 작고 스캔이 편해지니, 서명 알고리즘 선택이 곧 사용자 경험으로 이어지는 셈이다. Ed25519는 SSH 키 생성에서 이미 사실상 표준으로 자리 잡은 알고리즘이라 작은 키와 서명 크기로 검증도 빠르다. 저자는 이 방식으로 명단 50명분 인증서를 15초 만에 뽑아냈다고 밝혔는데, 서명·QR 생성이 전부 로컬 스크립트 한 번으로 끝난다는 뜻이다.
서버를 없애면 신뢰도 사라지지 않을까
그런데 서명을 검증하려면 공개키가 필요하고, 공개키를 어딘가에 공개해야 한다. 보통이라면 서버를 하나 띄우고 API를 만들 텐데, 이 프로젝트는 그마저도 GitHub Pages 정적 페이지 하나로 대체했다. 공개키를 HTML에 상수로 박아넣고, QR을 스캔하면 열리는 페이지가 URL 프래그먼트(# 뒤 부분)에 담긴 서명값을 브라우저 안에서 곧바로 검증한다. 프래그먼트는 서버로 전송되지 않는 값이라 개인정보가 로그에 남을 일도 없다. 데이터베이스도, 백엔드도, 유지보수할 서버도 없다. 새 교육 기수가 시작되면 명단 하나 올리고 커맨드 한 줄 실행하면 끝난다는 저자의 말이 과장으로 안 들리는 이유다. 돈도 거의 안 든다. 호스팅은 무료고, 매년 나가는 돈은 도메인 갱신비 15달러 정도가 전부다.
여기까지 읽으면 이걸로 위조가 완전히 사라진다고 생각하기 쉬운데, 저자 본인이 먼저 선을 긋는다. 이 서명이 지키는 건 "이 발급 기관이 발급한 특정 인증서 한 장"의 무결성이지, 발급 기관 자체를 사칭하는 사기는 막지 못한다. 사기꾼이 자기 키로 서명하고 자기 도메인에 똑같이 생긴 검증 페이지를 올리면, 그 페이지 안에서는 얼마든지 "유효함"이 뜬다. 그래서 실제 방어선은 결국 도메인이다. 진짜 발급 기관이 소유한 도메인 주소를 인증서 위에 인쇄해두고, 사람이 육안으로 그 주소를 확인하는 마지막 단계가 있어야 이 구조 전체가 의미를 가진다. 국내에서도 위조 서류로 취업까지 성공한 사건이 보도된 적 있는데, 그런 사기는 QR이나 서명 여부보다 애초에 가짜 발급 기관을 진짜처럼 꾸미는 데서 시작한다. 서명 기술이 아무리 정교해져도 사람이 도메인을 확인하지 않으면 뚫리는 구간은 여전히 남는다.
작은 발급 기관에 더 맞는 이유
블로그 사진을 GitHub 저장소에 올리고 jsDelivr로 불러오는 방식을 몇 달째 쓰고 있다. 저장소에 파일 하나 커밋하면 끝이라 서버 걱정을 해본 적이 없는데, 그 감각이 QR 인증서에도 그대로 적용된다는 게 흥미로웠다. 트래픽이 크지 않은 개인·소규모 프로젝트에서는 정적 페이지에 로직을 최대한 밀어넣는 쪽이 합리적이라는 걸 몸으로 겪은 셈이다. 교육 과정 수료증처럼 발급량은 적고 위조 시도도 흔치 않은 영역에서는 서버와 데이터베이스를 갖춘 정교한 인증 시스템이 오히려 과잉이다. 저자 스스로도 이 정도 보호 수준이면 대부분의 실제 사기 시나리오에는 충분하다고 인정한다.
결국 이 글이 남긴 판단은 하나다. 서명은 데이터 위변조를 막고, 정적 호스팅은 그 서명을 검증할 자리를 공짜로 마련해주지만, 발급 기관이 누구인지 확인하는 몫은 여전히 사람에게 남아 있다. 다음에 QR 인증서를 만들 일이 생기면 나도 서버부터 세우지 않고 이 구조를 먼저 떠올릴 것 같다. 다만 QR 옆에 발급 기관 도메인을 크게 박아두는 것도 잊지 않을 생각이다.
대화 참여하기