[Mastering Ethereum] 3장 키와 주소

in #kr-dev6 years ago (edited)

modolee_logo
안녕하세요. 개발자 모도리입니다.
요즘 참여하고 있는 스터디에서 Mastering Ethereum 를 교재로 하여 매주 스터디를 진행하고 있습니다. 이번 주에 제가 맡은 부분을 정리해서 올립니다.

이더리움 키와 주소

  • 이더리움의 기반 기술 중 하나는 암호학이다.
  • 암호학(cryptography)는 그리스어로 비밀 글쓰기(secret writing)를 의미하지만, 암호학은 단순한 암호화 이 외의 더 많은 것들을 포함한다. - 디지털 서명(digital signature), 디지털 지문(digital fingerprints)
  • 이더리움 네트워크에 정보가 공개 될 때 암호화는 사용되지 않는다. 모든 정보를 누구나 볼 수 있다. 그래서 상태 업데이트가 올바르게 되었는지는와 합의가 이루어졌는지를 검증할 수 있다.
  • 이더리움에서 자산의 소유권을 제어하기 위한 개인 키와 주소에 사용되는 공개 키 암호화(PKC : public key cryptography)을 알아보자.

소개

  • 이더리움에는 EOA(Externally Owned Accounts), CA(Contract Accounts) 두 가지 종류의 계정이 존재한다. CA는 개인 키를 가지고 있지 않기 때문에, EOA에 대해서만 다루도록 한다.
  • 개인 키는 이더리움에서 사용자 간의 상호 작용에 있어 핵심적인 역할을 한다.
  • 계정 주소는 개인 키로 부터 얻어낼 수 있으며, 1개의 개인 키는 오직 1개의 계정 주소와 매핑된다.
  • 개인 키는 이더리움 시스템 내에서 직접적으로 사용되지 않는다. 즉, 이더리움 시스템에 직접적으로 전송되거나 저장되어 있지 않다.
  • 계정 주소디지털 서명 만이 전송되고 저장된다.
  • 자산의 접근과 제어는 개인 키를 이용해 만들어진 디지털 서명으로 이뤄진다.
  • 만약 누군가가 개인 키 복사본을 가지고 있다면, 동일하게 자산의 접근과 제어가 가능하다. 그러므로 안전한 개인 키 관리가 필요하다.
  • 이더리움과 같이 공개 키 암호화를 사용하는 시스템은 공개 키와 개인 키로 이루어진 키 쌍을 사용한다. 일반적으로 개인 키는 특별한 파일에 담겨 지갑 소프트웨어가 관리하고 있으므로, 사용자가 직접 보는 경우는 드물다.
    • 공개 키 : 은행의 계좌번호와 같아서, 다른 계정과의 식별을 위해서 사용된다.
    • 개인 키 : 은행의 비밀번호와 같아서, 계정을 제어할 수 있다.
  • 이더리움 전송 시 수신자는 이더리움 주소를 나타낸다. 일반적으로 공개 키를 통해 생성 된 주소이지만, 그렇지 않은 경우도 있다. (CA주소를 나타내기도 하며, CA는 개인 키를 가지고 있지 않다.)

공개 키 암호화와 암호화폐

공개 키 암호화의 발견

  • 공개 키 암호화(비대칭 키 암호화)은 현대의 정보 보안에 핵심이다.
  • 1970년대 전까지는 정부가 비밀로 지키고 있던 강력한 암호학 지식이 Martin Hellman, Whitfield Diffie, Ralph Merkle 세 사람에 의해 공개적으로 알려지게 되었다.

