[Blockchain] Mnemonic Wallet

EllaDev·2022년 4월 6일
0

이 글은 간단한 Mnemonic Wallet 개발 과정을 기록한 것이다.

Mnemonic 정의

사전적 정의

기억술(記憶術, 영어: mnemonic)은 정보의 기억을 위한 방법으로, 특히 숫자의 나열처럼 직관적인 관계가 없어 외우기 어려운 정보에 다른 정보를 연결하여 외우기 쉽도록 하는 데 쓰인다. 대표적인 예로 리듬을 가진 노래를 만들어 외우거나, 생일과 같이 이미 자기와 깊게 관련된 정보로부터 연상을 하는 것이 있다. - 위키 백과

'Mnemonic'의 어원은 "기억"을 기반으로 가지고 있다.
개발에서는 특정 문자를 알기 쉽게(기억하기 쉽게) 표현하는 방법으로 사용됩니다.
예를 들면, 초기 컴퓨터 개발에서 기계어를 사람이 이해하기 쉽고 편리하게 만들기 위해서 Assembly언어가 나오게 되었다. 또한 C언어, Java 또한 개발자들이 쉽게 개발하기 위해 나온 언어이다. 이는 모든 것은 니모닉을 사용한 것이라 할 수 있다.

Blockchain에서의 정의

블록체인에서는 암호화폐를 주고 받기 위한 암호화폐 지갑이 있다. 이 지갑은 비대칭 키 암호방식을 사용하여 암호화/복호화하는데에 Public key와 Private Key가 필요하다.
여기서 Private Key는 Public key의 소유를 증명하는 중요한 키로 외부에 노출되면 안된다.
암호화 되어있는 Private Key는 복잡하고 기억하기 어렵게 되어있어서 이를 사용자 입장에서 쓰기 편하도록 니모닉화하여 사용하기도 한다.

Mnemonic Code

BIP39 : Mnemonic Code와 Binary Seed를 생성하는 절차를 서술한 것으로 니모닉 코드의 표준이다.



Mnemonic Wallet 개발

Mnemonic Wallet

암호화폐 지갑에서 Private Key를 복원할 때 Mnemonic Parse를 사용한다.
만약 니모닉을 분실하면 절대 복구할 수 없으므로 꼭 따로 저장해두어한다.

개발 환경

사용하는 모듈 정리

{
  "express": "~4.16.1",
  "cookie-parser": "~1.4.4", 
  "cors": "^2.8.5", 
  "http-errors": "~1.6.3",
  "morgan": "~1.9.1", // nodeJS 에서 사용되는 로그 관리를 위한 미들웨어
  "pug": "2.0.0-beta11" 
  "debug": "~2.6.9", // console.log()를 대신할 수 있는 로깅(디버깅) 모듈
  "eth-lightwallet": "^4.0.0",
}

express와 pug를 이용해서 기본적인 서버와 view를 만들어서 개발 환경을 구성하였다.
그리고 Mnemonic Wallet 기능 개발을 도와줄"eth-lightwallet" 모듈 또한 필요하다.

개발 기능

newMnemonic API

기능
새로운 Mnemonic 코드를 생성하는 API

코드

router.post("/newMnemonic", async (req, res) => {
  let mnemonic;
  try {
    mnemonic = lightwallet.keystore.generateRandomSeed();
    res.json({ mnemonic }).status(200);
  } catch (error) {
    res.status();
    console.log(error);
  }
});
  • keystore.generateRandomSeed() : 새로운 Mnemonic 문자열을 생성하여 반환하는 함수

PostMan에서 확인

newWallet API

기능
니모닉 코드와 비밀번호를 이용해서 키스토어 생성하는 API

코드

router.post("/newWallet", async (req, res) => {
  let password = req.body.password;
  let mnemonic = req.body.mnemonic;
  
  try {
    let options = {
      password: password,
      seedPhrase: mnemonic,
      hdPathString: "m/0'/0'/0'",
    };
    lightwallet.keystore.createVault(options, function (err, data) {
      data.keyFromPassword(password, function (err, pwDerivedKey) {
        data.generateNewAddress(pwDerivedKey, 1);
        let address = (data.getAddresses()).toString();
        let keystore = data.serialize();
		res.json({ keystore: keystore, address: address });
      });
    });
  } catch (error) {
    console.log('newWallet : ',error);
  }
});

-j

PostMan에서 확인

keystore를 로컬에 저장

fs 모듈(fs.writeFile)를 이용해서 .json파일로 로컬에 저장

코드

router.post("/newWallet", async (req, res) => {
  let password = req.body.password;
  let mnemonic = req.body.mnemonic;
  
  try {
    let options = {
      password: password,
      seedPhrase: mnemonic,
      hdPathString: "m/0'/0'/0'",
    };
    lightwallet.keystore.createVault(options, function (err, data) {
      data.keyFromPassword(password, function (err, pwDerivedKey) {
        data.generateNewAddress(pwDerivedKey, 1);
        let address = (data.getAddresses()).toString();
        let keystore = data.serialize();
        console.log('address', address)
        fs.writeFile('keystore.json', keystore, function(err){
           if(!err){
            res.status(200).json({ address: address, message: "성공"});
           }else{
            res.status(999).json({ message: "실패"});
           }
        })
      });
    });
  } catch (error) {
    console.log('newWallet : ',error);
  }
});

위의 전체 코드는 보고 싶다면 여기를 누르면 된다.

개발 회고

늘 지갑을 사용자로써 이용만 해보다가 어떤 원리로 구현되는 것인지 알게 되면서 신기했다.
이론은 복잡해서 전체적으로 이해하기 어려웠는데 실제로 코드를 짜보면서 전반적인 흐름을 조금은 이해할 수 있었다.
또한 "eth-lightwallet"모듈을 이용해서 복잡하게만 생각했던 지갑 기능을 미리 기능 구현된 함수를 이용해서 간단하게 할 수 있었다.
코드를 짜면서 큰 어려움은 없었지만 비동기 처리와 콜백함수를 잘못 구현해서 'newWallet API'을 만들 때 조금 헤맷던거 같다.
현재 사용한 기능 이외에도 다양한 기능들이 있으므로 더 다양한 기능들도 구현해 봐야겠다는 생각했고 비동기 처리 부분 또한 다시 한번 복습이 필요한거 같다.

profile
Frontend Developer

0개의 댓글