5 장. 지갑— 이더리움을 활용한 결제 시스템

birdgang
19 min readJun 30, 2024

--

암호화폐 지갑은 디지털 자산인 암호화폐를 안전하게 보관하고 관리할 수 있는 소프트웨어 도구입니다. 사용자의 개인 키(private key)와 공개 키(public key)를 관리하며, 블록체인 네트워크에서 거래를 수행할 수 있도록 도와줍니다.

2. 지갑의 종류

암호화폐 지갑은 크게 두 가지로 나눌 수 있습니다.

  1. 핫 월렛 (Hot Wallet)
  • 온라인 지갑 : 웹 브라우저를 통해 접속할 수 있는 지갑으로, 인터넷에 연결되어 있어 언제 어디서나 접근이 가능합니다. (MetaMask, MyEtherWallet)
  • 모바일 지갑 : 스마트폰에 설치하여 사용할 수 있는 지갑으로, QR 코드를 통해 빠르고 쉽게 결제를 할 수 있습니다. (Trust Wallet, Coinomi)
  • 데스크탑 지갑 : PC에 설치하여 사용하는 지갑으로, 보안성이 높지만 설치된 컴퓨터에 종속됩니다. (Exodus, Atomic Wallet)

2. 콜드 월렛 (Cold Wallet)

  • 하드웨어 지갑 : USB 형태로 된 물리적 장치에 암호화폐를 저장하는 지갑으로, 인터넷에 연결되지 않아 해킹 위험이 낮습니다. (Ledger Nano S, Trezor)
  • 종이 지갑: 개인 키와 공개 키를 종이에 출력하여 보관하는 방법으로, 해킹의 위험이 전혀 없으나 종이를 분실하거나 훼손할 위험이 있습니다.

3. 지갑의 주요 기능

암호화폐 지갑은 단순히 암호화폐를 저장하는 기능 외에도 다양한 기능을 제공합니다.

  • 거래 관리 : 암호화폐를 송금하고 받을 수 있는 기능
  • 잔액 확인 : 보유하고 있는 암호화폐의 잔액을 확인하는 기능
  • 키 관리 : 개인 키와 공개 키를 안전하게 저장하고 관리하는 기능
  • 보안 : 2단계 인증, 비밀번호 보호, 지문 인식 등 다양한 보안 옵션 제공
  • 다중 통화 지원 : 여러 종류의 암호화폐를 한 지갑에서 관리할 수 있는 기능

4. 지갑 사용의 예시

다음은 MetaMask 지갑을 사용하는 예시입니다.

MetaMask 지갑 설정

  1. MetaMask 확장 프로그램을 웹 브라우저에 설치합니다.
  2. 확장 프로그램을 실행하고 새 지갑을 생성합니다.
  3. 지갑 생성 시 제공되는 12개의 복구 문구를 안전한 곳에 보관합니다.
  4. 지갑 비밀번호를 설정합니다.

암호화폐 송금

  1. MetaMask 지갑을 열고 ‘송금’ 버튼을 클릭합니다.
  2. 받는 사람의 공개 키(주소)를 입력합니다.
  3. 송금할 암호화폐의 양을 입력합니다.
  4. 송금 수수료(Gas fee)를 설정합니다.
  5. ‘확인’ 버튼을 클릭하여 송금을 완료합니다.

5. 비결정적(무작위) 지갑

비결정적 지갑(Non-deterministic Wallet)은 사용자가 무작위로 생성된 키 쌍을 통해 암호화폐 주소를 만드는 방식입니다. 각 키 쌍은 고유하며, 동일한 키 쌍을 다시 생성할 수 없습니다. 이는 초기 암호화폐 지갑에서 사용되었으며, 각각의 주소는 별도로 백업해야 합니다.

  • 고유성 : 무작위로 생성된 각 키 쌍은 전 세계에서 유일합니다.
  • 보안성 : 임의의 키 생성으로 인해 예측이 불가능하며, 높은 보안성을 유지합니다.
  • 복잡한 관리 : 각 주소와 그에 해당하는 프라이빗 키를 개별적으로 백업해야 하므로, 관리가 어렵습니다.
  • 백업 필요 : 각 키를 별도로 백업하지 않으면, 해당 주소에 대한 접근을 영구히 잃을 수 있습니다.

사용 사례

비결정적 지갑은 초기 암호화폐 사용자들이 많이 이용했습니다. 이는 암호화폐의 보안성에 중점을 둔 방식으로, 각 거래마다 새로운 주소를 사용함으로써 프라이버시를 강화할 수 있습니다.

예시

  1. 무작위 키 생성

