Skip to content

MasteringEthereum Wallet

Seong-il Lee edited this page Oct 24, 2018 · 1 revision

지갑(Wallet)

  • 이더리움에서 "지갑"이라는 단어는 조금씩 다르게 사용된다.
  • 상위 계층에서 봤을 때 이더리움에 대한 기본 사용자 인터페이스 역할을 하는 응용 소프트웨어이다.
  • 지갑은 사용자 자산의 제어권의 통제, 키와 주소 관리, 자산 추적 그리고 트랜잭션의 생성과 서명을 한다.
  • 몇 몇 이더리움 지갑은 컨트랙트(예 : ERC20 토큰)와 상호작용을 할 수 있다.
  • 더 좁게 프로그래머의 관점에서 봤을 때 지갑은 사용자의 키를 저장하고 관리하는데 사용되는 시스템을 의미한다.
  • 모든 지갑은 키 관리 컴포넌트를 가지고 있으며, 몇 몇 지갑들은 그게 전부인 경우도 있다.
  • 이더리움 기반의 DApp과의 인터페이스로 사용되는 브라우저의 일부로 지갑이 사용되기도 한다.
  • 지갑이라는 단어에 대한 명확한 정의는 없다.
  • 여기에서는 개인 키 들의 보관함 그리고 이 키 들을 관리하는 시스템이라고 정의하고 진행하겠다.

지갑 기술 오버뷰

지갑 설계 시 고려사항

  • 지갑 설계 시 고려해야 될 중요한 점 중 하나는 편의성과 프라이버시의 균형이다.
  • 가장 편리한 이더리움 지갑은 하나의 개인 키와 주소를 가지고 매번 재사용하는 것이다. 하지만 이것은 누구나 쉽게 당신의 모든 트랜잭션을 추적하고 연관 지을 수 있기 때문에 프라이버시에 매우 취약하다
  • 매 트랜잭션 마다 새로운 키를 사용하는 것은 프라이버시에 가장 좋긴 하지만, 관리가 매우 어려워진다.
  • 올바른 평균을 이루게 하는 것은 매우 어렵지만, 좋은 지갑 설계를 위해선 중요하다.

지갑에 대한 오해

  • 이더리움에 대한 오해 중 하나는 이더리움 지갑이 이더나 토큰을 가지고 있다는 것이다.
  • 매우 엄격히 말하자면 지갑은 단지 키만 가지고 있고, 이더나 다른 토큰들은 이더리움 블록체인에 기록되어 있다.
  • 사용자는 자신의 지갑에 있는 키를 이용해서 서명한 트랜잭션을 통해서 이더리움 네트워크에 있는 토큰을 제어한다.
  • 어떤 의미에서 지갑은 열쇠고리이다. 하지만 지갑에 보관 될 키가 이더나 토큰을 다른 사람들에게 전달하는데 사용되기 때문에 구분은 무의미하다.
  • 중요한 것은 기존 뱅킹의 중앙 집중 방식에서 블록체인 플랫폼의 탈중앙화 된 시스템으로 사고 방식으로 바꾸는 것이다.
    • 기존 뱅킹 시스템 : 자신과 은행만 자신의 계좌 잔고를 확인할 수 있고, 자금 이체를 원할 경우 은행만 확신(납득)시키면 된다.
    • 블록체인 플랫폼 : 계정의 주인을 알 수는 없지만, 누구나 계정의 이더 잔액을 확인할 수 있다. 그리고 소유자가 자금 이체를 원할 경우 모두에게 확신(납득)시켜야 한다.
  • 실제로 블록체인 플랫폼에서는 지갑 없이 계좌 잔고 확인이 가능하다. 그리고 사용하고 있는 지갑이 마음에 들지 않을 경우 다른 지갑으로 옮겨갈 수 있다.