공개 키 암호화

  • 공개 키 암호화은 정보 보안을 위해 유일한 키를 사용한다.
    • 이 키는 특별한 속성을 갖는 수학 함수를 기반으로 한다.
    • 그냥 계산하시는 쉽지만, 역산은 힘들다.
    • 이 함수를 이용하면 수학의 법칙으로 안전이 보장되는 디지털 비밀과 위조할 수 없는 디지털 서명을 만들 수 있다.
  • 예를 들어 두 소수를 곱하는 것은 매우 쉬운 일이지만, 어떤 큰 수가 주어지고 곱해서 이 수를 만들 수 있는 두 소수를 구하는 것은 매우 어려운 일이다.
    • 8018009가 주어지고 곱해서 이 수를 만들 수 있는 두 소수를 찾는 것은 어렵다.
  • 이런 함수 중 몇 몇은 비밀 정보 일부가 주어지면 쉽게 풀 수 있다.
    • 앞의 수에서 한 소수가 2003이라는 것을 알려준다면, 8018009 ÷ 2003 = 4003 를 계산하여 다른 한 소수도 쉽게 구할 수 있다.
    • 이렇게 역산을 할 수 있는 함수의 비밀 정보가 없는 한 역산이 매우 힘든 함수를 trapdoor function이라고 부른다.

타원 곡선

  • 암호학에서 유용하게 사용되는 고급 수학 함수는 타원 곡선이다.
  • 타원 곡선의 산술, 곱셈 연산은 매우 단순하지만, 나눗셈은 거의 불가능하다.
  • 이것을 이산 로그 문제라고 부르며, 현재는 알려진 trapdoor function이 없다.
  • 타원 곡선 암호화는 현재 컴퓨터 시스템에 널리 사용되며 이더리움의 개인 키와 디지털 서명의 기초가 된다.

이더리움에서 공개키 암호화의 사용

  • 이더리움에서 개인 키 - 공개 키 쌍을 만들기 위해서 공개 키 암호화를 사용한다.
  • "쌍" 이라고 불리우는 이유는 공개 키가 개인 키로 부터 생성되기 때문이다.
  • 이것은 이더리움 계정과 계정의 자산을 제어할 수 있으며, 스마트 컨트랙트 이용 시 인증이 가능하다.
  • 디지털 서명은 어떤 메세지로도 만들 수 있는데, 이더리움에서는 메세지라는 정보와 개인 키를 이용해서 디지털 서명을 만든다.
  • 자산을 옮기거나 스마트 컨트랙트 실행을 위해 이더리움 네트워크에 트랜잭션을 보내기 위해서는 개인 키와 대응되는 디지털 서명이 있어야 한다.
  • 타원 곡선 알고리즘을 통하면 디지털 서명과 계정 주소, 트랜잭션 상세 내역을 맞춰 봄으로써 누구나 트랜잭션 검증이 가능하다.
  • 검증 과정에는 개인 키가 포함되지 않는다. 하지만 계정 주소를 생성한 공개 키와 쌍을 이루는 개인 키를 가진 사람만이 해당 메세지를 만들 수 있다는 것을 확실할 수 있습니다.
  • 이것이 공개 키 암호화의 "magic" 입니다.

TIP

  • 대부분의 지갑 구현체들은 개인 키, 공개 키 쌍을 모두 키 페어 형태로 저장한다. 하지만 개인 키를 통해서 공개 키를 생성할 수 있으므로, 개인 키가 저장되어 있어도 상관 없다.
  • 이더리움 프로토콜에 암호화 부분은 없다. 즉, 이더리움의 모든 메세지는 누구나 읽을 수 있다. 개인 키는 오직 트랜잭션 인증을 위한 디지털 서명을 만드는 데에 만 사용 된다.

개인 키(Private Keys)

  • 개인 키는 간단히 생각하면 랜덤하게 선택 된 숫자이다.
  • 개인 키를 소유하고 제어하는 것이 해당 키와 연결 된 이더리움 주소의 자산을 제어하는 데 핵심이다.
  • 그리고 또한 해당 이더리움 주소의 접근을 승인하는 스마트 컨트랙트에 접근할 수 있다.
  • 개인 키는 자산의 사용하는데 필요한 디지털 서명을 만드는데 사용된다.
  • 개인 키는 반드시 비밀로 잘 지켜야 한다. 개인 키가 제 3자에게 노출된다면, 그 사람 역시 개인 키 소유자와 동일하게 이더리움 계정의 자산과 스마트 컨트랙트들을 제어할 수 있게 된다.
  • 개인 키는 반드시 백업해 두어야 하고, 갑작스런 손실(분실)로 부터 보호되어야 한다. 개인 키를 잃게 된다면, 복구 할 수 없으며 자산 역시 영원히 잃게 된다.