무작위 지갑의 프라이빗 키와 퍼블릭 주소를 생성하는 간단한 파이썬 코드를 통해 비결정적 지갑의 원리를 설명할 수 있습니다.

const Wallet = require('ethereumjs-wallet').default;
const crypto = require('crypto');

// 무작위 프라이빗 키 생성
const privateKey = crypto.randomBytes(32).toString('hex');
console.log(`프라이빗 키: ${privateKey}`);

// 프라이빗 키로부터 이더리움 계정 생성
const wallet = Wallet.fromPrivateKey(Buffer.from(privateKey, 'hex'));
const address = wallet.getAddressString();
console.log(`이더리움 주소: ${address}`);

이 코드는 무작위 프라이빗 키를 생성하고, 해당 키로부터 이더리움 계정을 만듭니다. 각각의 프라이빗 키는 고유하며, 해당 프라이빗 키를 사용해 생성된 퍼블릭 주소도 고유합니다.

2. 키 관리

비결정적 지갑을 사용할 때, 생성된 각 키 쌍을 안전하게 관리해야 합니다. 이를 위해 다음과 같은 절차를 따를 수 있습니다.

  • 키 백업 : 프라이빗 키를 안전한 장소에 기록하고, 이를 여러 곳에 백업합니다. 예를 들어, 종이에 적어 두거나 암호화된 디지털 저장소에 보관할 수 있습니다.
  • 키 관리 도구 사용 : 키를 효율적으로 관리하기 위해 키 관리 도구를 사용할 수 있습니다. 이는 키를 안전하게 저장하고, 필요할 때 쉽게 접근할 수 있게 해줍니다.
  • 보안 유지 : 프라이빗 키를 절대 공개하지 않으며, 신뢰할 수 있는 환경에서만 사용합니다.

비결정적(무작위) 지갑은 높은 보안성을 제공하는 반면, 관리의 복잡성이 큰 단점입니다. 각 프라이빗 키와 주소를 별도로 백업해야 하는 불편함이 있지만, 그만큼 보안이 강화됩니다. 초기 암호화폐 사용자들은 이러한 방식으로 프라이버시와 보안을 지켰습니다. 현대의 지갑들은 이 단점을 보완한 결정적(Deterministic) 지갑으로 발전해 왔지만, 비결정적 지갑의 원리를 이해하는 것은 암호화폐의 기초를 배우는 데 중요합니다.

6. 결정적 지갑의 정의

결정적 지갑(deterministic wallet)은 사용자가 하나의 시드(seed) 문구 또는 마스터 키를 통해 무수히 많은 개인 키와 공개 키를 생성할 수 있는 지갑입니다. 시드 문구는 일반적으로 12, 18, 24개의 단어로 구성되며, 이 단어들은 특정 순서로 배열됩니다. 이 시드 문구를 통해 생성된 모든 키들은 서로 연결되어 있으며, 단 하나의 시드 문구를 이용해 전체 지갑을 복구할 수 있습니다.

결정적 지갑의 장점

  • 단순한 백업 및 복구 : 하나의 시드 문구만 안전하게 보관하면 모든 키를 복구할 수 있습니다. 이는 지갑 분실 시에도 자산을 쉽게 복구할 수 있게 합니다.
  • 키 관리의 효율성 : 여러 개의 키를 개별적으로 관리할 필요 없이, 하나의 시드 문구로 관리가 가능합니다.
  • 안전성 : 시드 문구만 유출되지 않으면, 다른 키들이 유출되어도 지갑을 안전하게 유지할 수 있습니다.
    결정적 지갑의 유형

결정적 지갑의 유형

  • HD 지갑(Hierarchical Deterministic Wallet) : 계층적 결정적 지갑으로, 계층적 구조를 가지고 있어 다양한 용도로 분리된 키를 생성할 수 있습니다. 각 계층의 키는 부모 키에서 파생되며, 이를 통해 특정 계정 또는 용도에 따라 키를 분리 관리할 수 있습니다.
  • 단일 계층 결정적 지갑 : 단일 계층에서 모든 키가 파생되는 방식으로, 구조가 간단하며 보통 소규모 사용자에게 적합합니다.

예시

  • MetaMask를 브라우저에 설치하고 초기 설정을 진행합니다.
  • 새 지갑을 생성하면 12개의 단어로 구성된 시드 문구가 제공됩니다.
  • 이 시드 문구를 안전한 장소에 기록하여 보관합니다.
  • MetaMask 에서 “지갑 가져오기” 옵션을 선택하고, 시드 문구를 입력하여 기존 지갑을 복구합니다.

