잊어버린 지갑 암호 찾기
복구 단어(시드 문구)는 있는데 거기 걸어둔 추가 암호가 기억나지 않을 때. 기억나는 조각만 넣으면 됩니다. 니모닉(시드 단어)은 여기에 넣지 마세요.
복구 단어(시드 문구)는 있는데 거기 걸어둔 추가 암호가 기억나지 않을 때 쓰는 도구입니다.
기억나는 조각을 입력하면 탐색해야 할 경우의 수와 예상 소요 시간을 계산합니다.
니모닉(시드 단어)은 여기에 입력하지 마세요 — 오프라인 프로그램에서만 입력합니다.
입력하신 내용은 이 브라우저 밖으로 나가지 않습니다. 서버로 보내지 않으니 기록될 것도 없습니다.
페이지를 연 뒤 나간 요청: 0건 — 개발자도구(F12, 맥은 Option+Command+I)의 Network 탭에서 직접 세어보세요.
그리고 여기에는 니모닉이 없습니다. 이 화면을 통째로 누가 본다 해도 그것만으로 지갑은 열리지 않습니다.
| 실행 환경 | 예상 소요 |
|---|
소요 시간은 어림입니다. 기본값은 기준 컴퓨터에서 실측한 속도이고, 버튼을 눌러
이 컴퓨터 속도를 재면 그에 맞춰 다시 계산합니다 — 복구에 쓰이는 것과 같은
PBKDF2-HMAC-SHA512(2048 라운드)를 이 페이지 안에서 돌려보는 것이고, 그 값은 밖으로 나가지 않습니다.
재고 나서도 나머지(주소 1개당 41.5µs, 코어를 늘렸을 때 실제로 나오는 배수)는 기준 기계에서
실측한 값이라 컴퓨터에 따라 다소 달라집니다. 프로그램은 실행 중 실제 속도로 남은 시간을 다시
계산해 보여주므로, 그쪽 숫자에는 어림이 없습니다.
성공은 보장되지 않습니다 — 실제 패스프레이즈가 위에서 정의한 조합 안에 없으면 찾을 수 없습니다.
패스프레이즈를 찾는 것으로 끝이 아닙니다. 시드 문구를 컴퓨터에 입력하는 순간부터 그 지갑은 더 이상 안전하다고 보기 어렵습니다. 미리 읽어 두시고, 하드웨어 지갑이 없다면 지금 주문해 두세요 — 찾고 나서 주문하면 기다리는 동안 위험이 계속됩니다.
어떤 프로그램도 "당신의 시드가 새어 나가지 않았다"를 증명할 수 없습니다. 저희 프로그램은 소스가 공개되어 있고 해시로 확인할 수 있지만, 같은 컴퓨터에 다른 무엇이 있었는지는 아무도 모릅니다. 증명하려 애쓰는 대신 새어 나가도 소용없게 만드는 편이 확실합니다. 자산을 새 지갑으로 옮기고 나면 옛 시드는 빈 지갑의 열쇠가 됩니다.
보내기 전에 받는 주소를 하드웨어 지갑 화면에서 직접 확인하세요. 앱에 보이는 주소와 기기 화면의 주소가 다르면 중단하세요. 거래를 만드는 기기는 개인키를 보지 못하므로 훔칠 것이 없지만, 받는 주소를 바꿔치기할 수는 있습니다. 하드웨어 지갑의 화면이 그것을 잡아내는 유일한 방법입니다.
주문해서 기다리는 동안에도 위험은 계속됩니다. 본인 명의 거래소 계정이나 새로 설치한 휴대폰 지갑으로 먼저 옮겨 두고, 기기가 도착하면 그때 다시 옮기세요. 완벽한 방법을 사흘 기다리는 것보다, 통제할 수 있는 곳으로 오늘 옮기는 편이 낫습니다.
복구는 오프라인에서 하시길 권합니다. 다만 그것이 안전하다는 증명은 아닙니다. 악성코드는 본 것을 그 자리에서 보낼 필요가 없습니다 — 적어 두었다가 컴퓨터가 다시 연결될 때 보내면 됩니다. 프로그램을 지워도 그 프로그램이 적어 둔 것은 지워지지 않습니다. 오프라인은 예방이지 증명이 아니고, 증명은 공개된 소스와 해시가 합니다. 그리고 어느 쪽도 자산을 옮기는 것만큼 확실하지는 않습니다.
대부분은 그대로 두시면 됩니다. 바꿔야 하는 경우가 드물어서, 먼저 그것부터 말씀드립니다 — 지갑 앱에서 ‘계정 추가’를 눌러본 적이 없다면 ‘첫 번째 계좌만’ 그대로 두세요.
씨앗 단어 하나로 만든 지갑 안에는 서로 완전히 분리된 계좌를 여러 개 둘 수 있습니다. 은행 통장 하나에 입출금 계좌와 적금 계좌가 따로 있는 것과 비슷합니다. 돈도 주소도 섞이지 않습니다.
Ledger Live나 Trezor Suite에서 ‘계정 추가’(Add account)를 누르면 그때 두 번째 계좌가 생깁니다. 눌러본 적이 없다면 계좌는 하나뿐입니다.
가장 헷갈리는 지점입니다. 계좌 하나 안에 주소가 수없이 많습니다. 파생 경로를 보면 두 숫자가 각각 어디인지 보입니다:
m/84'/0'/0'/0/0
│ │
계좌 번호 주소 번호
바로 위 칸 ‘확인할 주소 개수’는 오른쪽 숫자를 몇 개까지 볼지이고, 이 칸은 왼쪽 숫자를 몇 개까지 볼지입니다.
계좌 수와 주소 개수는 곱해집니다. 계좌 3개 × 주소 20개면 후보 하나마다 주소를 60개씩 만들어 대조한다는 뜻입니다. 그래서 계좌만 보고 ‘몇 배’라고 말할 수 없고, 주소를 몇 개로 두었느냐에 따라 이렇게 달라집니다:
주소 1개로 둔 경우 계좌 3개 → 1.1배 계좌 20개 → 2.2배 주소 20개로 둔 경우 계좌 3개 → 2.2배 계좌 20개 → 12배
둘 다 넉넉히 잡는 것이 가장 비쌉니다. 정확한 숫자는 오른쪽 ‘예상 소요’가 바꾸는 즉시 다시 계산해서 보여줍니다 — 표를 외우실 필요는 없고, 바꿔보고 숫자를 보시면 됩니다.
주소를 만들어 대조하는 부분은 정확히 20배가 됩니다. 그런데 그게 후보 하나를 시험하는 비용의 전부가 아닙니다. 후보당 실제로 걸리는 시간은 이렇게 쪼개집니다 (기준 컴퓨터 실측):
주소 1개 주소 20개
씨앗 만들기 (PBKDF2) 414.0us 414.0us ← 주소 수와 무관
후보 하나 처리하는 비용 189.5us 189.5us ← 주소 수와 무관
주소 유도 (41.5us x 개수) 41.5us 830.0us ← 여기만 20배
──────── ────────
합계 645.0us 1433.5us → 2.22배
패스프레이즈에서 씨앗을 만드는 계산(HMAC-SHA512를 2048번)이 가장 비싼데, 이건 후보마다 한 번입니다. 씨앗이 나온 뒤 주소를 뽑는 것은 훨씬 싸고, 그것만 20번 반복됩니다.
차를 10분 몰고 아파트에 가서 우편함을 여는 일과 같습니다. 우편함 하나 여는 데 30초라면, 20개를 열어도 운전은 한 번이라 전체가 20배가 되지는 않습니다.
그래서 줄여야 할 것은 후보의 수입니다. 기억을 하나 더 짜내 조각을 확정하면 그만큼 씨앗 만들기 자체가 줄어듭니다 — 오른쪽 ‘무엇을 좁히면 가장 빨라지나’가 그 배수를 보여줍니다.
자산이 두 번째 계좌에 있는데 첫 번째만 확인하도록 두면 오류 없이 그냥 못 찾습니다. 그래서 순서를 이렇게 권합니다 — 먼저 기본값으로 돌려보고, 못 찾았을 때 계좌 범위를 넓혀 다시 돌리세요. 반대로 하면 처음부터 몇 배를 기다리게 됩니다.
지갑 앱의 계정 목록을 보시면 몇 개를 만들어 두었는지 그대로 나옵니다. 하드웨어 지갑을 쓰신다면 Ledger Live나 Trezor Suite의 계정 화면입니다.
주소가 없으면 사실상 복구할 수 없습니다. 왜 그런지가 이 도구의 원리 그 자체라, 먼저 그것부터 설명드립니다.
다만 지금 모르신다고 해서 없는 것은 아닙니다. 자산이 있는 주소를 모르시더라도 거래소에서 그 지갑으로 보낸 기록 같은 것을 통해 알아낼 수 있는 경우가 많습니다. 찾는 방법은 아래에 정리해 두었습니다.
패스프레이즈에는 ‘틀렸습니다’가 없습니다. 어떤 문자열을 넣어도 지갑이 하나 만들어집니다. 틀린 패스프레이즈를 넣으면 오류가 나는 것이 아니라, 비어 있는 다른 지갑이 열릴 뿐입니다.
그래서 프로그램은 이렇게 일합니다 — 후보를 하나 넣어 지갑을 만들고, 거기서 주소를 뽑아, 알고 계신 주소와 같은지 대조합니다. 같으면 찾은 것이고, 다르면 다음 후보로 넘어갑니다. 대조할 주소가 없으면 맞은 것을 눈앞에 두고도 그냥 지나칩니다.
지갑 주소는 원래 공개된 정보입니다. 누군가에게 돈을 받으려면 알려줘야 하는 것이고, 블록체인에 이미 누구나 볼 수 있게 적혀 있습니다. 주소로는 자산을 가져갈 수 없습니다 — 그건 니모닉이 하는 일이고, 니모닉은 이 페이지에 절대 입력하지 않습니다.
패스프레이즈를 걸어서 만든 그 지갑의 주소여야 합니다. 여기가 가장 자주 어긋나는 지점입니다. 하드웨어 지갑은 패스프레이즈 없이 열리는 지갑과 패스프레이즈를 넣어 열리는 지갑이 서로 완전히 다른 지갑이고 주소도 전혀 다릅니다. 찾으려는 자산이 들어 있는 쪽, 그 주소를 넣으세요. 다른 쪽 주소를 넣으면 며칠을 돌려도 맞지 않습니다.
받는 주소든 거스름돈 주소든 상관없고, 하나면 충분합니다.
지갑은 씨앗 하나에서 주소를 계속 만들어내고 0번부터 번호가 붙습니다. 프로그램은 앞에서부터 정해진 개수만 확인하므로, 알고 계신 주소가 5번인데 1개만 확인하도록 두면 찾지 못합니다. 몇 번인지 모르시겠으면 아래 확인할 주소 개수를 20으로 잡으세요. 시간은 2배쯤 늘어납니다 — 공짜는 아니지만, 못 찾고 끝나는 것보다 낫습니다.
방법이 아주 없지는 않습니다. 잔고가 있는 모든 주소를 모아둔 파일(Address Database)을 놓고 대조하는 방식인데, 수십 GB짜리 파일이 필요하고 훨씬 느립니다. 이 페이지는 그 설정을 만들지 않습니다. 그전에 위 목록을 한 번 더 뒤져보시길 권합니다 — 주소 하나가 며칠을 아낍니다.
bc1qpr5e6syrl39vnarnj95la7fl4sv52yu0zfq75v
복사됨
아무 데도 가지 않습니다. 다만 그건 저희가 하는 말이고, 그 말을 믿지 않아도 확인할 수 있게 되어 있다는 것이 이 아래 내용입니다.
그 숫자는 이 페이지가 스스로를 세어서 적은 것입니다. 페이지를 의심하는 사람에게 페이지가 적어 준 숫자는 아무 것도 증명하지 못합니다. 편하라고 붙여 둔 표시일 뿐이고, 진짜 증거는 아래 두 가지입니다.
이 페이지는 다음 규칙과 함께 전달됩니다. 응답 헤더에 그대로 들어 있어 직접 읽어보실 수 있습니다.
Content-Security-Policy: default-src 'none'; connect-src 'none'; form-action 'none'; base-uri 'none'; frame-ancestors 'none'
connect-src 'none'이 핵심입니다. 이 한 줄이 fetch,
XMLHttpRequest, WebSocket, sendBeacon을
전부 막습니다. form-action 'none'은 폼으로 보내는 길까지 막습니다.
이건 약속이 아니라 브라우저가 강제하는 규칙이라, 페이지가 보내려고
시도해도 실패합니다 — 그리고 그 실패가 콘솔에 빨갛게 찍힙니다.
index.html)와
style.css 둘뿐입니다. 그 뒤로는 무엇을 입력하고 무슨 버튼을 눌러도
목록이 늘지 않습니다.config.json 내려받기도
전부 그대로 됩니다. 보낼 곳이 필요했다면 여기서 멈췄을 것입니다.브라우저 안에서 만들어져 다운로드 폴더로 바로 저장됩니다. 어디에도 올라가지 않습니다. 위 Network 탭에 아무 것도 늘지 않는 것으로 확인하실 수 있고, 인터넷을 끊은 채로도 받아진다는 것이 같은 이야기입니다.
이 화면이 통째로 다른 사람에게 보인다면, 그 사람이 알게 되는 것은 지갑 주소와 입력하신 조각입니다. 니모닉이 없으니 그것만으로 지갑은 열리지 않지만, 주소로 잔고를 조회할 수는 있습니다.
그래서 위험이 전혀 없다고는 말씀드리지 않습니다. 대신 이렇게 하세요 — 끝나면 탭을 닫고, 남기고 싶지 않으시면 방문 기록에서 지우세요. 그리고 니모닉은 어떤 경우에도 이 페이지에 입력하지 마세요. 그것 하나만 지키면 이 화면이 새어도 지갑은 안전합니다.
“누군가 이 페이지를 받아갔다”는 기록뿐입니다. 손님이 입력한 것은 애초에 저희에게 도달하지 않으므로, 지울 것도 숨길 것도 없습니다.
의심하시는 게 맞습니다. 그래서 설명 대신 무엇이 실행되는지 그대로 적어둡니다.
복구 프로그램이 하는 것과 똑같은 계산을 이 페이지 안에서 0.1초쯤 돌려보고, 몇 번 했는지 세는 것이 전부입니다. 컴퓨터에 대해 캐내는 것이 아니라, 그냥 문제를 하나 풀려보고 시간을 재는 것입니다.
PBKDF2-HMAC-SHA512를 2048번 반복합니다. BIP39 지갑이 패스프레이즈에서 시드를
만들 때 쓰는 바로 그 계산이고, 복구 프로그램이 후보 하나를 시험할 때마다 하는
계산입니다. 그래서 이 속도가 곧 복구 속도입니다. 브라우저에 원래 들어 있는
crypto.subtle을 쓰며, 외부에서 가져오는 코드는 없습니다.
이 계산에 들어가는 값은 "passphrase0", "passphrase1" …
같은 지어낸 문자열입니다. 손님이 입력한 것은 무엇도 쓰이지 않습니다.
브라우저가 알려주는 것은 코어 개수 하나(navigator.hardwareConcurrency)뿐이고,
그것도 화면의 입력칸에 그대로 보여주며 직접 고치실 수 있습니다.
측정 결과는 이 페이지의 계산에만 쓰이고 사라집니다. 쿠키도, 저장소도 쓰지 않아 새로고침하면 다시 재기 전 상태로 돌아갑니다.
이건 약속이 아니라 브라우저가 강제합니다. 이 페이지는 스스로에게
connect-src 'none' 규칙을 걸어두어, 설령 코드가 어딘가로 보내려 해도
브라우저가 막습니다. F12 → 네트워크 탭을 열고 버튼을 눌러보세요.
요청이 하나도 늘지 않습니다. 화면 위쪽 요청 수 표시도 그대로 0입니다.
이 페이지 소스(Ctrl+U)의 measureThisMachine()가 전부입니다.
const key = await crypto.subtle.importKey(
"raw", enc.encode("passphrase" + i), "PBKDF2", false, ["deriveBits"]);
await crypto.subtle.deriveBits(
{name:"PBKDF2", salt, iterations:2048, hash:"SHA-512"}, key, 512);
이걸 120번 하면서 매번 걸린 시간을 적고, 평균이 아니라 하위 20% 지점의 값을 씁니다. 컴퓨터가 잠깐 다른 일에 붙들리면 한 번이 통째로 느려지는데, 평균을 쓰면 그 방해가 "이 컴퓨터는 몇천 배 느립니다"가 되어 몇 년짜리 예상 시간이 나옵니다. 실제로 겪은 일입니다. 방해는 계산을 느리게만 만들지 하드웨어보다 빠르게 만들 수는 없으므로, 아래쪽 값이 진짜 속도에 가깝습니다. 터무니없는 값이 나오면 아예 버리고 기준 속도를 씁니다.
잰 것은 1코어 속도 하나입니다. 코어를 여러 개 썼을 때 실제로 몇 배가 나오는지, 주소 유도에 얼마가 걸리는지는 저희 기준 컴퓨터에서 잰 값이라 컴퓨터에 따라 다소 다릅니다. 그래서 이 시간은 구매 판단용 어림입니다. 복구 프로그램은 실행 중 실제로 나오는 속도로 남은 시간을 계속 다시 계산해 보여주므로, 그쪽 숫자에는 어림이 없습니다.