카테고리 없음

Blockchain Wallet(지갑)

tp134679 2025. 5. 14. 16:50

<목차>

1. ECC

2. 키페어, 서명

3. 공개키 검증

 

블록체인에서의 지갑은 타인들에게 나를 검증하고 나만이 알고있는키로 인증이 가능해야합니다.  즉 지갑이 곧 나 자신을 뜻하는 인증 매체 로서 나의 자산이나 정보 등을 가지고 있습니다. 

 

지갑이 할 수 있는 일

1. 암호화폐를 보내고 받을 수 있습니다.

 

2. 이 지갑이 나임을 인증
3. 지갑내의 잔액확인 
4. 내가 언제 얼마를 주고받았는지 거래내역을 볼 수 있습니다.
5. 복구 문구만 있다면, 지갑을 언제든 다시 복원할 수 있습니다.

 

1. ECC 

블록체인은 중앙기관이 없는만큼 모두가 나임을 검증가능하고 믿을 수 있는 인증이 필요한 수학적 기능이 필요했습니다. 

그래서 블록체인의 지갑은 ECC라는 수학적 기술을 사용하게 되었습니다. 

ECC란

타원 곡선 위에서 수학적 연산을 사용한 비대칭 암호화 방식으로서 블록체인의 지갑이 공개키 비밀키를 만들때 사용되게 됩니다.

비대칭 암호화

서로 다른 키 두 개(공개키, 비밀키)를 사용해서 정보를 암호화/복호화하는 방식입니다.

누군가에게 공개키를 줘도, 비밀키 없이는 서명이나 복호화가 불가능합니다.

 

ECC 특징 

위조 불가능: 나만 만들 수 있는 ‘도장’ (비밀키)
검증 가능:
누구나 확인할 수 있는 ‘열쇠’ (공개키)
효율적:
짧은 키, 빠른 속도, 낮은 연산 부담(256비트)
보안성:
공개키로는 절대 비밀키를 알 수 없음

안정성: 수많은 지갑이 존재: 256비트 키 → 천문학적 조합 가능

 

 

secp256k

ECC  중에는 secp256k1라는 타원곡선 알고리즘이있습니다. y² = x³ + 7   (mod p)

여기서 p는 소수로 계산합니다. 랜덤한 비밀키를 생성하고 비밀키를 기반으로  secp256k1알고리즘으로 계산하여

한쌍의 키페어를 생성합니다.  

 

2. 키페어, 서명

비밀키 

비밀키는 랜덤한 무작위의 정수로서 겹치지않은 렌덤한 64자리의 비밀 키값입니다. 지갑을 생성할때나 계정을 만들어질때 각각 비밀키가 부여되고 블록체인에서는 이 비밀키를 가지고 있어야만 나 임을 검증 가능함으로 절때 잊어버려서는 안되는 비밀 키값입니다. 또한 

secp256k1 알고리즘을 통하여 공개키와 서명값을 만들어주는 키값이기도 합니다.

  getPrivateKey(): string {
        return randomBytes(32).toString("hex");
    }

키페어 

 secp256k1 비밀키로 생성한 한쌍의 키페어 입니다 .

생성된 키페어를 가지고 서명을 하거나 공개키를 기반으로 우리의 지갑 주소로 사용하기도 합니다.

 

공개키 

    getPublicKey(): string {
        const keyPair = ec.keyFromPrivate(this.privateKey);
        return keyPair.getPublic().encode("hex", true);
    }

 

주소

 getAccount():string {
        // 공개키에서 뒷 부분 40자리만 잘라 주소로 사용
        return `${this.publicKey.slice(26)}`;
    }

 

3. 서명 공개키 검증

서명

 

서명은 트랜잭션을 보낼때 내가 이 트렌젝션을 발생시켰습니다 인증하는 서명이 들어가야합니다. 이 트랜잭션이 어디에서 나온건지 해커가 만들어낸 트랜잭션이지 또한 사용자가 나중에 이 트랜잭션을 조회하기 위해해서는 꼭 서명이 필요하기 때문에 블록체인에서는 서명이 생기게 되었습니다. 

 

내가 비밀키로 생성한 keyair 에 트렌잭션의 hash  를 넣고 사인을 해서 서명값을 만들어내는 메커니즘을 가지고 있습니다. 

   const txData = "나는 임시 트랜잭션."
        const hash = SHA256(txData).toString();
        const keyPair = ec.keyFromPrivate(privateKey);
        signature = keyPair.sign(hash, "hex");

 

 

 공개키 검증

 

 

이렇게 만들어진 서명값은 ECDSA 서명 알고리즘 을 따라서 만들어집니다. 

 

  Signature {
      r: BN {
        negative: 0,
        words: [
           3872489,   174330,
          58254850, 11726074,
          39794887, 61159837,
          33019078, 51808935,
          43635993,  2125819
        ],
        length: 10,
        red: null
      },
      s: BN {
        negative: 0,
        words: [
          58616028, 38010459, 38584541, 41690169,
          30866399, 38561419, 12427537, 42521041,
          17631685,  1807078,        0,        0,
                 0,        0,        0,        0,
                 0,        0,        0,        0,
                 0,        0,        0,        0,
                 0,        0,        0,        0,
                 0,        0
        ],
        length: 10,
        red: null
      },
      recoveryParam: 1
    }

 

이런식으로 나오게 되는데 

r , s 는 내 비밀키를 이용하여 만들어진 2개의 임의의 숫자 입니다. 

r, s = 서명의 진짜 내용

이걸로 공개키를 가진 누구나 검증 가능

하지만 비밀키 없이는 절대 만들 수 없습니다.

 

r, s 로 나뉘어서 만들어지는 이유는 비밀키로 만들어진 서명값을 공개키로 검증하기 위해서 입니다. 

사용자는 r, s , 메시지 해시, 공개키를 이용해서 다음과같이 체크합니다.  이과정에서 사용자가 유효성을 검증하고 

진짜 이 사람이 서명한 거구나 하고 신뢰를 얻을 수 있기 때문입니다. 

        const keyPair = ec.keyFromPublic(publicKey, "hex");
       const txData = "나는 임시 트랜잭션."
        const hash = SHA256(txData).toString();

        const isValid = keyPair.verify(hash, signature);