랜덤 한 수로 부터 개인 키 생성하기

랜덤 소스

  • 개인 키를 만들기 위한 첫 단계는 안전한 엔트로피 소스 또는 랜덤성을 찾는 것이다.
  • 개인 키를 만들 때에는 반드시 1 ~ 2^{256} 사이의 숫자를 선택해야 한다.
  • 그 숫자를 고르는 방법이 예측 가능하거나 결정적(deterministic)이지 않다면 어떤 방법이든 상관없다.
  • 이더리움은 랜덤 한 256 bits를 만들기 위해 기본 운영체제의 난수 생성기(RNG : Random Number Generator)를 사용한다.
  • 보통 OS의 난수 생성기는 사람의 랜덤 소스에 의해 초기화 됩니다. 몇 초간 마우스를 마구잡이로 움직이거나 키보드를 마구잡이로 누르라고 요구하는게 이러한 이유입니다. 비트코인 주소 생성기
  • 다른 방법은 컴퓨터의 마이크 채널을 통해 들어 오는 우주 방사선 잡음을 이용하는 방법이다.

개인 키 범위

  • 조금 더 정밀하게 보자면, 개인 키는 0이 아닌 2^{256} (78자리 숫자로, 대략 1.158 * 10^{77} 정도) 이하의 숫자이다.
  • 정확한 숫자는 2^{256}와 앞 38 자리를 공유하며, 이더리움에서 사용하는 타원 곡선의 규칙에 의해 정의된다.
  • 개인 키 생성을 위해서는 랜덤 한 256 bits를 선택하고 유효한 범위인지 확인한다.
  • 프로그래밍 측면에서는 보통 매우 긴 랜덤 한 문자열(암호학적으로 안전한 랜덤성 소스로 부터 수집 된)을 Keccak-256 또는 SHA256(두 방법 모두 간편히 256-bits의 숫자를 만들어 냄 )과 같은 256-bits 해시 알고리즘에 넣어서 랜덤한 256-bits를 만들어 냅니다.
  • 만약 결과가 유효한 범위 안에 있다면 적합한 개인 키를 만들어 낸 것이고, 그렇지 않으면 다시 시도하면 된다.

개인 키 생성은 오프라인 작업

  • 개인 키 생성 과정은 이더리움 네트워크 또는 다른 어떤 외부와의 커뮤니케이션이 필요 하지 않아 오프라인으로 진행할 수 있다. (오프라인으로 하는 것을 추천)
  • 다른 누군가가 선택할 수 없는 숫자를 선택하려면 진~~짜 랜덤해야 한다.
  • 만약에 자신이 직접 숫자를 선택한다면, 다른 누군가도 시도해 볼 확률이 굉장히 높다. (그리고 이더가 털린다.)
  • 좋지 않은 난수 생성기(대부분의 프로그래밍 언어가 제공하는 pseudo-random rand() 함수와 같은 것)을 사용하는 것은 좋지 않은데, 그 이유는 제대로 된 난수 생성기에 비해 훨씬 더 분명하고 훨씬 더 복제하기 쉽다.
  • 온라인 계정의 비밀번호 처럼, 추측 불가능 해야 한다.
  • 다행스럽게도 개인 키를 기억할 필요가 없으므로 개인 키를 선택하는 최선의 방법(진정한 무작위성)을 취할 수 있습니다.

TIP
이더리움 개인 키 영역의 크기는 셀 수 없게 큰 숫자이다. 대략 10진수로 10^{77}, 77자리의 숫자이다. 비교를 해보자면, 볼 수 있는 우주가 10^{80}개의 원자를 포함하고 있다고 한다. 즉, 우주의 거의 모든 원자가 이더리움 계정을 가질 수 있을 만큼의 개인 키가 있는 것이다. 만약 랜덤 한 개인 키를 뽑았다면, 누구도 그 수를 추측할 수 있는 방법은 없다.

