dukDukz

[블록체인] 지갑 만들기 본문

웹 개발/블록체인

[블록체인] 지갑 만들기

헤일리_HJ 2021. 9. 9. 14:09

[wallet.js] 생성

secp256k1
이거를 쓴다... 상세한 내용은 블로그에서 알아보는게 좋을 것 같다.

사용방법만.. 알아보자

기본적으로 얘는 알고리즘 암호화다.
그래서 저 암호화를 사용하려면 패키지가 하나 필요한데,
그게 바로 elliptic 이다.

$ npm install elliptic

가져오자

const ecdsa = require('elliptic')

console.log(ecdsa);

 

ecdsa 를 한번 찍어보자

색을 보니 class 는 절대 아님

찍어보니 긴 객체가 나오는데
일단은 이 안에 있는 ec 라는 애를 사용할거임

그래서 사용방법이

const ec = ecdsa.ec("secp256k1")        // 암호화 방법은 secp256k1 
console.log(ec);

 

ec 를 찍어보니 긴 객체가 쭉 나온다.

이제 ec 라는 애가 갖고 있는 속성값을 사용해서 어떤걸 만들어낼 수 있는지 봐야함


1. key 만들기

 

console.log(ec.genKeyPair());


하면

KeyPair {
  ec: EC {
    ...
}

 

이런 객체가 나온다.

console.log(ec.genKeyPair().getPrivate());

 

이렇게 하면 바이너리 파일이 나온다.
words : [숫자들..] 이 있으면

.toString(16)

이렇게 바꾸면 16진수로 바뀜

.toUpperCase()
여기 까지하면 대문자로

console.log(ec.genKeyPair().getPrivate().toString(16).toUpperCase());


지금 키값을 생성한거면
렌덤 키값을 생성한거임
sha256 으로 암호화를 진행했는데 얘는 기본적으로 복화화가 안되는 단방향 암호화임

하지만 이번에 생성한 암호화는 렌덤한 글자 스트링들을 우리한테 반환해주는거임
그런데 렌덤하게 하다보면 중복될 수 있는 가능성은 없는가?

예를 들어 동전 던지기를 256번한다
앞면 0 뒷면 1 
이걸 256번
256bit

경우의 수가 2^256 = 10^77 정도가 되어서 렌덤 생성으로 인해 중복될 가능성은 희박하다.

 

 

정리

 

주로 블록체인에서 쓰는 암호화는 secp256k1 이거라고 한다.

렌덤한 키 값을 생성하기 위해서 secp256k1 이거를 썼고

console.log(ec.genKeyPair().getPrivate().toString(16).toUpperCase());
이렇게 쓰면 16진수로 반환이 되는 키값을 생성할 수 있다.

2. key 생성 함수 만들기

// key 생성하는 함수
function generatorPrivateKey(){
    const KeyPair = ec.genKeyPair()
    const privateKey = KeyPair.getPrivate()
    return privateKey.toString(16).toUpperCase()
}

console.log(generatorPrivateKey());


단순히 키를 생성한거고 아무런 의미는 없다..

지갑이라는 뜻은 무언가를 넣는 공간.


db 로 치면 
id 값이 key 값이라는것이다.
content
date

그래서 id 누구의 content 를 찾고 싶다면 볼 수 있듯이
지갑의 history 를 볼 수 있도록 해야한다.


3. 지갑 만들기 기본 작업

const fs = require('fs')


이걸 추가

db를 사용하는 이유? - 파일로만 관리하기 힘들어서..

코인은 다시 옛날로 돌아가서 파일로 관리한다고 보면 된다.

뭔가 저장하는 곳(=파일) 이 필요함

내가 생성한 블럭에 코인이라는게 있을텐데
그 생성한 내용을 지갑에 담아서 내용을 볼 수 있게 해준다.

랜덤생성을 하면, 그 사람의 지갑 주소를 실행할때마다 다르게 보여준다. -> 이건 지갑이 아니다.

 

주소값이 항상 같아야함
그래서 렌덤생성한 값을 파일에 저장해줘야 한다는 것.

 


최종 목표 : 
node server.js 가 실행되면 특정 폴더에 특정 파일에 
키 값이 나올 수 있도록 할 것이다.
keyfile을 저장함

node server.js 를 하면 
http 인터페이스를 통해서 3000번에 /address 로 요청하게 되면 (http://localhost:3000/address)
키값(generatorPrivateKey)을 보여줄 수 있도록 해줄 것이다. <- keyfile을 읽어서 보여줌

 

 


4. 키 값이 저장될 폴더 생성하기

node server.js 했는데
특정폴더 = wallet 
하나의 변수라고 생각하고

wallet이 있는지 -> fs.existsSync("wallet/")
있으면 wallet/ 생성 안함
없으면 wallet/ 폴더 생성함
mkdir 로 생성 (찾을 수도 있고 만들 수도 있음)

구현해보자!

 

const fs = require('fs')

const privateKeyLocation = "wallet/"+(process.env.PRIVATE_KEY || "default")
const privateFile = `${privateKeyLocation}/private_key`

function initWallet() {
    if (!fs.existsSync("wallet/")) {     // 값이 true 여야 if 문이 실행되니까 앞에 ! 붙여줌
        fs.mkdirSync("wallet/")     // 폴더를 생성해준다.
    }

    if(!fs.existsSync(privateKeyLocation)){
        fs.mkdirSync(privateKeyLocation)
    }

    // 파일이 있는가 없는가를 체크해봐야함
    if(!fs.existsSync(privateFile)){
        // 디렉토리를 만드는게 아니라서 mkdirSync 가 필요없음
        console.log(`주소값 키값을 생성중입니다...`);
        const newPrivateKey = generatorPrivateKey()     //key 를 생성해서 변수에 담음
        
        // 파일 생성
        fs.writeFileSync(privateFile,newPrivateKey)
        // 첫번째 인자값은 경로+파일명, 두번째 인자값은 파일 내용들

        console.log(`개인 키 생성이 완료되었습니다`);
    }    
}
initWallet()

 

 


파일을 읽어서 갖다 쓰는것도 해놔야함

파일을 읽는데 읽는 순간 우리가 알 수 없는 언어로 읽게 됨
그래서 잘라서 읽기를 시도함

// 저 파일을 읽어서 출력하는 함수
function getPrivateFromWallet(){
    // 파일을 읽어서 가져와서 buffer 에 넣을거임
    const buffer = fs.readFileSync(privateFile)
    // 첫번째 인자값은 경로+파일명
    //console.log(buffer.toString());    // 알 수 없는 Buffer ~ 형태로 가져옴
    return buffer.toString()
}
getPrivateFromWallet()
console.log(getPrivateFromWallet());

5. 비밀키를 이용해서 공개키 만들기

 

블록체인에는 키가 두개 존재함
공개키 와 비밀키

내가 나임을 증명하는 것은 비밀키로 인증
비밀키는 공개되면 내 지갑을 해킹할 수 있음..(특별한 권한까지 다 있는 키-공인인증서)

공개 키는 내 히스토리 정도만 다 보낼 수 있음 (계좌번호)

비밀 키를 갖고 내용 조작해서 공개키를 만드는 경우가 대부분이다.

function getPublicFromWallet(){
    const privateKey = getPrivateFromWallet()   // 일단 비밀키를 가져오고
    const key = ec.keyFromPrivate(privateKey,"hex") // ec 안에 있는 내장함수 keyFromPrivate()
    return key.getPublic().encode("hex")            // ec 안에 있는 내장함수 getPublic()
}

console.log(getPublicFromWallet());

module.exports = {
    initWallet,
    getPublicFromWallet,
}

 

이렇게 내보내고 사용해보자

[server.js]

 

const wl = require('./wallet')


app.get('/address',(req,res)=>{
    const address = wl.getPublicFromWallet()
    res.send({address})
})

맨 아래로 가서  
wl.initWallet()     // 저함수가 실행되면 파일, 키값 생성

추가해줌

$ node server

팽귄에서

$ curl http://localhost:3000/address



하면 

{
    "address": "04afd5d3486de820dd40ffb24437c369c676f2f799bf8dcf04c9ec8dfe22fd2ef38b167055de22c99cde26f63e9918aae8e5292fd90b2ca6089724d490fc7aa04b"
}


이런게 나온다.