시드 문구의 보안 관리

  • 종이에 기록하여 안전한 장소에 보관 : 디지털 파일로 저장하는 것은 해킹의 위험이 있으므로 종이에 기록하는 것이 좋습니다.
  • 여러 복사본 생성 : 하나의 복사본만 보관하면 분실 시 위험하므로 여러 개의 복사본을 만들어 서로 다른 안전한 장소에 보관합니다.
  • 시드 문구 노출 방지 : 시드 문구를 누구와도 공유하지 말고, 온라인이나 네트워크가 연결된 장치에 저장하지 마십시오.

결정적 지갑은 이더리움뿐만 아니라 다양한 블록체인 네트워크에서 사용될 수 있으며, 스마트 계약을 관리하거나 다양한 암호화폐를 통합 관리하는 데 유용합니다. 결정적 지갑을 활용하면 여러 계정과 키를 손쉽게 관리할 수 있어 사용자 경험을 크게 향상시킬 수 있습니다.

7. HD 지갑 (BIP-32 / BIP-44)

HD 지갑(계층적 결정적 지갑, Hierarchical Deterministic Wallet)은 암호화폐의 주소와 키를 관리하는 방법론 중 하나입니다. HD 지갑의 가장 큰 특징은 하나의 시드(seed)로부터 무한에 가까운 키 쌍을 생성할 수 있다는 것입니다. 이는 복구와 백업을 매우 용이하게 해줍니다.

BIP-32

BIP-32 (BIP는 Bitcoin Improvement Proposal의 약자)는 비트코인의 HD 지갑(Hierarchical Deterministic Wallets) 규격을 정의하는 제안서입니다. BIP-32는 하나의 시드(seed)에서 무한한 수의 키 페어를 생성할 수 있는 계층적 구조를 제공합니다. 이를 통해 사용자는 단일 백업 시드만으로 모든 주소와 키를 복구할 수 있습니다.

  • 마스터 키(Master Key) : HD 지갑의 루트에 위치한 키 페어입니다. 하나의 시드에서 생성 됩니다.
  • 확장 키(Extended Key) : 비트코인 주소를 생성하기 위해 사용되는 키 페어에 추가 정보(체인 코드, 깊이, 인덱스 등)가 포함된 키입니다. 확장 개인 키(Extended Private Key) 확장 키의 개인 키 부분 이고, 확장 공개 키(Extended Public Key) 는 확장 키의 공개 키 부분 입니다.
  • 계층적 구조 : 키들은 트리 구조로 배열되어 있습니다. 마스터 키에서 파생된 키들이 다시 여러 하위 키를 생성하는 구조입니다.

장점

  • 단일 시드 백업 : 사용자는 단 하나의 시드만 백업하면 모든 키를 복구할 수 있습니다.
  • 계층적 구조 : 키들을 조직적으로 관리할 수 있습니다. 예를 들어, 계정, 주소, 트랜잭션 등을 구분하여 관리할 수 있습니다.
  • 확장 공개 키를 통한 보안 : 개인 키를 공개하지 않고도 여러 주소를 생성하고 관리할 수 있습니다.

BIP-44

BIP-44는 BIP-32를 기반으로 한 멀티-계정, 계층적 결정적 지갑(Hierarchical Deterministic Wallet)의 표준을 정의합니다. BIP-44는 다중 계정, 다중 주소 생성을 지원하며, 여러 체인(예: Bitcoin, Ethereum 등)을 관리할 수 있습니다. BIP-44 경로는 고정된 형식을 따릅니다.

m / purpose' / coin_type' / account' / change / address_index
  • purpose : 항상 44' (BIP-44를 따름)
  • coin_type : 각 암호화폐에 대한 고유한 번호 ( 이더리움: 60, 폴리곤: 966)
  • account : 계정 번호
  • change : 외부 주소(0)와 내부 주소(1) 구분
  • address_index : 각 계정 내 주소의 인덱스
const bip39 = require('bip39');
const bip32 = require('bip32');
const ethUtil = require('ethereumjs-util');

// 시드 생성
const mnemonic = bip39.generateMnemonic();
const seed = bip39.mnemonicToSeedSync(mnemonic);
console.log(`Mnemonic: ${mnemonic}`);
console.log(`Seed: ${seed.toString('hex')}`);


// 마스터 키 생성
const root = bip32.fromSeed(seed);
console.log(`Master Private Key: ${root.toBase58()}`);
console.log(`Master Public Key: ${root.neutered().toBase58()}`);