Warning
난수 생성을 위해 직접 코드를 작성하거나 프로그래밍 언어에서 제공하는 단순한 난수 생성기를 사용하지 마라. 필수적으로 충분한 엔트로피를 시드로 하는 암호학적으로 안전한 pseudo-random 숫자 생성기(CSPRNG - Cryptographically Secure Pseudo-Random Number Generator)를 사용하라. 난수 생성기의 문서를 공부하고 암호학적으로 안전한지 확실히 확인하라. CSPRNG 라이브러리의 올바른 구현은 키 보안에 굉장히 중요하다.

  • 아래는 랜덤하게 생성된 개인 키를 16진수 형태로 나타낸 것이다. (256 bits 가 64자리의 16진수로 표현되어 있다.):
    f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

공개 키(Public Keys)

  • 이더리움의 공개 키는 타원 곡선 상의 한 점이다. 즉, 타원 곡선 방정식을 만족하는 x, y 좌표 쌍이다.
  • 단순히 말해서 이더리움 공개 키는 두 숫자이며 그것을 붙여서 사용합니다.
  • 이 두 숫자는 개인 키를 가지고 단 방향 계산을 해서 얻어진다.
  • 개인 키를 가지고 있으며 공개 키를 계산하는 것은 매우 쉽지만, 공개 키를 가지고 개인 키를 구하는 것은 불가능하다.

Warning
앞으로 수식들이 나올텐데, 당황하지 마라. 따라 오기 힘들다면, 다음 몇 섹션은 건너 뛸 수 있다. 당신 대신 수학을 해 줄 수 있는 툴과 라이브러리는 많다.

  • 공개 키는 개인 키를 이용한 타원 곡선 곱셈 계산을 통해 얻어지지만, 실질적으로 역산은 불가능하다.

  • K = k * G

    • k : 개인 키
    • G : 상수 점 (x, y). Generator Point
    • K : 공개 키
    • * : 일반 곱셈이 아닌 타원 곡선 상에서 일어나는 특별한 곱셈 연산자
  • K를 안다고 했을 때 가능한 모든 k를 brute-force로 시도한다고 했을 때 걸리는 시간은 우주가 허용하는 시간 보다 오래 걸릴 것이다.

  • 단순히 말하면 타원 곡선 상의 산술 연산은 일반적인 정수 산술 연산과 다르다.

  • 한 점(G)에 정수(k)배를 해서 다른 한 점(K)를 얻을 수 있다. 하지만 나눗셈과 같은 연산은 없다. 그래서 단순히 공개 키 K를 점 G로 나눈다고 해서 개인 키 k를 얻을 수 없다.

  • 이것이 공개 키 암호화와 암호화폐가 설명하고 있는 단방향 수학 함수이다.

TIP
타원 곡선 곱셈은 암호학자들이 "단 방향" 함수라고 말하는 것 중 하나이다. 정방향(곱셈)을 쉽게 할 수 있지만, 역방향(나눗셈)은 불가능하다. 개인 키 소유자는 쉽게 공개 키를 만들고 누구에게나 공유할 수 있지만, 누구도 공개 키를 가지고 개인 키를 계산할 수는 없다. 이 수학적 트릭이 위조할 수 없고 안전한 디지털 서명 기반이 되고, 디지털 서명은 이더리움 자산의 소유권을 증명하고 컨트랙트를 제어할 수 있다.

  • 개인 키로 부터 어떻게 공개 키를 만들어 내는 지 시연해 보기 전에 타원 곡선 암호화를 조금 더 자세히 살펴 보자.

타원 곡선 암호화 설명

  • 타원 곡선 암호화는 비대칭 (또는 공개 키 ) 암호화 종류로, 타원 곡선의 점에 덧셈과 곱셈으로 표현되는 이산 로그 문제를 기반으로 한다.
  • 아래 그림은 타원 곡선의 한 예로 이더리움에서 사용하는 타원 곡선과 비슷하다.

TIP
이더리움은 비트코인과 동일하게 secp256k1이라는 타원 곡선을 사용한다. 이 덕분에 많은 비트코인 라이브러리를 재사용 할 수 있다.