지갑의 종류

  • 지갑은 2가지 기존 종류가 있는데, 키 간의 연관성이 있느냐 없느냐에 따라서 나뉜다.
  • 첫번째 종류는 비결정적 지갑으로, 각각의 키가 독립적으로 서로 다른 난수에서 생성된다. 이런 지갑을 JBOK(Just a Bunch of Keys) 지갑이라고도 한다.
  • 두번째 종류는 결정적 지갑으로, 모든 키가 시드라고 알려진 하나의 마스터 키에서 유도되어 나온다. 모든 키가 서로 연관되어 있으며 원본 시드가 있는 경우 복구가 가능하다. 키 유도 방법은 여러가지가 있는데, 가장 일반적으로 사용하는 방법은 Hierarchical Deterministic Wallets(BIP-32/BIP-44)에 설명되어 있는 트리와 비슷한 방법이다.

결정적 지갑의 복구

  • 데이터 손실 사고(예 : 전화를 도난 당하거나 화장실에 떨어뜨림)에 대비해서 결정적 지갑을 보다 안전하게 유지하려면, 단어 목록(영어 또는 다른 언어)으로 된 시드(니모닉 코드)를 적어두고 사고가 발생했을 때 사용하라.
  • 복구 단어 목록은 매우 신경써서 다뤄야 한다. 컴퓨터나 스마트폰에 파일 형태로 저장하지 말고, 종이에 적어서 안전한 곳에 보관하라.

비 결정적[Nondeterministic(Random)] 지갑

nondeterministic_wallet

  • 첫번째 이더리움 지갑(이더리움 프리세일을 위해 만들어짐)에는, 랜덤하게 생성 된 하나의 개인 키가 저장 된 각각의 지갑 파일이 저장되었다.
  • 이러한 "구식" 지갑은 여러면에서 뒤떨어지기 때문에 결정적 지갑으로 대체되고 있다.
  • 예를 들어 프라이버시를 극대화하기 위해 자금을 받을 때 마다 새로운 주소를 사용한다고 하자. 많은 자금을 다루게 되면 키가 점점 늘어나고 주기적으로 백업을 해야 한다. 만약에 데이터 백업 전에 손실된다면 자금과 스마트 컨트랙트에 대한 제어권을 잃게 된다.
  • 많은 이더리움 클라이언트는 키 스토어 파일(추가 보안을 위해서 비밀번호로 암호화 된 하나의 개인 키가 포함 된 JSON으로 인코딩 된 파일)을 이용한다.
  • JSON 파일 내용
{
    "address": "001d3f1ef827552ae1114027bd3ecf1f086ba0f9",
    "crypto": {
        "cipher": "aes-128-ctr",
        "ciphertext":
            "233a9f4d236ed0c13394b504b6da5df02587c8bf1ad8946f6f2b58f055507ece",
        "cipherparams": {
            "iv": "d10c6ec5bae81b6cb9144de81037fa15"
        },
        "kdf": "scrypt",
        "kdfparams": {
            "dklen": 32,
            "n": 262144,
            "p": 1,
            "r": 8,
            "salt":
                "99d37a47c7c9429c66976f643f386a61b78b97f3246adca89abe4245d2788407"
        },
        "mac": "594c8df1c8ee0ded8255a50caf07e8c12061fd859f4b7c76ab704b17c957e842"
    },
    "id": "4fcb2ba4-ccdb-424f-89d5-26cce304bf9c",
    "version": 3
}
  • 키 스토어 형식은 brute-force, dictionary, rainbow table 공격으로 부터 방어하기 위해 key derivation function(KDF) 을 사용한다.
  • 쉽게 말해서 개인 키를 비밀번호(passphrase)로 직접 암호화하지 않는 대신 비밀번호를 반복적으로 해싱하여 stretched 비밀번호를 사용한다.
  • 해싱을 262,144번 반복한다. JSON 파일의 crypto.kdfparams.n 파라미터에서 확인할 수 있다.
  • brute-force로 비밀번호를 알아내려는 공격자는 매 번 262,144번의 해싱을 해야하는데, 충분히 복잡하고 긴 비밀번호에 대해서 공격이 불가능 하도록 공격 속도를 늦춘다.

비결정적 지갑은 단순한 테스트 이 외에는 사용하는 것을 권장하지 않는다. 백업이 너무 성가시고 가장 기본적인 상황에 사용된다. 대신 산업표준기반의 백업용으로 니모닉 시드가 있는 HD 지갑을 사용하여라.

