오픈 소스 프로토콜 중에서 비트코인이 독특한 점은 프로토콜을 변경하는 것이 극도로 어렵다는 것입니다. 대부분의 다른 프로토콜에서는 기능을 즉시 추가, 수정 또는 폐기할 수 있지만, 비트코인 세계에서는 가장 사소한 변경조차도 전체 비트코인 네트워크의 대다수의 동시 협력이 필요합니다. 그 이유는 간단합니다: 비트코인에서는 절대적인 합의가 필요합니다. HTML 및 CSS와 같은 인터넷 프로토콜에서는 웹 브라우저가 일부 스타일 요소를 잘못 해석하더라도 웹페이지가 잘못 표시되는 것 외에는 큰 문제가 발생하지 않습니다. 반면 비트코인에서는 단일 거래가 잘못 유효하거나 무효가 되면 전체 블록이 무효가 되어, 2013년 3월처럼 전체 네트워크가 반으로 나뉠 수 있습니다. 결과적으로 사토시 나카모토가 2008년에 내린 대부분의 결정은 우리가 본질적으로 고착되어 있습니다. 사토시의 선택이 완벽하지는 않았지만, 다행히도 그는 대체로 옳았던 것으로 보입니다. 사실, 사토시가 내린 선택 덕분에 우리가 모두 더 나은 상황이 된 경우가 여러 번 있습니다.
주소는 공개 키의 해시
비트코인의 흥미롭고 처음에는 약간 혼란스러운 측면 중 하나는 개인 키와 비트코인 주소 간의 정확한 관계입니다. 일반적으로 거래는 “비트코인 주소”로 전송되며, 주소로 전송된 돈을 주장하려면 (즉, 비트코인 지갑이) 해당 “개인 키”로 생성된 디지털 서명을 포함하는 거래를 만들어야 합니다. 비트코인 주소는 공개적으로 안전하게 배포할 수 있지만, 개인 키는 암호화된 비트코인 지갑에 안전하게 저장해야 합니다.
예를 들어, 무작위로 생성된 개인 키는 다음과 같습니다: 5JexEhxcSeADA4MmpHq426zC2935JHKc2de1nphv75u8TRhAqqP
그에 해당하는 주소는: 1MEMPfCcqatuWxHWFsFcyhDTq3eV61xLB4
그렇다면 이 두 값 간의 관계는 무엇일까요? 그 답은 공개 키 암호학이라는 수학의 한 분야에 있습니다. 암호학이라는 용어는 일반적으로 비밀을 안전하게 전송하는 기술과 관련이 있지만, 공개 키 암호학은 실제로 다른 목적으로 더 자주 사용됩니다: 인증. 예를 들어, 소프트웨어 회사가 모든 사용자에게 업데이트를 전송하고 싶지만, 다른 사람들이 컴퓨터 바이러스를 포함한 가짜 업데이트를 게시하지 못하도록 안전하게 수행하고 싶다고 가정해 보겠습니다. 공개 키 암호학을 사용하면 소프트웨어 회사는 개인 키와 공개 키로 구성된 키 쌍을 생성하고 소프트웨어에 공개 키를 포함할 수 있습니다. 회사가 업데이트를 전송할 때, 개인 키를 사용하여 암호화된 디지털 서명 알고리즘으로 업데이트를 디지털 서명하고, 클라이언트는 업데이트를 수신한 후 공개 키의 복사본을 사용하여 서명의 유효성을 확인할 수 있습니다. 공격자가 소프트웨어 회사의 비밀 개인 키를 알지 못한 채 가짜 업데이트를 만들려고 하면, 서명이 유효성을 검사하지 못하고, 공격자가 정당한 업데이트를 전송 중에 수정하더라도 서명이 유효성을 검사하지 못합니다.
이것이 비트코인과 같은 통화에서 어떻게 사용될 수 있는지 볼 수 있습니다: 모든 사람이 자신의 공개 키를 게시하고, A에서 B로 보내려면 A가 자신의 개인 키로 B의 공개 키가 포함된 메시지에 서명해야 합니다. 이를 통해 프로토콜은 A가 B에게 돈을 보내는 거래를 승인했음을 추론할 수 있습니다.
하지만 비트코인은 더 복잡합니다. 비트코인 주소는 공개 키가 아니라, 공개 키의 해시입니다. 해시는 어떤 것을 입력으로 받아 고정 크기의 출력을 생성하는 함수로, 역으로 계산하는 것은 거의 불가능한 특성을 가지고 있습니다. 즉, 메시지 M이 주어지면 hash(M)을 계산하는 것은 쉽지만, hash(M)가 주어지면 M을 찾는 데는 우주의 열적 사멸 이후까지 걸릴 것입니다. 비트코인에서는 개인 키와 주소 간의 관계가 다음과 같습니다:
그렇다면 거래는 어떻게 작동할까요? 거래 자체에 대한 명백한 정보 외에도 비트코인 거래에는 두 가지가 포함됩니다: 지출자의 공개 키와 지출자의 개인 키로 생성된 서명입니다. 거래를 검증하는 사람은 (1) 공개 키의 해시가 지출자의 주소인지 확인하고, (2) 서명이 공개 키와 일치하는지 확인합니다. 이 두 가지 사실을 종합하면, 거래가 지출자의 주소에 해당하는 개인 키의 소유자에 의해 이루어졌거나 승인되었다는 증명이 됩니다.
이 점은 놀라울 정도로 평범합니다: 비트코인이 사용하는 타원 곡선 DSA 암호 시스템 하에서는 공개 키가 512비트 길이로, 이를 표현하는 데 거의 100자의 문자가 필요합니다.
예를 들어, 공개 키는 다음과 같습니다: 04b52fd5a616a8f08ccad58469102f86fc7891e5aa4262ab8d43e41767c17d45b80850044a62af51783609176daf02fc46221057a8de11ee6ae8743065b27a4b5e
그에 해당하는 비트코인 주소는 16진수 형태로: 4b463093e6fc3135a4de2ff577c4b658198777a9
그리고 더 익숙한 base58 형태로: 1obodiqhAZ3GD9onBXRZ9v7hshkuBreCu
하지만 실제로는 사토시가 생각했던 것만큼 많은 것을 달성하지 못합니다.
사실, 공개 키를 훨씬 더 간결하게 인코딩하는 방법이 있으며, 단 257바이트만 차지합니다: 03c5c9833d00bed3211a5f3733316ecf6ebc407806d70caa14862f1e2e8c2f852d
그리고 이를 base58 형태로 변환하면: 15sqRCowBDTfyuxPQD3ba8sN3wBB8MwGbo6gsBEGeKmUbNQADGh
오늘날 우리가 사용하는 주소보다 그렇게 길지 않습니다. 그렇다면 사토시의 선택은 불필요한 복잡성과 낭비를 초래한 것일까요? 사실, 대답은 아닙니다.
공개 키 해시 주소 구조를 사용하는 또 다른 매우 좋은 이유는 양자 암호학입니다. 양자 컴퓨터는 타원 곡선 DSA를 깨는 것이 가능하지만 (즉, 공개 키가 주어지면 양자 컴퓨터는 개인 키를 매우 빠르게 찾을 수 있습니다), 해시 알고리즘을 역으로 계산하는 것은 불가능합니다 (또는 가능하지만 비트코인 주소를 해독하는 데 280회의 계산이 필요하며, 이는 여전히 매우 비현실적입니다). 따라서 비트코인 자금이 사용하지 않은 주소에 저장되어 있다면 (즉, 공개 키가 알려지지 않았다면), 양자 컴퓨터에 대해 안전합니다 – 적어도 사용하려고 시도하기 전까지는 말입니다. 비트코인을 완전히 양자 안전하게 만드는 이론적인 방법이 있지만, 주소가 단순히 공개 키의 해시라는 사실은 양자 컴퓨터가 등장하더라도 공격자가 우리가 완전히 전환하기 전에 훨씬 적은 피해를 줄 수 있다는 것을 의미합니다.
2100만 BTC 한도
비트코인의 다소 논란이 있는 속성 중 하나는 고정된 통화 공급입니다. 현재 10분마다 25 BTC가 생성되고 있으며, 이 양은 4년마다 절반으로 줄어듭니다. 결국 존재하는 비트코인은 2100만 개를 넘지 않을 것입니다. 반면, 각 비트코인은 1억 개의 조각(“사토시”라고 불림)으로 나눌 수 있으므로, 비트코인의 가치가 상승하더라도 사용하기 어려워지지 않을 것입니다. 따라서 총 통화 단위 수는 2,100,000,000,000,000: 2.1경, 즉 약 250.899입니다. 이 수치를 선택한 사토시는 대부분 사람들이 인식하는 것보다 훨씬 더 운이 좋거나 현명했습니다.
우선, 이 숫자는 264 – 1보다 훨씬 적습니다. 이는 컴퓨터의 표준 정수에 저장할 수 있는 가장 큰 정수입니다. 그 이상으로 가면 정수는 제로로 돌아갑니다. 하지만 또 다른 더 낮은 임계값이 있습니다. 총 사토시 수는 이 임계값보다 약간 낮습니다: 부동 소수점 형식으로 정확하게 표현할 수 있는 가장 큰 정수입니다.
정수는 컴퓨터가 저장할 수 있는 유일한 숫자 종류가 아닙니다. 소수점을 처리하기 위해 컴퓨터는 부동 소수점 표현이라는 형식을 사용합니다. 부동 소수점 표현은 본질적으로 과학적 표기법의 이진 버전입니다. 예를 들어, 물리학을 공부한 경우 익숙할 수 있는 몇 가지 값은 다음과 같습니다:
- 지구의 질량: 5.972 * 10^24 kg
- 태양의 질량: 1.989 * 10^30 kg
- 빛의 속도: 2.998 * 10^8 m/s
- 1광년: 9.460 * 10^15 m
- 양성자의 질량: 1.672 * 10^-27 kg
- 플랑크 길이: 1.616 * 10^-35 m
과학적 표기법이 이러한 값들을 다양한 규모에도 불구하고 합리적인 정확도로 표현할 수 있게 해주는 방식을 주목하세요. 부동 소수점 표기법은 본질적으로 이진 과학적 표기법입니다. 예를 들어, 숫자 9.625를 저장할 때 컴퓨터는 “1.001101 * 10^11”을 저장합니다 (또는 더 정확하게는 01000000 00100011 01000000 00000000 00000000 00000000 00000000 00000000, 이는 고정밀 직렬화된 형태에서 동일한 것입니다). 이 고정밀 형태에서 “유효 숫자” (지수 부분이 아닌 부분)는 52비트입니다. 이는 고정밀 (더 정확하게는 “배ble precision”) 부동 소수점 숫자가 253까지의 정수를 정확하게 저장할 수 있지만 그 이상은 불가능하다는 것을 의미합니다. 비트코인의 250.9 사토시는 지수적으로 이 최대값 바로 아래에 위치합니다.
정수 대신 부동 소수점 값이 중요한 이유는 무엇일까요? 많은 고급 프로그래밍 언어 (예: 자바스크립트)는 저수준의 “부동 소수점” 및 “정수 표현”을 노출하지 않고, 프로그래머에게 “숫자”라는 개념만 제공합니다 – 물론 부동 소수점 형태로 표현됩니다. 만약 사토시가 210백만을 선택했다면, 많은 언어에서 비트코인 프로그래밍은 현재보다 훨씬 더 어려웠을 것입니다.
스테판 토마스는 그의 BitcoinJS 라이브러리에서 이를 활용하지 않았기 때문에, 해당 라이브러리는 거래 출력 값을 저장하기 위해 일반 숫자 대신 전문화된 “큰 숫자” 객체를 사용합니다. 이에 대해 질문을 받았을 때, 토마스는 일반 숫자를 사용하는 것이 가능하다는 것을 깨달았지만, 비트코인JS는 타원 곡선 산술이 2512까지의 숫자를 요구하기 때문에 “큰 숫자” 라이브러리를 포함해야 한다고 답했습니다. 따라서 선택은 임의적이었습니다. 제 자신의 BitcoinJS 포크 (다른 개선 사항도 추가함)는 사토시의 수를 저장하기 위해 일반 숫자를 사용하며, 이는 sx 및 pybitcointools와 같은 외부 거래 출력 데이터 소스와의 호환성을 원하는 데서 비롯된 결정입니다.
올바른 타원 곡선 선택하기
비트코인이 거래를 디지털 서명하고 검증하는 데 사용하는 타원 곡선 암호학은 메시지를 서명하는 단일 표준화된 방법이 아닙니다. 사실, 선택할 수 있는 다양한 “곡선”이 있습니다. 다양한 “곡선”이 무엇인지 이해하기 위해서는 ECC 뒤에 있는 수학이 어떻게 작동하는지에 대한 기본적인 이해가 필요합니다. 일반적으로, 타원 곡선은 두 차원 평면에서 (x,y) 점의 집합으로, y2 = x3 + ax + b라는 방정식이 성립합니다. 여기서 a와 b는 곡선의 매개변수입니다. 다음은 하나의 타원 곡선의 모습입니다:
타원 곡선 암호학은 이러한 곡선에서 “점 추가” 및 “점 두 배”라는 연산에 의존하며, 이러한 연산은 다이어그램으로 가장 잘 설명됩니다:
본질적으로 두 점 P와 Q를 더하려면, 그 사이에 선을 그린 다음, 그 선이 교차하는 곡선의 다른 점을 찾아서, 그 점에서 수직선을 그려서 답을 얻습니다. 그러나 암호학적 목적을 위해 이러한 일반적인 타원 곡선은 약점이 있습니다: 부정확하다는 것입니다. 점 추가를 많이 수행하면 부동 소수점 반올림 오류가 서서히 축적되어 결국 결과가 완전히 무의미한 잡음이 됩니다. 따라서 타원 곡선 암호학은 두 가지 수정이 있는 타원 곡선을 사용합니다. 첫째, 방정식은 이제 y2 = x3 + ax + b + kp로, 여기서 k는 임의의 정수이고 p는 큰 소수입니다 (a와 b와 함께 곡선의 매개변수입니다). 둘째, x와 y는 정수여야 합니다. 결과적으로 생성된 집합은 “곡선”이라고 하기에는 거의 불가능하지만, 놀랍게도 동일한 수학이 여전히 작동하며, 정수로 제한하면 반올림 오류를 피할 수 있습니다.
사용할 수 있는 다양한 곡선 매개변수가 있으며, SEC2 문서에서 표준 매개변수를 제공합니다. 그러나 일반적으로 곡선은 두 가지 범주로 나뉩니다: “의사 난수” 곡선과 코블리츠 곡선. 의사 난수 곡선에서는 매개변수 a와 b가 특정 “시드”에서 지정된 알고리즘 (본질적으로 해시)에 의해 선택됩니다.
표준 256비트 의사 난수 곡선인 secp256r1의 경우, 시드는 c49d360886e704936a6678e1139d26b7819f7e90이며, 다음과 같은 매개변수를 생성합니다:
p = 115792089210356248762697446949407573530086143415290314195533631308867097853951
a = 15792089210356248762697446949407573530086143415290314195533631308867097853948
b = 41058363725152142129326129780047268409114441015993725554835256314039467401291
명백한 질문은 다음과 같습니다: 시드는 어디서 왔나요? 왜 시드를 15와 같은 더 무해해 보이는 숫자로 선택하지 않았나요? 최근 미국 국가안전국이 암호학적 표준을 무너뜨렸다는 사실을 고려할 때, 시드가 NSA만 아는 방식으로 곡선을 약하게 만들기 위해 의도적으로 선택되었을 가능성이 우려됩니다. 다행히도 여유 공간은 무한하지 않습니다. 해시 함수의 특성 때문에, NSA는 하나의 “약한” 곡선을 찾고 시드를 역으로 결정할 수 없었습니다. 오히려 유일한 공격 경로는 서로 다른 시드를 시도하여 약한 곡선을 생성하는 것입니다. NSA가 특정 곡선에만 영향을 미치는 타원 곡선 취약성을 알고 있다면, 의사 난수 매개변수 생성 과정은 그 곡선을 표준화하는 것을 방지할 것입니다. 그러나 만약 그들이 10억 곡선 중 하나에서 약점을 알고 있다면, 그 과정은 보호를 제공하지 않습니다. 우리가 아는 한, c49d360886e704936a6678e1139d26b7819f7e90는 미국 표준 기술 연구소가 시도한 10억 번째 시드일 수 있습니다.
다행히도 비트코인은 의사 난수 곡선을 사용하지 않습니다. 비트코인은 코블리츠 곡선을 사용합니다. 비트코인의 secp256k1에서 매개변수는:
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
a = 0
b = 7
그게 전부입니다. 그리고 p는 생성하기도 꽤 간단합니다. 이는 단지 2256 – 232 – 977입니다 (공정성을 위해, secp256r1의 p와 a도 꽤 간단합니다; 문제가 되는 것은 b입니다). 이러한 매개변수의 단순성은 NSA / NIST가 의도적으로 나쁜 곡선을 생성할 여유 공간을 거의 제공하지 않습니다. 그리고 0, 7 및 977의 특정 값도 보안 및 효율성 제약에 의해 정당화될 수 있으므로, 비트코인의 타원 곡선 매개변수가 악의적인 의도로 선택되었을 가능성은 매우 낮습니다. 효율적인 암호화 그룹의 현재 의장인 댄 브라운이 이에 대해 질문을 받았을 때, 그는 “비트코인이 secp256k1을 사용하고 있다는 것을 몰랐습니다. 사실, 누군가가 secp256k1 대신 secp256r1을 사용하는 것을 보니 놀랍습니다.”라고 답했습니다. 만약 secp256r1이 실제로 손상되었다면, 비트코인이 secp256r1 대신 secp256k1을 사용하는 몇 안 되는 응용 프로그램 중 하나이기 때문에 비트코인은 정말로 총알을 피한 것입니다.