코인을 옮기지 않고 하는 소유 증명
비트코인 주소의 개인키로 메시지에 서명하면 코인을 한 개도 옮기지 않고 그 주소를 통제한다는 사실을 보일 수 있다. 2011년 signmessage에서 BIP-137, 2026년 완료된 BIP-322까지, 그리고 서명이 증명하지 못하는 것과 거래소의 개인지갑 확인까지 정리한다.
개인키를 직접 다루기 시리즈 7/8편
- 단어 12개에 평생 모은 비트코인이 전부 담긴다
- 이 12개 단어를 잃어버리면, 수억 원이 영원히 사라집니다
- 인터넷에 연결된 지갑 vs 금고 속 지갑
- Coldcard·Jade·Trezor·Ledger 보안 모델 비교
- 하드웨어 지갑은 이전 거래 전체를 요구한다
- 열쇠가 있어도 금고는 찾을 수 없다
- 코인을 옮기지 않고 하는 소유 증명
- 내가 갑자기 죽으면, 내 비트코인은 어떻게 되는가
2016년 5월 2일, 크레이그 라이트는 자신이 사토시 나카모토라는 증거로 블로그에 서명 하나를 올렸다. 사르트르의 글에 사토시의 키로 서명했다는 설명이 붙어 있었다. 곧 그 서명이 2009년 블록체인에 이미 기록된 거래에서 그대로 복사해 온 것이라는 사실이 드러났다. 보안 연구자 댄 카민스키는 그를 세계 최초로 암호학적으로 증명 가능한 사기꾼이라고 불렀다.
4년 뒤인 2020년 5월, 라이트가 미국 소송에서 자기 것이라고 내놓은 주소 145개로 서명된 메시지가 공개됐다. 첫 문장은 이랬다. 크레이그 스티븐 라이트는 거짓말쟁이이고 사기꾼이다, 그는 이 메시지에 서명한 키를 갖고 있지 않다. 마지막 문장은 우리 모두가 사토시다였다.
두 사건에 쓰인 도구는 같다. 비트코인 주소의 개인키로 임의의 문장에 서명하는 기능이다. 한 번은 거짓 주장을 무너뜨리는 데 실패한 위조로, 한 번은 그 주장을 반박하는 증거로 쓰였다. 2027년 2월부터는 이 도구가 한국의 평범한 이용자에게도 가까워진다. 트래블룰 개정으로 개인지갑과의 이전은 송신인과 수신인이 같은 경우에만 허용되고, 같은 사람인지 확인하는 가장 깔끔한 방법이 바로 메시지 서명이기 때문이다.
비밀을 보여주지 않고 비밀을 증명한다
비트코인에서 소유란 주소에 대응하는 개인키를 쥐고 있다는 뜻이다. 코인을 쓰려면 그 키로 거래에 서명해야 하고, 네트워크는 서명이 맞는지만 확인한다. 키 자체는 어디에도 전송되지 않는다.
메시지 서명은 이 구조에서 거래를 빼고 문장을 넣은 것이다. 거래소가 "2026년 10월 13일, 거래소 계정 확인용"이라는 문장을 주면, 나는 그 문장에 내 주소의 키로 서명해 돌려준다. 거래소는 주소와 문장과 서명 세 가지만으로 검증한다. 맞으면 이 문장에 서명한 사람이 그 주소를 쓸 수 있는 키를 갖고 있다는 결론이 나오고, 코인은 한 개도 움직이지 않는다.
라이트의 2016년 서명이 실패한 지점도 여기서 보인다. 서명은 수학적으로 유효했다. 다만 그것은 사르트르의 글이 아니라 2009년 거래의 내용에 대한 서명이었다. 서명은 어떤 문장에 대한 것인지까지 함께 검증되므로, 검증하는 쪽이 원래 문장을 직접 넣어 돌려 보면 맞지 않는다. 라이트가 내놓은 설명은 그 단계를 독자가 건너뛰도록 쓰여 있었다.
2011년의 signmessage
메시지 서명은 2011년 9월 30일 Pieter Wuille의 코드가 병합되면서 비트코인에 들어왔고, 그해 11월 0.5.0 버전에 signmessage와 verifymessage 명령으로 실렸다. 동작은 단순하다. 서명할 문장 앞에 정해진 문구를 붙이고 해시한 뒤 그 해시에 ECDSA 서명을 한다.
Bitcoin Signed Message:\n
이 문구가 붙는 이유는 Bitcoin Core 소스의 주석에 적혀 있다. 서명된 메시지가 뒤따른다는 표시이고, 실수로 거래에 서명하는 일을 막기 위해서다. 문장에 대한 서명이 어떤 경우에도 거래에 대한 서명으로 해석될 수 없도록 처음부터 둘을 갈라 놓은 것이다.
결과물은 65바이트이고 보통 Base64 문자열로 주고받는다. 여기에는 공개키가 들어 있지 않다. 첫 바이트에 공개키 복구 정보가 담겨 있어서, 검증하는 쪽이 서명과 문장만으로 공개키를 다시 계산해 낸다. 그 공개키를 해시한 값이 주소와 같으면 통과다.
이 마지막 비교 때문에 이 방식은 공개키 해시가 곧 주소인 경우, 즉 1로 시작하는 P2PKH 주소에서만 성립한다. 지금도 그렇다. 2026년 10월 현재 Bitcoin Core의 signmessage에 bc1 주소를 넣으면 이 오류가 돌아온다.
Address does not refer to key
주소가 늘어나자 형식이 갈라졌다
2017년 세그윗 이후 지갑의 기본 주소는 3으로 시작하는 감싼 세그윗과 bc1q로 시작하는 네이티브 세그윗으로 옮겨 갔다. 주소 형식은 바뀌었는데 메시지 서명은 여전히 1로 시작하는 주소만 알았다.
지갑들은 각자 우회로를 만들었고, 2019년 이 관행을 문서로 정리한 것이 BIP-137이다. 동기 절은 문제를 이렇게 적는다. P2PKH 주소로 서명하는 방법은 문서는 없어도 잘 알려진 과정이지만, 세그윗 주소가 도입되면서 서명만 보고는 그것이 P2PKH인지 P2SH인지 bech32인지 구분할 방법이 분명하지 않게 됐다는 것이다. BIP-137의 해법은 첫 바이트의 범위를 늘리는 것이었다. 27부터 34까지는 기존의 P2PKH, 35부터 38까지는 감싼 세그윗, 39부터 42까지는 네이티브 세그윗이다.
이것은 꼬리표를 붙인 것이지 구조를 바꾼 것은 아니다. 여전히 단일 키 하나의 ECDSA 서명이고, 그래서 멀티시그 주소나 스크립트로 잠긴 주소, 슈노르 서명을 쓰는 탭루트 주소는 이 형식으로 다룰 수 없다. BIP-137 본문도 이미 장점이 많은 새 형식이 정의되어 있다며 BIP-322를 가리키고, 일부 소프트웨어는 새 범위의 첫 바이트를 오류로 처리한다고 적어 두었다.
BIP-322는 서명을 거래로 바꿨다
BIP-322의 발상은 주소 유형마다 서명 규칙을 따로 만드는 대신, 비트코인이 이미 갖고 있는 검증기를 그대로 쓰자는 것이다. 어떤 주소든 그 주소의 코인을 쓰는 방법은 스크립트가 정의하고 있다. 그렇다면 그 주소에서 코인을 쓰는 척하는 거래를 만들어 스크립트를 통과시키면 된다.
그래서 BIP-322는 가상의 거래 두 개를 만든다. 첫째 거래는 존재하지 않는 출력을 입력으로 삼는다. 이전 거래 번호가 전부 0이고 출력 번호가 0xFFFFFFFF인, 실제로는 있을 수 없는 자리다. 이 입력에는 메시지의 해시가 들어가고, 출력은 금액 0에 서명할 주소의 잠금 스크립트를 단다. 메시지 해시는 BIP-340 방식의 태그 해시로 계산하고, 태그 문자열은 BIP0322-signed-message다.
둘째 거래는 첫째 거래의 그 출력을 쓴다. 출력은 금액 0의 OP_RETURN 하나뿐이다. 서명하는 사람은 둘째 거래가 스크립트 검증을 통과하도록 증인 데이터를 채우고, 그것이 곧 서명이 된다. 검증하는 쪽은 두 거래를 다시 만들어 합의 규칙대로 검사한다. 단 하나의 예외는 첫째 거래의 입력이 존재하지 않는다는 점이다. 바로 그 예외 때문에 이 거래는 네트워크에 내보내도 절대 유효해질 수 없다.
이 설계의 장점은 범위다. BIP-322 동기 절의 표현으로는 어떤 스크립트로 통제되는 코인이든 원칙적으로 서명할 수 있다. 멀티시그 주소라면 여러 서명자가 협력해 증인 데이터를 채우고, 이를 위해 PSBT에 전용 필드가 추가됐다. 하드웨어 지갑은 어떤 주소로 어떤 메시지에 서명하는지를 화면에 보여 주도록 권고된다.
형식은 넷이다. 1로 시작하는 주소에만 쓰는 기존 방식, 증인 데이터만 담는 간단한 형식, 둘째 거래 전체를 담는 전체 형식, 그리고 자금 증명이다. 2026년 4월 15일 BIP-322는 완료 상태가 되면서 서명 앞에 형식을 알리는 접두사 smp, ful, pof를 붙이도록 바뀌었다. 하위 호환이 깨지는 변경이라고 문서 스스로 밝혔으니, 그 전에 만들어진 구현이 내놓는 서명과는 모양이 다를 수 있다. 6월 4일에 2.0.0 판이 나왔다.
검증 결과도 둘이 아니라 셋이다. 유효, 무효, 그리고 판단 불가다. 검증기가 아직 모르는 스크립트 버전이나 업그레이드용 연산자를 만나면 판단 불가를 낸다. 미래의 소프트포크를 미리 무효라고 단정하지 않으려는 장치다.
표준이 끝났어도 지갑은 아직이다
BIP 문서는 완료됐지만 구현은 고르지 않다. Bitcoin Core에는 BIP-322를 넣으려는 풀 리퀘스트가 2019년, 2020년, 2022년 세 차례 올라왔고 모두 병합되지 않고 닫혔다. 마지막 시도의 작성자는 지갑 코드가 바뀌는 속도를 따라가는 데 드는 노력이 기능에 대한 관심과 전혀 맞지 않았다고 남겼다. Core에서 갈라져 나온 Bitcoin Knots는 2025년 4월 28.1 버전에서 BIP-322를 지원한다.
지갑 쪽에서는 Sparrow가 2023년 7월 1.7.8 버전에서 탭루트를 포함한 단일 서명 주소에 BIP-322 서명을 추가했다. Trezor Suite는 메시지 서명과 검증 기능을 제공하지만 탭루트 계정에서는 쓸 수 없다고 안내한다. Ledger Live에는 비트코인 메시지 서명 기능이 없어서 Sparrow 같은 외부 지갑에 연결해 서명한다.
실무적으로 말하면, 1로 시작하는 주소는 어디서나 서명과 검증이 된다. bc1q 주소는 대부분의 지갑에서 되지만 형식이 BIP-137인지 BIP-322인지에 따라 다른 도구에서 검증이 실패할 수 있다. bc1p 탭루트 주소와 멀티시그는 BIP-322를 지원하는 소수의 도구에서만 된다.
서명이 증명하지 못하는 것
BIP-322는 자기 한계를 동기 절에 직접 적어 두었다. 어떤 메시지 서명 프로토콜도 자금의 통제를 실제로 증명할 수는 없다. 서명은 만들어지는 순간 낡은 것이 되고, 비밀키를 가진 사람이 다른 사람을 대신해 서명해 줄 수도 있기 때문이다.
첫째 한계는 시간이다. 서명은 그것이 만들어진 시점에 그 키를 누군가 쥐고 있었다는 사실만 말한다. 서명 다음 날 키가 다른 사람에게 넘어갔어도 서명은 여전히 유효하다. 메시지에 날짜와 상대가 정한 임의의 문자열을 넣는 이유가 이것이다. 적어도 그 문장이 만들어지기 전에 미리 서명해 둘 수는 없게 된다.
둘째 한계는 사람이다. 서명은 이 키를 가진 쪽이 이 문장에 동의했다는 것까지만 보인다. 키를 가진 사람이 누구인지는 서명 바깥의 문제다. 수탁 업체가 고객을 대신해 서명할 수도 있고, 남의 부탁을 받고 서명할 수도 있다. 2020년의 145개 서명도 정확히는 이 키들을 가진 쪽이 라이트가 아니라는 사실을 보였을 뿐, 그 키를 가진 쪽이 누구인지는 지금도 말하지 않는다.
셋째 한계는 범위다. 서명은 그 주소를 통제한다는 사실을 보일 뿐 그것이 전부라는 사실은 보이지 못한다. 2011년 6월 23일 마운트곡스는 지갑을 통제하고 있음을 보이려고 424,242.42424242 BTC를 한 번에 옮겼다. 그 지갑이 고객 잔고 전체를 덮는지는 그 거래가 말해 주지 않았고, 2014년 파산 때 약 85만 BTC가 사라진 것으로 드러났다. BIP-322의 자금 증명 형식도 같은 선을 긋는다. 제시한 코인이 전부라는 것도, 아직 쓰이지 않았다는 것도 증명하려 하지 않는다고 문서에 적혀 있다. 거래소가 수천 개 주소의 코인을 한꺼번에 이렇게 보이려 할 때 무엇이 더 필요하고 무엇이 끝내 남는지는 준비금 증명에서 이어서 다뤘다.
거래소는 무엇으로 확인하나
유럽은 이 질문에 목록으로 답했다. 유럽은행감독청의 트래블룰 가이드라인은 1,000유로를 넘는 자기보관 주소 이전에서 사업자가 쓸 수 있는 소유 확인 방법을 다섯 가지로 열거한다. 비대면 검증 과정에서 주소를 화면에 띄워 보이는 방법, 대면 검증, 사업자가 정한 소액을 그 주소와 사업자 계정 사이에 주고받는 방법, 그 주소의 키로 특정 메시지에 서명하게 하는 방법, 그리고 신뢰할 수 있는 다른 기술적 수단이다. 하나로 충분하지 않으면 여러 방법을 조합하고, 확인된 주소는 화이트리스트에 올릴 수 있다.
한국은 아직 방법을 정하지 않았다. 개정 시행령은 송·수신인이 동일한 경우라는 요건을 두었을 뿐이고, 동일인을 무엇으로 확인할지는 감독규정과 업계 안내에 남아 있다. 현재 관행은 거래소마다 다르다. 업비트는 개인지갑 주소를 등록할 때 지갑을 연결하고 지갑 소유 확인을 위한 서명을 받는다. 안내문이 예로 드는 것은 메타마스크 같은 브라우저 확장 지갑이다. 2022년 화이트리스트 도입 당시 코인원은 출금 주소와 본인 정보가 함께 보이는 화면을 이미지나 영상으로 받았고, 코빗은 지갑 화면과 신분증을 함께 찍어 내도록 했다.
서명 방식은 셋 가운데 가장 정확하면서 가장 오래 남는다. 화면 캡처는 거래소 서버에 있는 사진 한 장이지만, 서명은 누구든 언제든 다시 검증할 수 있는 수학적 연결이다. 2022년 1월 Trezor가 지갑 안에서 서명 증명을 한 번에 처리하는 프로토콜을 넣었다가 곧 철회한 이유가 그것이었다. 기술의 결함이 아니라 그 연결이 너무 단단하다는 것이 반대의 근거였다.
서명하기 전에 확인할 것
거래소가 서명을 요구하면 먼저 메시지를 읽는다. 무엇에 동의하는지 모르는 문장에는 서명하지 않는다. 메시지 서명은 거래 서명과 구조적으로 분리되어 있어서 서명 한 번으로 코인이 빠져나가지는 않지만, 서명한 문장은 그 자체로 남는다.
서명용 주소를 따로 쓴다. 서명은 그 주소와 내 신원을 영구히 묶는다. 장기 보관용 주소 전체가 아니라 거래소에서 받기 위한 주소 하나를 서명에 쓰고, 받은 다음에는 다른 주소로 옮기는 편이 자기수탁의 의미를 덜 해친다. 주소를 다시 쓰지 않는 습관과 같은 이유다.
하드웨어 지갑이라면 기기 화면을 본다. 컴퓨터 화면에 뜬 메시지와 기기가 보여 주는 메시지와 주소가 같은지 확인하는 것이 하드웨어 지갑을 쓰는 이유다.
마지막으로 검증해 본다. 서명을 내기 전에 같은 지갑이나 다른 도구의 검증 기능에 주소, 문장, 서명을 넣어 통과하는지 확인한다. 형식이 갈라져 있는 지금은 내 지갑이 만든 서명을 상대 도구가 읽지 못하는 일이 드물지 않다.
서명은 이름을 말하지 않는다
2020년의 메시지는 145개의 주소가 같은 문장에 서명한 기록이다. 그 서명들이 증명한 것은 정확히 하나다. 이 키들을 가진 누군가가 이 문장에 동의했다는 것. 그 누군가의 이름은 서명 어디에도 없다.
거래소의 개인지갑 확인도 같은 구조다. 서명은 키와 문장을 묶고, 이름은 그 문장을 요구한 쪽이 붙인다. 코인을 옮기지 않고 소유를 증명할 수 있다는 것은 편리한 일이다. 동시에 그 증명은 한번 내주면 거둘 수 없다. 어떤 주소에 이름을 붙일지는 서명하는 사람이 고를 수 있는 마지막 선택이다.