결정적[Deterministic(Seeded)] 지갑

deterministic_wallet

  • 결정적(Deterministic or "seeded") 지갑은 하나의 마스터 키(또는 시드)에서 유도(파생)된 모든 개인 키를 포함하고 있다.
  • 시드는 랜덤하게 생성 된 숫자로 인덱스 번호 또는 "체인 코드"와 같은 다른 데이터와 조합되어 개인 키를 유도한다.
  • 결정적 지갑 생성 시의 하나의 백업으로도 충분히 모든 유도 된 키를 복구할 수 있어서, 지갑의 모든 자금과 스마트 컨트랙트를 보호하는데 충분한다.
  • 시드로 지갑 임포트, 익스포트를 할 수 있어서 쉽게 다른 지갑 간의 키 이동이 허용된다.
  • 이러한 설계는 전체 지갑의 접근에 시드 하나만 필요하므로, 시드 보안을 가장 중요하게 만듭니다. 반대로 단일 데이터에만 보안 노력을 집중시킬 수 있어 이점으로 볼 수 있다.

계층 결정적[HD(Hierarchical Deterministic)] 지갑 (BIP-32/BIP-44)

hd_wallet

  • 결정적 지갑은 단일 시드에서 많은 키를 쉽게 유도하기 위해 만들어졌다.
  • 현재 가장 진보한 형태의 결정적 지갑은 계층 결정적(HD) 지갑이다. (비트코인의 BIP-32 표준에 정의)
  • HD 지갑은 트리 구조(부모 키가 연속 된 자식 키를 유도할 수 있고, 각각의 자식 키는 손자 키를 유도할 수 있음)의 유도 된 키를 포함하고 있다.
  • HD 지갑은 단순한 결정적 지갑보다 몇 가지 장점이 있다.
    • 첫째, 트리 구조는 추가적인 조직적 의미를 나타내는데 사용할 수 있다. 특정 서브 키의 브랜치는 입금을 위해 사용하고, 다른 브랜치는 출금의 잔돈 받기 위해 사용할 수 있다. 키 브랜치는 기업 설정에도 사용할 수 있다. 부서, 자회사, 특정 기능 또는 회계 카테고리를 다른 브랜치로 할당할 수 있다.
    • 둘째, 사용자가 개인 키에 접근하지 않고도, 연속 된 공개 키를 생성할 수 있다는 것이다. 자금을 사용할 수 있는 개인 키를 지갑이 가지고 있지 않기 때문에, HD 지갑은 안전하지 않은 서버나 감시 전용 또는 수신 전용으로 사용할 수 있다.

시드와 니모닉 코드 (BIP-39)

  • 개인 키의 안전한 백업과 복구를 위한 인코딩 방법은 여러가지가 있다. 현재 가장 선호하는 방법은 연속 된 단어를 이용하는 것으로, 올바른 순서로 단어를 입력하면 개인 키를 다시 만들 수 있다.
  • 이것을 니모닉이라고 부르며, BIP-39에서 표준화 되었다.
  • 요즘 많은 이더리움 지갑(다른 암호화폐 지갑도 마찬가지로)에서 이 표준을 사용한다. 호환 가능한 니모닉을 사용하여 백업과 복구를 위해 임포트, 익스포트 가능하다.
  • 왜 이 방법이 널리 사용되지 있는지를 예제를 통해 알아보자.

결정적 지갑에 사용되는 시드

  • 16진수 표현 FCCF1AB3329FD5DA3DA9577511F8F137
  • 니모닉 단어 12개 wolf juice proud gown wool unfair wall cliff insect more detail hub
  • 실제로 나열 된 16진수를 받아 쓸 때 오류가 발생할 확률은 허용할 수 없을 정도로 높다.
  • 반대로 알려진 단어들의 목록을 다루는 것은 쉽다. 왜냐하면 단어(특히 영단어) 쓰기는 많이 반복 해봤기 때문이다. 만약 실수로 "inzect"가 기록되었다면, 지갑 복구를 위해서는 "inzect"는 유효하지 않은 단어이고 대신 "insect"를 사용해야 된다는 것을 빠르게 판단할 수 있다.