타원곡선_예

  • 이더리움은 NIST(US National Institute of Standards and Technology)에 의해 확립 된 secp256k1이라는 표준으로 정의 된 타원 곡선과 수학적 상수의 집합을 사용한다.
  • secp256k1 곡선은 타원 곡선을 만드는 아래 함수에 의해 정의된다.
  • y^2=(x^3+7) over (𝔽_p)
    or
  • y^2 mod p = (x^3+7) mod p
  • mod p 는 이 곡선이 소수 차수 p의 유한 체(finite field) 위에 있다는 것을 나타내며 𝔽_p 라고 쓴다.
  • p는 매우 큰 소수이다. p = 2^{256} – 2^{32} – 2^{9} – 2^{8} – 2^{7} – 2^{6} – 2^{4} – 1
  • 이 곡선은 실수가 아니라 소수 차수의 유한 체 상에 정의되기 때문에 시각화 하기 어려운 2차원의 흩어진 점들의 형태로 보여진다.
  • 하지만 수학적으로는 실수에서와 동일하다.
  • F(p), p=17 타원 곡선을 시각화 하면 다음과 같다.
    샘플_타원곡선

secp256k1
secp256k1 - bitcoin wiki
secp256k1 실습
y^2=(x^3+ax+b) over (𝔽_p)

  • Curve
    • a = 0
    • b = 7
  • Field
    • p = 17

K = k * G

  • n : k (개인 키)
  • P : G (Generator Point)
  • Q = n * P : k * G (공개 키)
  • 아래 좌표 Q는 secp256k1 곡선 상의 한 점이다.
  • Q = (49790390825249384486033144355916864607616083520101638681403973749255924539515, 59574132161899900045862086493921015780032175291755807399284007721050341297360)
  • 파이썬을 이용해서 Q가 secp256k1 곡선 상의 점이라는 것을 검증할 수 있다.
  • y^2 mod p = (x^3+7) mod p 수식을 정리하면, (x^3+7 - y^2) mod p = 0 이 된다.
  • x, y에 Q의 좌표를 넣어서 계산해 보자.
  • 파이썬 연습장
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
x = 49790390825249384486033144355916864607616083520101638681403973749255924539515
y = 59574132161899900045862086493921015780032175291755807399284007721050341297360
result = (x ** 3 + 7 - y**2) % p
print(result)

실행 결과
0

타원 곡선 산술 연산

  • 많은 타원 곡선 수학은 우리가 학교에서 배웠던 정수 산술 연산과 상당히 비슷하게 보이고 동작한다.
  • 덧셈 연산자는 수직선 상에서 움직이는 대신에 곡선의 다른 점으로 움직인다.
  • 덧셈 연산자가 정의 되었다면, 곱셈 연산자도 정의할 수 있다. (곱셈은 덧셈을 반복하면 된다.)

타원곡선_곱셈

공개 키 생성하기

  • 랜덤하게 생성 된 수 k (개인 키)를 미리 정의 된 곡선 상의 점 G(Generator Point)에 곱하면 곡선 상의 또 다른 점 K(공개 키)를 얻을 수 있습니다.
  • secp256k1 표준의 G가 정의되어 있으며, 항상 같은 G를 사용한다.

K = k * G

  • k : 개인 키
  • G : Generator Point (생성점?)
  • K : 공개 키
  • 모든 이더리움 사용자들이 항상 같은 G 를 사용하기 때문에, G에 개인 키 k를 곱하면 항상 같은 공개 키 K가 나온다.
  • k(개인 키)와 K(공개 키)는 고정 된 관계를 가지고 있지만, k에서 K를 구하는 단 방향으로의 계산만 가능하다.
  • 그래서 이더리움 주소(공개 키로 부터 생성 된)를 개인 키 노출 없이 누구나와 공유할 수 있다.

예제 용 개인 키
f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

  • 위의 개인 키를 이용해서 공개 키를 만들어 보자.
  • K = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 * G
  • K 는 2차원 상의 한 점이다. K = (x, y)

