비트코인 주소는 사용자 편의를 위해 만들어진 개념이다. 보통은 비트코인을 특정 주소로 보낼 때 트랜잭션의 출력에 해당 주소가 직접적으로 기록되지는 않는다.
비트코인 초창기에는 공개키가 곧 주소였고, 해당 주소가 직접적으로 트랜잭션의 출력에 기록됐다. 하지만 이제는 몇 가지 표준화된 비트코인 주소를 사용하게 되면서 각 비트코인 주소가 가리키는 스크립트 유형으로 처리된다.
각 스크립트 유형의 비트코인 주소에 대해 알아보자.
공개키로부터 P2PKH 주소를 만드는 과정은 다음과 같다.
RIPEMD160(SHA256(pubkey))
0x00
버전 바이트 추가SHA256(SHA256(result2))
결과의 처음 4바이트를 추가Base58check(result3)
Base58check 결과값이 주소가 된다.
초기에는 공개키를 해싱하지 않고 그대로 사용했으며 주소라는 개념도 없었다(주소를 만드는 과정 자체가 없었다). P2PKH부터 주소라는 개념이 등장했고 공개키를 해싱해서 사용하기 시작했다. 공개키 해싱은 다음의 장점이 있다.
주소를 만드는 과정은 P2PKH와 거의 같으며 입력으로 리딤 스크립트(RedeemScript)를 사용한다는 점과 버전 바이트만 다르다. 리딤 스크립트로부터 P2SH 주소를 만드는 과정은 다음과 같다.
RIPEMD160(SHA256(redeemScript))
0x05
버전 바이트 추가SHA256(SHA256(result2))
결과의 처음 4바이트를 추가Base58check(result3)
공개키로부터 P2WPKH 주소를 만드는 과정은 다음과 같다.
RIPEMD160(SHA256(pubkey))
result1.length=20
=> result2.length=32
)00000
(5개의 비트) 버전 정보 추가 (result3.length=33
)bc
)를 이용해서 체크섬 계산 (코드)result4.length=39
)address.length=42
)주소를 만드는 과정은 P2WPKH와 거의 같으며 입력으로 리딤 스크립트(RedeemScript)를 사용한다는 점과 result1
계산 시 SHA256만 사용하고 RIPEMD160는 사용하지 않는다는 점이 다르다. 따라서 result1.length
는 32가 되고 5bit 배열로 변환 시 result2.length
는 P2WPKH 보다 20 만큼 더 커진다. 결과적으로 P2WSH 주소는 P2WPKH의 42 문자보다 20 더 많은 62 문자가 된다.
주소를 만드는 과정은 P2WPKH와 거의 같으며 버전 정보로 0이 아니라 1을 사용한다는 점과 인코딩 시 Bech32 대신 Bech32m를 사용한다는 점이 다르다. Bech32m은 Bech32 체크섬 계산의 약점을 보완했다. 그리고 P2TR에서는 서명 알고리즘으로 Schnorr를 사용하면서 변형된 공개키를 사용하게 된다.
비트코인 니모닉(mnemonic)은 종종 시드 문구(seed phrase) 또는 복구 문구(recovery phrase)로 불리며 비트코인 지갑을 생성하기 위한 초기 데이터를 사람이 읽을 수 있는 단어들의 연속으로 표현한 것이다.
복잡한 문자열로 이루어진 개인키를 사람이 관리하는 것은 실수의 여지가 있기 때문에 사용자 친화적인 니모닉을 사용하는 게 좋다. 현재 거의 모든 지갑 앱이 니모닉을 통해 지갑을 생성하는 프로세스를 채택하고 있다. 이때 니모닉을 프린트하거나 클립보드에 복사해서 메모장에 붙여넣는 등의 행동은 위험하다(라고 개인적으로 생각한다). 아날로그 방식으로 니모닉을 백업할 것을 추천한다.
니모닉은 BIP-39에서 제안되었으며 니모닉을 만드는 과정은 다음과 같다.
SHA256(엔트로피)
결과에서 (앞쪽부터) 체크섬 크기 만큼을 엔트로피 뒤에 붙인다. 예를 들어, 256비트 엔트로피에는 8비트 체크섬이 추가되어 총 264비트가 된다.체크섬이 존재하므로 단순히 니모닉 문구 24개를 선택하는 것으로는 유효하지 않은 니모닉이 생성될 확률이 높다. 23개의 단어를 선택했다면 마지막 1개의 단어로 들어갈 수 있는 단어는 2048개 중에 보통 10개 미만이다. 단어를 직접 선택하는 것은 무작위 생성이 아니므로 위험하다. 사람이 직접 선택하는 단어는 편향될 위험이 있기 때문에 비교적 쉽게 타인에게 노출될 수 있다.
니모닉을 생성할 때는 주사위 등의 무작위 생성 방식을 사용하는 게 좋다. 이미 많은 지갑 앱에서 주사위나 오디오/비디오 등의 무작위 데이터를 통한 니모닉 생성 기능을 제공하고 있다. 필요한 경우 필자가 만든 니모닉 생성 사이트를 이용하자.
12단어는 128비트 엔트로피로 이루어져 있으며 2^128 가지의 가능한 조합을 의미한다. 이는 엄청난 수치로, 현재의 컴퓨팅 기술로는 단순 대입(brute force) 공격으로 이를 깨트리기가 실질적으로 불가능하다. 단순 계산을 통해 초당 수조번의 시도를 할 수 있는 고성능 컴퓨터로도 10^25년 이상이 걸린다. 따라서 12단어도 충분히 안정적이라고 할 수 있다.
HD 지갑 (Hierarchical Deterministic Wallet)은 트리 구조를 사용하여 하나의 시드(보통 니모닉)에서 무한히 많은 개인키와 공개키를 파생시킬 수 있는 비트코인 지갑이다. HD 지갑의 주요 특징 및 장점은 다음과 같다.
BIP-44는 BIP-32를 확장하여 여러 암호화폐와 여러 계정을 지원하도록 정의한 프로토콜이다. BIP-44는 경로를 표준화하여 다양한 암호화폐와 계정을 구분하고 관리할 수 있게 해준다.
BIP-44는 다음과 같이 경로 구조를 정의한다.
m / purpose' / coin_type' / account' / change / address_index
여기서 각 섹션은 다음을 의미한다.
m
: master nodepurpose'
: 항상 44'
(BIP-44의 번호)로 고정coin_type'
: 각 암호화폐에 할당된 고유 번호 (Bitcoin은 0, Ethereum은 60)account'
: 사용자 지갑 내부의 계정 번호. 이를 통해 사용자는 지갑 안에 여러 개의 독립된 계정을 생성할 수 있다.change
: 0은 외부에 공개하는 주소용(수신 주소), 1은 내부 주소용(거스름돈 주소)address_index
: 주소의 인덱스 번호. 각 계정 내에서 주소를 생성할 때마다 증가예를 들어, m/44'/0'/0'
은 BIP-44 프로토콜을 따르고 비트코인을 관리하며 첫 번째 계정이라는 것을 의미한다. 만약 같은 니모닉으로 부모님의 비트코인 계정도 관리하고 싶다면 m/44'/0'/1'
을 활용할 수 있다.
BIP-49는 P2SH를 사용하여 SegWit 트랜잭션을 지원하는 주소를 생성하기 위한 방법을 제시한다. SegWit의 이점을 누리고 기존 시스템과의 호환성도 유지할 수 있도록 설계되었다. 이는 특히 레거시 시스템이나 지갑이 SegWit을 직접 지원하지 않는 경우에 유용하다. 다만 현재는 대부분의 지갑이 SegWit을 지원하므로 이 방식을 선택할 필요는 없어보인다.
BIP-49의 경로는 purpose'
부분에 49'
가 들어간다.
BIP-84는 BIP-44를 확장하여 SegWit 주소(P2WPKH) 생성을 지원하는 프로토콜이다. 현재 시점에 HD 지갑을 생성한다면 보통 이 프로토콜을 선택하게 된다.
BIP-84의 경로는 purpose'
부분에 84'
가 들어간다.
BIP-86은 BIP-44를 확장하여 Taproot 주소(P2TR) 생성을 지원하는 프로토콜이다. 현재 시점에는 이 프로토콜을 지원하는 지갑이 많지 않다.
BIP-86의 경로는 purpose'
부분에 86'
이 들어간다.
xpub은 확장 공개키(Extended Public Key)를 의미한다. 에어갭(air-gap) 방식의 하드웨어 지갑을 사용한다면 잔고 확인 및 수신 주소 확인을 위해 xpub를 추출해서 소프트웨어 지갑에 입력하게 된다.
xpub의 주요 구성요소는 다음과 같다.
m/84'/0'/0'
은 마스터 키에서 3단계 아래에 있으므로 Depth는 3이다. (m => 84 => 0 => 0)RIPEMD-160(SHA256(부모 공개키))
해시의 앞 4바이트다. 예를 들어, m/84'/0'/0'
의 Fingerprint는 m/84'/0'
의 공개키를 기반으로 계산된다.xpub을 사용하는 주된 이점 중 하나는 개인키를 노출하지 않고도 HD 구조를 통해 여러 공개키를 생성할 수 있다는 점이다. 예를 들어, 거래소나 지갑 서비스는 사용자의 개인키를 알 필요 없이 사용자의 각 입금마다 고유한 주소를 생성할 수 있다.
xpub이 주어지면, 해당 xpub에서 파생된 어떤 주소에도 입금할 수 있지만, 자금을 출금하거나 지출하기 위해서는 해당 주소의 개인키(xpriv)가 필요하다. 그러므로 xpub은 안전하게 공유될 수 있으며, 이를 통해 외부 서비스나 애플리케이션에서 해당 경로의 모든 주소에 대한 잔액을 모니터링할 수 있다.