// 이더리움 주소 생성
const ethPath = "m/44'/60'/0'/0/0";
const child = root.derivePath(ethPath);
console.log(`First Child Private Key: ${child.toBase58()}`);
console.log(`First Child Public Key: ${child.neutered().toBase58()}`);
const privateKey = child.privateKey;
const address = ethUtil.privateToAddress(privateKey).toString('hex');
console.log(`이더리움 주소: 0x${address}`);


// 폴리곤 주소 생성
const polygonPath = "m/44'/966'/0'/0/0";
const polygonChild = root.derivePath(polygonPath);
const polygonPrivateKey = polygonChild.privateKey;
const polygonAddress = ethUtil.privateToAddress(polygonPrivateKey).toString('hex'); // 폴리곤 주소도 이더리움 형식을 따름
console.log(`폴리곤 주소: 0x${polygonAddress}`);

이 코드는 주어진 니모닉(mnemonic) 문구 로부터 시드를 생성하고, BIP-44 경로에 따라 이더리움 주소를 생성합니다.

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

BIP-39 (Bitcoin Improvement Proposal 39)은 암호화폐 지갑에서 개인 키를 생성하고 백업하는 데 사용되는 표준입니다. 이 표준은 인간이 읽을 수 있는 12개에서 24개의 단어로 구성된 니모닉 문구를 사용하여 개인 키를 생성합니다. 이 니모닉 문구는 사용자가 기억하거나 기록하여 지갑을 복구할 수 있도록 도와줍니다.

시드 (seed)

시드는 암호화폐 지갑의 생성과 복구에 사용되는 랜덤 문자열입니다. 시드는 지갑의 모든 개인 키와 공개 키를 생성하는 데 사용되며, 이를 통해 지갑의 모든 자산에 접근할 수 있습니다. 시드는 일반적으로 128 비트 또는 256 비트 길이의 랜덤 값으로 생성됩니다.

니모닉 코드 (mnemonic code)

니모닉 코드는 시드를 사람이 이해하고 기억하기 쉽게 변환한 단어들의 조합입니다. BIP-39(Bitcoin Improvement Proposal 39)는 이러한 니모닉 코드의 생성 방식을 표준화한 프로토콜입니다. BIP-39는 시드를 12개에서 24개의 단어로 변환하여 사용자가 쉽게 기록하고 저장할 수 있도록 합니다.

비밀 키 (Private Key)

시드에서 파생된 개인 키입니다.

동작 원리

  1. 시드 생성 : 무작위로 128비트 또는 256비트 길이의 시드를 생성합니다.
  2. 체크섬 추가 : 시드의 해시 값을 계산하여 그 중 일부를 시드에 추가합니다. 예를 들어, 128비트 시드에는 4비트의 체크섬이 추가되어 132비트가 됩니다.
  3. 비트 그룹화 : 체크섬이 추가된 시드를 11 비트씩 그룹화합니다. 11비트 그룹은 2048개의 단어 목록에서 하나의 단어에 해당합니다.
  4. 니모닉 코드 생성 : 각 11비트 그룹에 해당하는 단어를 찾아 12개에서 24개의 단어로 이루어진 니모닉 코드를 생성합니다.

예시

위 그림은 128비트 엔트로피를 사용하여 12개의 니모닉 단어를 생성하는 과정을 설명하고 있습니다. 이 과정은 BIP39 표준에 따라 진행됩니다. 각 단계는 다음과 같습니다.

1. 엔트로피 생성 (128비트) : 먼저, 128비트의 랜덤한 엔트로피를 생성합니다.

2. SHA256 해시 생성 : 생성된 엔트로피에 대해 SHA256 해시 알고리즘을 적용하여 해시 값을 생성합니다. 이 해시 값에서 처음 4비트를 가져옵니다.

3. 체크섬 추가 : 128비트 엔트로피에 앞서 얻은 4비트의 체크섬을 추가합니다. 이로써 총 132비트의 데이터가 생성 됩니다.

4. 11비트로 분할 : 132비트 데이터를 11비트씩 12개로 분할 합니다.

5. BIP39 단어 목록 매핑 : 각 11비트 섹션을 BIP39 단어 목록(2048 단어)과 매핑하여 각 섹션에 해당하는 단어를 찾습니다. 예를 들어, 00001100000은 “army”에 해당합니다.

6. 니모닉 코드 생성 : 매핑된 단어들을 순서대로 나열하여 12개의 니모닉 단어로 구성된 구문을 완성합니다. 예시에서는 “army van defense carry jealous true garbage claim echo media make crunch”가 생성 되었습니다.

이 과정을 통해 사용자는 니모닉 단어들을 안전하게 보관하고, 필요시 지갑 복구 등에 사용할 수 있습니다. 니모닉 단어는 사용자가 암호화폐 지갑의 프라이빗 키를 복구하는데 중요한 역할을 합니다.

