안녕하세요 스크립토 6기 이희제입니다.
오늘은 마스터링 이더리움 책을 기반으로 챕터5의 내용을 살펴보겠습니다.
1~4 챕터의 글을 추후 올릴 예정입니다.😊
이번 챕터에서 다룰 주제는 바로 지갑입니다. 지갑은 사용자의 키를 보관하고 관리하기 위해 사용되는 시스템을 의미하며, 모든 지갑은 키 관리 구성요소를 가지고 있습니다.
✅ 이더리움에서 지갑은 단지 키만을 보유합니다.
사용자는 지갑에 있는 키로 트랜잭션을 서명함으로써 이더가 지신의 소유임을 증명하고 토큰을 제어합니다.
따라서 이더리움의 지갑은 **키체인(Keychain)**이라고 할 수 있습니다.
✅ 지갑의 형태는 두 가지가 있는데 지갑이 포함하는 키가 서로 관련이 있느냐 없느냐에 따라서 비결정적 지갑과 결정적 지갑으로 구분됩니다.
각각에 대해서 살펴보겠습니다.🧐
➡️ 각기 서로 다은 무작위 수로부터 각각의 키를 무작위적으로 추출하는 방식입니다.
자금을 받을 때마다 새로운 개인키가 필요한 새로운 주소를 사용합니다.
이 말은 때마다 모두 새로운 주소를 위한 새로운 지갑 파일을 만들어야 한다는 의미입니다.
하지만 많은 이더리움 클라이언트는 보안 강화를 위해 암호문으로 암호화된 단일 개인키가 들어있는, JSON 인코딩 파일인 **키저장소(keystore)**파일을 사용하며 그 내용은 아래와 같습니다.
// keyObject:
{
address: "008aeeda4d805471df9b2a5b0f38a0c3bcba786b",
Crypto: {
cipher: "aes-128-ctr",
ciphertext: "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46",
cipherparams: {
iv: "6087dab2f9fdbbfaddc31a909735c1e6"
},
mac: "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2",
kdf: "pbkdf2",
kdfparams: {
c: 262144,
dklen: 32,
prf: "hmac-sha256",
salt: "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"
}
},
id: "e13b209c-3b2f-4327-bab0-3bef2e51630d",
version: 3
}
//https://github.com/ethereumjs/keythereum
키 저장소는 Brute force, Dictionary, Rainbow table 공격을 대비해 암호 확장 알고리즘으로 알려진 **키 파생 함수(key derivation function, KDF)**를 사용합니다.
➡️ 모든 키가 **시드(seed)**라고 하는 단일 마스터 키로부터 파생되는 방식입니다.
결정적 지갑을 좀 더 안전하게 만들기 위해서 시드는 단어 목록으로 인코딩되어 지갑을 재생성할 수 있게 합니다.
✔ 이를 **니모닉 코드 단어(mnemonic code words)**라고 합니다.
결정적 지갑에서 시드는 모든 파생된 키를 복구할 수 있습니다. 그렇기 때문에 시드의 보안이 가장 중요합니다.
➡️ 현재 가장 개선된 결정적 지갑은 비트코인의 BIP-32으로 정의된 HD 지갑입니다.
HD 지갑은 아래 사진과 같이 트리 구조로 파생된 키들을 가지고 있습니다.
✅ 니모닉 코드 단어는 결정적 지갑을 파생하기 위해 시드로 사용되는 난수를 인코딩하는 단어 시퀀스입니다.
단어 시퀀스는 시드를 다시 만들어내고, 이 시드로부터 지갑과 모든 파생된 키들을 재생성할 수 있습니다.
니모닉 코드는 BIP-39에 정의되어 있습니다.
니모닉 단어는 BIP-38에서 정의한 표준화된 절차에 따라 지갑에서 자동으로 생성됩니다.
과정은 다음과 같습니다. (사진도 참고하시면 이해가 더 잘될 겁니다)
- 128 ~ 256 bit의 무작위 암호화 시퀀스 S 생성
[128비트 엔트로피/12단어 예제]
➡️ 니모믹 단어는 128~256bit 길이의 엔트로피를 표현하고 이 엔트로피는 키 스트레칭 함수 PBKDF2를 사용하여 더 긴(512bit) 시드를 파생하는 데 사용됩니다.
키 스트레칭 함수에는 니모닉과 **솔트(salt)**라는 두 가지 파라미터가 있습니다.
- PBKDF2 키 스트레칭 함수의 첫 번째 인자는 6단계에서 생성 된 니모닉 입니다.
➡️ BIP-39 표준은 시드의 파생에 선택적 암호문을 사용할 수 있습니다.
암호문을 사용하지 않으면 니모닉은 상수 문자열 "mnemonic"과 함께 솔트를 구성하여 연장됩니다.
✔ 선택적 암호문은 다음고 같은 두 가지 중요한 특징을 지닙니다.
- 니모닉 자체만으로는 의미가 없도록 만들어, 니모닉 백업이 도난으로부터 보호시킵니다.
HD 지갑은 128, 256 또는 512비트의 임의의 숫자인 단일 **루트 시드(Root Seed)**를 만듭니다. (니모닉이 생성)
HD 지갑의 모든 키는 루트 시드에서 파생되었고, 모든 호환 HD 지갑에서 그 시드로부터 전체 HD 지갑을 생성할 수 있습니다.
✅ 키는 확장될 수 있습니다. 키를 확장하는 것은 키 자체를 가져와서 특수 체인(chain code)를 추가하는 것입니다.
xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNsmsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73
xpub661MyMwAqRbcEnKbXcCqD2GT1di5zQxVqoHPAgHNe8dv5JP8gWmDproS6kFHJnLZd23tWevhdn4urGJ6b264DfTGKr8zjmYDjyDTi9U7iyT
HD 지갑의 매우 유용한 특징은 개인키가 없는 부모 공개키에서 자식 공개키를 파생할 수 있다는 점입니다.
자식 공개키를 파생하는 방법은 2가지입니다.
✅ 만약 자식 확장 개인키가 유출되는 경우, 자식 확장 개인키가 포함하고 있는 키와 체인코드를 사용하면 다른 자식의 개인키 전부를 알아낼수 있습니다.
-> 이러한 문제에 대응하기 위해 HD 지갑은 **강화파생(hardened derivation)**이라고 하는 대체 가능 파생 함수를 사용하여 부모 공개키와 자식 체인코드간의 관계를 끊어 부모/자식 시퀀스에 방화벽을 생성하여 개인키 유출에 방지합니다.
주어진 부모 키로 부터 하나 이상의 자식 키를 파생할 수 있습니다. 이를 관리하기 위해 인덱스 숫자가 사용됩니다.
BIP-32 부모-자식 파생 함수에서 사용되는 인덱스 숫자는 32비트 정수입니다.
HD 지갑의 키는 경로(path) 규칙을 사용하여 식별하며, 트리의 각 레벨은 슬래시(/) 문자로 구분합니다.
마스터 개인키에서 생성된 공개키는 M으로 시작하며, 마스터 개인키의 첫 번째 자식 개인키는 m/0 공개키는 M/0입니다.
✅ BIP-44는 목적 번호를 44로 설정하여 복수화폐 복수계정 구조를 제안합니다.
BIP-44를 따르는 모든 HD지갑 구조는 단지 하나의 트리 분기(m/44’/*)만을 사용한다는 사실에 의해 식별 됩니다.
➡️ BIP-44 는 미리 정의된 5개의 트리 레벨로 구성됩니다.
m / purpose' / coin_type' / account' / change / address_index
purpose' : 44' 로 설정되며 BIP-44 규격임을 의미
coin_type' : 가상화폐 유형을 의미, 이더리움은 60' 을 사용
account : 지갑을 하위 계좌로 세분화 할때 사용
change : 이더리움에서는 사용되지 않으며 비트코인에서는 수신주소와 잔액 주소를 구분하는데 사용
address_index : 주소 번호를 의미
이번 시간에는 이더리움에서의 지갑에 대해서 알아보았습니다.
다음 시간에는 트랜잭션에 대해서 알아보겠습니다.