개인 키로 얻은 2차원 점 K
x = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b
y = 83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

  • 이더리움의 공개 키는 130자의 16진수(65 bytes) 표현 된다.
  • Standards for Efficient Cryptography (SEC1)에서는 타원 곡선 상의 점을 식별하는데 사용할 수 있는 4가지 prefix를 정의했다.
| Prefix | Meaning                      | Length (bytes counting prefix)
| 0x00   | Point at Infinity            | 1
| 0x04   | Uncompressed Point           | 65
| 0x02   | Compressed Point with even Y | 33
| 0x03   | Compressed Point with odd Y  | 33
  • 이더리움은 압축 안된 공개 키만 사용하여, 04 prefix만 사용한다.
    04 + X-coordinate (32 bytes/64 hex) + Y-coordinate (32 bytes/64 hex)
  • 예제 용 개인 키로 만든 공개 키는 다음과 같다.
    046e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

타원 곡선 라이브러리

  • 암호화폐 관련 된 프로젝트에서 사용되는 secp256k1 타원 곡선의 구현체가 몇 가지 있다.

OpenSSL

  • OpenSSL 라이브러리는 secp256k1의 모든 구현을 포함하여, 포괄적인 암호학적 기본 요소(primitives)를 제공한다.
  • 예를 들어 공개 키를 만들어 내기 위해 EC_POINT_mul()를 사용할 수 있다.
  • https://www.openssl.org/

libsecp256k1

  • 비트코인 코어의 libsecp256k1은 secp256k1과 다른 암호학적 기본 요소의 C언어 구현체이다.
  • libsecp256k1의 타원 곡선 암호화는 비트코인 코어의 OpenSSL을 대체하기 위해서 스크래치부터 구현되었다.
  • 성능과 보안 모두 뛰어나다.
  • https://github.com/bitcoin-core/secp256k1

암호화 해시 함수

암호화 해시 함수의 5가지 주요 속성

  • Determinism

    • 동일한 입력 메세지는 항상 같은 해시 출력을 만든다.
  • Verifiability

    • 메세지의 해시 계산이 효율적이다. (선형 복잡도)
  • Uncorrelated

    • 원본 메세지와 출력 해시를 연관 지을 수 없도록 입력 메세지의 매우 작은 부분이 변경되어도 해시 출력의 많은 부분이 변경되어야 한다.
  • Irreversibility

    • 해시 출력을 통해서 입력 메세지를 계산하는 것은 불가능합니다. brute-force로 가능한 모든 메세지를 찾는 것과 같습니다.
  • Collision Protection

    • 두 개의 다른 입력 메세지가 동일한 해시 출력을 만들 수 없어야 한다.
    • 해시 충돌에 대한 저항은 이더리움에서 디지털 서명 위조를 피하기 위해 중요합니다.
  • 이러한 속성들 덕분에 암호화 해시 함수가 다양한 보안 프로그램에서 유용하게 사용된다.

    • Data fingerprinting
    • Message integrity (error detection)
    • Proof-of-Work
    • Authentication (password hashing and key stretching)
    • Pseudo-random number generators
    • Message commitment (commit–reveal mechanisms)
    • Unique identifiers

이더리움의 암호화 해시 함수 - Keccak-256

  • Keccak-256은 2007년에 National Institute of Science and Technology(NIST)에서 주최한 SHA-3 암호화 해시 함수 경연에 후보로 설계되었다.
  • Keccak이 우승하였고, 2015년에 Federal Information Processing Standard (FIPS) 202로 표준화 되었다.
  • 이더리움 개발 중에는 아직 NIST 표준이 확정되지 않았고, NIST가 효율성을 향상시키기 위해서 코드를 수정했다.
  • 수정한 코드의 결함이 발생해서 표준화가 늦어졌다.
  • 이더리움 재단에서는 NIST가 수정한 SHA-3 표준 보다는 원본 Keccak 알고리즘을 구현하기로 결정했다.
  • 이더리움에서 사용하는 Keccak-256과 최종 확정 된 표준 FIP-202 SHA-3의 차이 때문에 혼란을 일으킨다. ERC-59에서 모든 코드와 OPCODE에 있는 sha3 다시 네이밍하기 위해 나눈 흔적을 찾아 볼 수 있다.