관련하여 예시 코드는 다음과 같습니다.


const bip39 = require('bip39');

// 무작위 시드 생성
const randomSeed = bip39.generateMnemonic();
console.log(`랜덤 시드: ${randomSeed}`);

// 니모닉 코드로 변환
const mnemonic = bip39.entropyToMnemonic(randomSeed);
console.log(`니모닉 코드: ${mnemonic}`);

이 이미지는 니모닉 코드 단어(mnemonic code words)를 시드(seed)로 변환하는 과정을 설명하고 있습니다. 아래는 이미지의 각 부분을 상세히 설명한 내용입니다:

7. 니모닉 코드 단어 (Mnemonic Code Words)

  • 예시 : “army van defense carry jealous true garbage claim echo media make crunch”
  • 이것은 사용자가 지갑을 생성할 때 제공받는 단어 목록입니다. 사용자는 이 단어들을 안전하게 보관해야 하며, 지갑을 복구할 때 사용합니다.

8. 솔트 (Salt)

  • 구성 : “mnemonic” + (선택적) 암호(passphrase)
  • 솔트는 보안 강화를 위해 사용됩니다. 기본적으로 “mnemonic” 문자열과 선택적으로 사용자가 추가할 수 있는 암호 문구를 결합하여 만듭니다.

9. 키 스트레칭 함수 (Key Stretching Function)

  • 사용되는 함수 : PBKDF2 (Password-Based Key Derivation Function 2) with HMAC-SHA512
  • 라운드 수 : 2048회
  • 키 스트레칭 함수는 니모닉 코드 단어와 솔트를 입력으로 받아서 고유한 시드를 생성합니다. 이는 보안 강화를 위해 반복적인 해시 계산을 수행합니다.

10. 512비트 시드 (512-bit Seed)

  • 결과 값 : 5b5c417303faa3fcba7e57400e120a0ca83ec5a4fe9cfbfa757fbe63fbd77a89a1a3be4c67196f57c39a8b76373733891bfaba16ed27a813ceed498804c057
  • 최종적으로 생성된 512비트 시드는 암호화된 형태로, 이를 통해 암호화폐 지갑을 복구하거나 새로 생성할 수 있습니다.

이 과정은 니모닉 코드 단어와 선택적인 암호를 사용하여 보안성이 높은 512비트 시드를 생성하는 방식입니다. PBKDF2 함수는 입력 값을 반복적으로 해싱하여 최종 시드를 생성함으로써 보안성을 극대화 합니다. 이 시드는 암호화폐 지갑의 개인 키를 생성하는 데 사용됩니다.

관련하여 예시 코드는 다음과 같습니다.

// 니모닉 코드를 시드로 변환
const seed = bip39.mnemonicToSeedSync(mnemonic);
console.log(`시드: ${seed.toString('hex')}`);

위의 예시에서 생성된 니모닉 코드는 사용자가 지갑을 복구하거나 새로운 장치에서 지갑을 설정할 때 필요합니다. 니모닉 코드는 반드시 안전한 장소에 보관해야 하며, 절대로 타인과 공유해서는 안 됩니다.

결론

이더리움 지갑은 암호화폐 결제 시스템에서 필수적인 요소입니다. 다양한 지갑 옵션들이 각기 다른 보안 수준과 사용 편의성을 제공하며, 사용자의 필요와 목적에 따라 적절한 지갑을 선택하는 것이 중요합니다. 하드웨어 지갑은 높은 보안성을, 소프트웨어 지갑은 접근성과 사용 편의성을, 웹 지갑은 신속한 거래를, 모바일 지갑은 이동성을 제공합니다. 각 지갑 유형의 특성과 장단점을 이해하고, 이더리움의 고유한 기능들을 최대한 활용할 수 있는 전략을 세우는 것이 성공적인 암호화폐 결제 시스템 구축의 열쇠입니다. 앞으로도 기술의 발전과 더불어 지갑의 기능과 보안성도 향상될 것이며, 지속적인 학습과 최신 정보 습득이 필요합니다. 이더리움 지갑의 이해와 선택은 암호화폐 결제의 성공을 위한 첫걸음이며, 이를 통해 보다 안전하고 효율적인 결제 환경을 조성할 수 있습니다.

[6 장. 트랜잭션 — 이더리움을 활용한 결제 시스템](https://birdgang82.medium.com/6-%EC%9E%A5-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%EA%B2%B0%EC%A0%9C-%EC%8B%9C%EC%8A%A4%ED%85%9C-06220a99eea8)

--

--