지갑의 좋은 예

  • 암호화폐 지갑 기술이 성숙해지면서 폭 넓게 호환 가능하고, 사용하기 쉬우며, 안전하고 유연하게 만드는 산업 표준들이 등장했다.
  • 이런 표준들은 지갑이 하나의 니모닉에서 다중의 다른 종류의 암호화폐 키를 유도하는 것을 허용한다.
  • 일반적인 표준들
    • Mnemonic code words, based on BIP-39
    • HD wallets, based on BIP-32
    • Multipurpose HD wallet structure, based on BIP-43
    • Multicurrency and multiaccount wallets, based on BIP-44
  • 향후 이런 표준은 변경되거나 폐기 될 수 있지만, 현재는 대부분의 블록체인 플랫폼과 그들의 암호화폐를 위한 de facto 지갑 표준으로서 사용되는 연동 기술 집합체이다.
  • 이 표준은 광범위한 소프트웨어, 하드웨어 지갑에 사용되어 서로 연동할 수 있게 만들었다. 사용자는 이 지갑 중 하나에서 니모닉을 생성하고, 다른 지갑에서 임포트할 수 있으며, 모든 키와 주소를 복구할 수 있다.
  • 이러한 표준을 지원하는 지갑의 예
    • 소프트웨어 : Jaxx, MetaMask, MyCrypto, MyEhterWallet(MEW)
    • 하드웨어 : Keepkey, Ledger, Trezor

니모닉 코드 단어 (BIP-39)

  • 니모닉 코드 단어는 결정적 지갑을 유도하기 위한 시드로 사용되는 난수를 인코딩한 단어 나열이다. 이 나열 된 단어들은 시드를 다시 만들 수 있고, 그것으로 지갑과 모든 유도(파생) 된 키들을 다시 만들 수 있다.
  • 니모닉 단어를 사용하는 결정적 지갑을 구현한 지갑 어플리케이션은 지갑을 처음 만들 때 12개에서 24개의 나열 된 단어들을 보여준다. 이 단어들의 나열이 지갑 백업이고 같거나 호환되는 지갑 어플리케이션에서 모든 키를 복구하고 다시 만드는데 사용된다.

NOTE 종종 니모닉 단어와 "브레인지갑(brainwallet)"를 헷갈려하는데, 이 두가지는 같은 것이 아니다. 가장 큰 차이점은 브레인지갑은 사용자가 선택한 단어들로 구성되고, 니모닉 단어는 지갑이 랜던하게 생성한 단어를 사용자한테 보여준다. 이 중요한 차이점이 니모닉 단어를 보다 더 안전하게 하는데, 왜냐하면 사람은 매우 좋지 않은 난수 생성 소스이기 때문이다.

  • BIP-39에 정의 된 니모닉 코드와 시드 생성을 9단계에 걸쳐 설명하려한다. 명확하게 하기 위해 1 ~ 6 단계는 니모닉 코드 생성이고, 7 ~ 9 단계는 니모닉에서 시드 추출이다.

아래 부터는 한글로 변역이 필요함


니모닉 코드 생성하기

  1. Create a cryptographically random sequence S of 128 to 256 bits.
  2. Create a checksum of S by taking the first length-of-S ÷ 32 bits of the SHA-256 hash of S.
  3. Add the checksum to the end of the random sequence S.
  4. Divide the sequence-and-checksum concatenation into sections of 11 bits.
  5. Map each 11-bit value to a word from the predefined dictionary of 2,048 words.
  6. Create the mnemonic code from the sequence of words, maintaining the order. mnemonic_words

엔트로피에 따른 니모닉 길이 표 링크