사용하고 있는 해시 함수가 어떤 것일까?

  • 이더리움 코드에 SHA-3, Keccak-256을 혼용해서 사용하고 있긴 하지만, Keccak-256을 사용한다.
  • 실제로 공백 해시를 통해서 확인할 수 있습니다.
Keccak256("") =
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

SHA3("") =
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

이더리움 주소

  • 이더리움 주소는 공개 키 또는 컨트랙트에 Keccak-256 해시 함수를 적용하여 만들어 낸 유일한 식별자이다.
  • 이전 예제에서 사용했던 개인 키, 공개 키를 다시 가져와보자.
  • 개인 키 k :
    k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
  • 공개 키 K :
    K = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

Warning
주소를 계산할 때 사용하는 공개 키 형식은 prefix 04를 포함하지 않는다.

  • Keccak-256을 이용한 공개 키 K의 해시 :
    Keccak256(K) = 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9

Question

  • 실제로 공개 키 K를 Keccak-256 해시 함수에 넣어서 돌려보면 다른 값이 나오는데 왜 그런가??? 더 찾아보기
    6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0 이 형태 그대로 Keccak256에 입력으로 집어 넣는게 아닌가???
    53a07bd0be78dd08f3505b0f4daafc5d8dc848ca07a8b87f24129615789912ff
  • https://keccak-256.cloxy.net/
  • https://emn178.github.io/online-tools/keccak_256.html
  • 아래 소개 되는 helpeth를 이용하면 위와 같은 결과가 나오는데 그냥 직접 Keccak256을 돌리면 아래 값이 나온다.
    ./helpeth keyDetails -p 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
  • 그런데 여기서 제공하는 keccak256을 돌리면 또 정상적으로 나오는데, 16진수 인코딩의 문제가 아닌가 생각된다.
  • 입력 데이터에 prefix "0x"를 안 붙였을 때
    ./helpeth keccak256 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0 -> 53a07bd0be78dd08f3505b0f4daafc5d8dc848ca07a8b87f24129615789912ff
  • 입력 데이터에 prefix "0x"를 붙였을 때
    ./helpeth keccak256 0x6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0 -> 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9
  • 해시 결과 중에서 마지막 20 bytes (least significant bytes)가 바로 이더리움 주소이다.
    001d3f1ef827552ae1114027bd3ecf1f086ba0f9

  • 대부분의 이더리움 주소는 16진수로 인코딩 되었다고 표시하는 prefix "0x"를 붙이고 있다.
    0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

이더리움 주소 형식

  • 이더리움 주소는 공개 키의 Keccak-256 해시 값 중 마지막 20 bytes를 16진수로 표현한 것이다.
  • 주소 자체에 체크섬을 포함하고 있는 비트코인 주소와 다르게 이더리움 주소는 별도의 체크섬이 없는 raw 16진수이다.
  • 상위 레이어에서 체크섬을 포함하려고 하는데, ENS 같은 상위 레이어의 개발이 초기에 기대했던 것 보다 매~~우 느려서 대안을 ICAP 같은 인코딩이 지갑 개발자들이 사용하게 되었다.

Inter Exchange Client Address Protocol (ICAP)

  • International Bank Account Number (IBAN) 와 부분적으로 호환되는 형식
  • 표현하는 방식은 Direct, Basic, Indirect 3가지 있다.
  • 현재 많이 사용되고 있지 않기 때문에, 자세한 내용은 다루지 않겠다.
  • 자세한 내용은 공식 위키를 참고 바람

Hex encoding with checksum in capitalization (EIP-55)

  • ICAP와 ENS의 늦은 개발 때문에, EIP-55로 다른 표준이 제안되었다.

  • EIP-55는 16진수 주소 중 일부를 대문자화하여 구버전과 호환되는 이더리움 주소 체크섬을 제공한다.

  • 이더리움 주소는 대소문자 구분없이 사용할 수 있다는 점을 이용한 아이디어이다.

  • 일반 이더리움 주소
    0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

  • EIP-55 적용한 주소
    0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

  • 두 주소의 차이점은 중간 중간 대문자로 변경된 영문자가 보인다는 것이다.

  • EIP-55 적용하는 방법

  • prefix "0x"를 제외한 소문자로 된 주소의 해시 값을 구한다.

