블록체인 지갑

707·2022년 6월 20일
1

블록체인

목록 보기
6/10
post-thumbnail

블록체인 지갑

암호화폐의 지갑은 지갑 주소암호(개인키)로 구성되어있다.
다른 사람에게 코인을 보내는 경우 지갑의 주소와 전송한 금액 등이 적힌 트랜잭션 기록이 블록에 들어가게된다.
실제로 지갑 상에서 직접 코인을 가지고 있는 것이 아닌 지갑주소와 그 지갑주소에서 일어난 지금까지의 거래기록으로 현재 해당 지갑이 가지고 있는 코인의 잔액을 표시해주는 시스템이다.

개인키

무작위로 추출된 숫자와 문자 조합으로 이루어진 비밀번호. 256비트 길이의 랜덤하게 생성된 숫자이다. 보통 64자리의 16진수로 표현된다.

개인키는 지갑주소와 1:1로 대응되며, 지갑에 저장된 코인을 입출금하기 위한 도구이다. 즉, 개인키를 이용해 거래가 발생하게되며 그렇기 때문에 이 개인키가 외부에 노출된 경우 타인이 임의로 생성한 트랜잭션에 유효한 서명을 할 수 있다.
개인키로 트랜잭션에 서명을 하면 블록체인 네트워크에서는 공개키로 서명을 검증하여 트랜잭션을 시도한 사람이 진짜 지갑의 주인이 맞는지를 확인하게 된다. 개인키만 가지고 있으면 얼마든지 그 지갑에서 거래를 할 수 있게된다는 말이니 취급에 각별한 주의가 필요하다.

이렇게 개인키와 공개키를 사용하는 방식은 비대칭키 방식이라고도 하며, 반드시 두 개가 수학적인 쌍을 이룬다.

import { randomBytes } from "crypto";

privKey = randomBytes(32).toString("hex");

단순하게 32byte의 16진수 (64자리 string) 생성



공개키

개인키로부터 연산되어 생성되는 값으로 (항상 한 쌍이다!) 블록체인 거래에서 해당 공개키를 가지고 있는 사람의 거래들이 참인지 거짓인지 확인이 가능하다.
또한 공개키로부터 비트코인 주소가 생성된다.

공개키는 secp256k1이라는 표준에 정의된 타원곡선을 이용한 방식으로 생성되며, 트랜잭션이 발생할 때 해당 트랜잭션을 검증하는 역할을 해준다.


비트코인의 경우 출금을 하고자 할 때 다음과 같이 처리된다.

  1. 송금자는 개인키와 공개키로 이루어진 한 쌍의 키를 생성한다.
  2. 송금자는 공개키를 미리 수신자에게 전달한다. 송금자의 전자 서명을 검증하기 위해 수신자는 송금자의 공개키를 알고 있어야 한다.
  3. 송금자는 데이터의 해시값을 생성하고, 생성된 해시값을 개인키를 이용해 암호화한다. 이 때 송금자만 가지고 있는 개인키를 이용한다. 👉 전자서명 생성.
  4. 송금자는 생성된 전자서명을 원래 보내려던 원본 데이터에 붙여서 수신자에게 전달한다.
  5. 수신자는
    5-1. 원본 데이터의 해시값을 직접 계산
    5-2. 공개키를 사용해 전자서명을 복호화하여 해시값 계산
    위의 두 계산값이 동일하다면 데이터가 변조되지 않았고 송금자가 확인된 정상적인 거래임을 확인할 수 있게된다!

import elliptic from "elliptic"; // 타원곡선 라이브러리

const keyPair = ec.keyFromPrivate(privKey); 
// 타원곡선 알고리즘으로 keypair를 생성해서 퍼블릭키를 구할 수 있음.
pubKey = keyPair.getPublic().encode("hex", true); 
// 퍼블릭키 생성한걸 16진수로 압축해서 (compact:true) 나타내겠다.


계정

공개키로 생성된 나의 지갑주소.

이더리움의 경우 공개키의 마지막 40자를 주소로 사용한다.
이렇게 하나의 지갑에 각 코인의 체인이 사용하는 공개키👉주소 변환방법을 사용하여 여러가지 코인의 주소를 가질 수 있게된다.

const buffer = Buffer.from(pubKey);
const address = buffer.slice(26).toString();



전자서명

개인키와 트랜잭션 내용을 해싱한 값을 이용하여 서명을 만든다.
서명을 만들기 위해서는 지갑의 주인만 알고있는 개인키가 필요하니 수신자 입장에서는 이 서명을 검증하는 것으로 트랜잭션을 요청한 사람이 정상적인 지갑주인임을 확인할 수 있다.

const keyPair = ec.keyFromPrivate(privKey);
const hash = SHA256("transaction data 들어감").toString();
signature = keyPair.sign(hash, "hex");



서명검증

블록체인 서버는 지갑에서 보낸 데이터의 서명을 검증하여 트랜잭션을 시도하는 사용자가 올바른 사용자인지 확인한다.
클라이언트는 트랜잭션 내용으로 만든 해시와 자신의 개인키서명을 생성하고
블록체인 서버는 사용자가 보낸 해시공개키를 이용하여 해당 서명을 검증한다.

타원곡선 알고리즘을 사용하면 이런 비대칭적 구조로 트랜잭션을 할 수 있어클라이언트는 개인키의 노출없이 안전한 거래가 가능해진다!

const hash = SHA256("hanbin").toString();
const keyPair = ec.keyFromPublic(pubKey, "hex");
const verify = ec.verify(hash, signature, keyPair);
// 위 코드는 아래처럼 쓸 수도 있다.
// const verify = keyPair.verify(hash, signature);
console.log(verify); // true ⭕️

// 임의의 공개키로 verify를 시도하면 false가 출력된다.
const keyPair2 = ec.keyFromPublic(
  "0339b0a1ed8ea377f313fe1f7b02e9c7a27fbe5a800034054d66ea93a86b702a69",
  "hex");
const verify2 = ec.verify(hash, signature, keyPair2); // false ❌

0개의 댓글