니모닉에서 시드 추출

  • The entropy is then used to derive a longer (512-bit) seed through the use of the key-stretching function PBKDF2.
  • The key-stretching function takes two parameters: the mnemonic and a salt. The purpose of a salt in a key-stretching function is to make it difficult to build a lookup table enabling a brute-force attack.
  1. The first parameter to the PBKDF2 key-stretching function is the mnemonic produced in step 6.
  2. The second parameter to the PBKDF2 key-stretching function is a salt. The salt is composed of the string constant "mnemonic" concatenated with an optional user-supplied passphrase.
  3. PBKDF2 stretches the mnemonic and salt parameters using 2,048 rounds of hashing with the HMAC-SHA512 algorithm, producing a 512-bit value as its final output. That 512-bit value is the seed.

mnemonic_to_seed

BIP-39의 선택적 비밀번호(passphrase)

  • The BIP-39 standard allows the use of an optional passphrase in the derivation of the seed. If no passphrase is used, the mnemonic is stretched with a salt consisting of the constant string "mnemonic", producing a specific 512-bit seed from any given mnemonic. If a passphrase is used, the stretching function produces a different seed from that same mnemonic. In fact, given a single mnemonic, every possible passphrase leads to a different seed.
  • The optional passphrase creates two important features:
    • A second factor (something memorized) that makes a mnemonic useless on its own, protecting mnemonic backups from compromise by a thief.
    • A form of plausible deniability or "duress wallet," where a chosen passphrase leads to a wallet with a small amount of funds, used to distract an attacker from the "real" wallet that contains the majority of funds.
  • However, it is important to note that the use of a passphrase also introduces the risk of loss:
    • If the wallet owner is incapacitated or dead and no one else knows the passphrase, the seed is useless and all the funds stored in the wallet are lost forever.
    • Conversely, if the owner backs up the passphrase in the same place as the seed, it defeats the purpose of a second factor.

니모닉 코드를 사용하는 곳

  • python-mnemonic : The reference implementation of the standard by the SatoshiLabs team that proposed BIP-39, in Python
  • ConsenSys/eth-lightwallet : Lightweight JS Ethereum wallet for nodes and browser (with BIP-39)
  • npm/bip39 : JavaScript implementation of Bitcoin BIP-39: Mnemonic code for generating deterministic keys
  • Mnemonic Code Converter

시드로 부터 HD 지갑 만들기

  • HD wallets are created from a single root seed, which is a 128-, 256-, or 512-bit random number. Most commonly, this seed is generated from a mnemonic as detailed in the previous section.
  • Every key in the HD wallet is deterministically derived from this root seed, which makes it possible to recreate the entire HD wallet from that seed in any compatible HD wallet. This makes it easy to export, back up, restore, and import HD wallets containing thousands or even millions of keys by transferring just the mnemonic from which the root seed is derived.

HD 지갑 (BIP-32)과 패스(Paths) (BIP-43/44)

확장된(extended) 공개 키와 개인 키

  • In BIP-32 terminology, keys can be "extended.” With the right mathematical operations, these extended "parent" keys can be used to derive "child" keys, thus producing the hierarchy of keys and addresses described earlier.
  • Extending a key involves taking the key itself and appending a special chain code to it. A chain code is a 256-bit binary string that is mixed with each key to produce child keys.
  • If the key is a private key, it becomes an extended private key distinguished by the prefix xprv: xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8i...
  • An extended public key is distinguished by the prefix xpub: xpub661MyMwAqRbcEnKbXcCqD2GT1di5zQxVqoHPAgHNe8dv5JP8gWmDproS6kFHJnLZd23tWevhdn
  • A very useful characteristic of HD wallets is the ability to derive child public keys from parent public keys, without having the private keys. This gives us two ways to derive a child public key: either directly from the child private key, or from the parent public key.
  • 예제 두 가지
    • One common application of this method is to install an extended public key on a web server that serves an ecommerce application.
    • Another common application of this solution is for cold-storage or hardware wallets. In that scenario, the extended private key can be stored in a hardware wallet, while the extended public key can be kept online.

Hardened child key derivation

  • Extended key의 단점 : the xpub contains the chain code (used to derive child public keys from the parent public key), if a child private key is known, or somehow leaked, it can be used with the chain code to derive all the other child private keys. A single leaked child private key, together with a parent chain code, reveals all the private keys of all the children.
  • HD wallets use an alternative derivation function called hardened derivation, which "breaks" the relationship between parent public key and child chain code. The hardened derivation function uses the parent private key to derive the child chain code, instead of the parent public key. This creates a "firewall" in the parent/child sequence, with a chain code that cannot be used to compromise a parent or sibling private key.