Keccak256("001d3f1ef827552ae1114027bd3ecf1f086ba0f9")
23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1
  • 주소와 주소 해시 값의 같은 자리 문자끼리 비교한다.
Address: 001d3f1ef827552ae1114027bd3ecf1f086ba0f9
Hash   : 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9...
  • 만약 해시 값이 0x8과 같거나 큰 경우 대문자로 바꿔준다.
Address: 001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
Hash   : 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9...


  • 에러 검출하기
  • 주소 0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9 의 마지막 두번째 문자 FE로 잘못 입력 한 경우
  • 주소는 0x001d3F1ef827552Ae1114027BD3ECF1f086bA0E9가 되고, 해시 값은 다음과 같다.
Keccak256("001d3f1ef827552ae1114027bd3ecf1f086ba0e9")
5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927
  • EIP-55 조건에 맞게 대문자화 되었는지 확인해 본다.
001d3F1ef827552Ae1114027BD3ECF1f086bA0E9
5429b5d9460122fb4b11af9cb88b7bb76d892886...
  • 뒤에서 4번째 문자 A와 매칭되는 해시 값은 2인데 대문자화 되어 있으니, 뭔가 잘못 된 것이다! (다른 문자들도 다른 것이 더 있다.)

Key, Transaction 관리 툴 helpeth

  • https://github.com/ethereumjs/helpeth
  • 다양한 기능을 제공하지만 여기에선 개인 키를 넣어서 공개 키, 주소, ICAP주소, EIP-55 체크섬 주소 정보를 얻을 수 있는 명령을 소개한다.
  • 설치를 위해서는 npm이 필요하다.
  • 설치하기
    git clone https://github.com/ethereumjs/helpeth.git
    cd helpeth
  • 실행하기
    npm install
    helpeth keyDetails -p 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f
  • 실행 결과
    Address: 0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
    Address (checksum): 0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
    ICAP: XE60 HAMI CDXS V5QX VJA7 TJW4 7Q9C HWKJ D
    Public key: 0x6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

결론

  • 이더리움의 공개 키, 개인 키 사용을 중심으로 공개 키 암호화에 대해서 알아보고, 이더리움 주소 생성과 검증에 사용되는 해시 함수와 같은 암호학적 도구들을 사용해 봤다.
  • 그리고 디지털 서명과 어떻게 개인 키를 드러내지 않고 개인 키의 소유권을 주장할 수 있는지도 살펴봤다.
  • Wallets 챕터에서는 이런 것과 더불어 지갑이 어떻게 키들을 관리하는지 살펴보겠다.

참고 자료

Sort:  

오! 대단하십니다!

감사합니다! ^^

저보다 정리를 더 잘해주셨네요.ㅎㅎ

먼저 정리해 주신 덕분에 도움 많이 됐습니다! ^^

  • 개인 키 : 256 bits (32 bytes)
  • 공개 키 : 520 bits (65 bytes) -> 실제로 해시에는 64bytes만 사용
  • 주소 : 160 bits (20 bytes)

주소의 표현할 수 있는 범위가 개인 키, 공개 키 보다 좁으니 서로 다른 개인 키에서 동일한 주소를 생성할 수도 있지 않느냐 라는 질문을 받았습니다.

그래서 구글링을 해봤는데, 가능성은 있지만 그 가능성이 매우 희박하다라고 답변이 달려 있습니다. 물론 이 글은 비트코인 관련 질문이긴 하지만 이더리움도 동일하게 적용됩니다.

https://bitcointalk.org/index.php?topic=566319.msg6208311#msg6208311

"하루 동안 상어한테 물리고, 버스에 치이고, 총 맞고, 번개를 맞은 다음에 복권에 당첨 될 정도의 확률이다" 라고 하네요 ㅋㅋㅋ