Index numbers for normal and hardened derivation

  • It is clearly desirable to be able to derive more than one child key from a given parent key. To manage this, an index number is used.
  • To easily distinguish between keys derived through the normal (unhardened) derivation function versus keys derived through hardened derivation, this index number is split into two ranges.
  • Index numbers between 0 and 2^31–1 (0x0 to 0x7FFFFFFF) are used only for normal derivation.
  • Index numbers between 2^31 and 2^32–1 (0x80000000 to 0xFFFFFFFF) are used only for hardened derivation.
  • first normal child key : 0
  • first hardened child key : 0'
  • first hardened child key : 1'
  • When you see an HD wallet index i' : 2^31 + i

HD wallet key identifier (path)

  • Keys in an HD wallet are identified using a "path" naming convention, with each level of the tree separated by a slash (/) character.
  • Private keys derived from the master private key start with m. Public keys derived from the master public key start with M.
  • Therefore, the first child private key of the master private key is m/0. The first child public key is M/0. The second grandchild of the first child is m/0/1, and so on.
  • The "ancestry" of a key is read from right to left, until you reach the master key from which it was derived. For example, identifier m/x/y/z describes the key that is the z-th child of key m/x/y, which is the y-th child of key m/x, which is the x-th child of m.
  • HD Wallet path examples

Navigating the HD wallet tree structure

  • The HD wallet tree structure is tremendously flexible. The flip side of this is that it also allows for unbounded complexity: each parent extended key can have 4 billion children: 2 billion normal children and 2 billion hardened children. Each of those children can have another 4 billion children, and so on. The tree can be as deep as you want, with a potentially infinite number of generations. With all that potential, it can become quite difficult to navigate these very large trees.
  • Based on BIP-43, an HD wallet should use only one level-1 branch of the tree, with the index number defining the purpose of the wallet by identifying the structure and namespace of the rest of the tree. More specifically, an HD wallet using only branch m/i'/... is intended to signify a specific purpose and that purpose is identified by index number i.
  • BIP-44 proposes a multicurrency multiaccount structure signified by setting the "purpose" number to 44'. All HD wallets following the BIP-44 structure are identified by the fact that they only use one branch of the tree: m/44'/*.
  • BIP-44 specifies the structure as consisting of five predefined tree levels:

m / purpose' / coin_type' / account' / change / address_index

  • first level : purpose' is always set to 44'
  • second level : coin_type'. specifies the type of cryptocurrency coin, allowing for multicurrency HD wallets where each currency has its own subtree under the second level. SLIP0044
  • third level : account'. which allows users to subdivide their wallets into separate logical subaccounts for accounting or organizational purposes. For example, an HD wallet might contain two Ethereum "accounts": m/44'/60'/0' and m/44'/60'/1'. Each account is the root of its own subtree.
  • fourth level : change. an HD wallet has two subtrees: one for creating receiving addresses and one for creating change addresses. Only the "receive" path is used in Ethereum, as there is no necessity for a change address like there is in Bitcoin.
  • Note that whereas the previous levels used hardened derivation, this level uses normal derivation. This is to allow the account level of the tree to export extended public keys for use in a nonsecured environment. Usable addresses are derived by the HD wallet as children of the fourth level, making the fifth level of the tree the address_index.

BIP-44 HD Wallet structure examples M/44'/60'/0'/0/2 : The third receiving public key for the primary Ethereum account M/44'/0'/3'/1/14 : The 15th change-address public key for the 4th Bitcoin account m/44'/2'/0'/0/1 : The second private key in the Litecoin main account, for signing transactions

결론

Wallets are the foundation of any user-facing blockchain application. They allow users to manage collections of keys and addresses. Wallets also allow users to demonstrate their ownership of ether, and authorize transactions, by applying digital signatures

Clone this wiki locally