JS Dev Blog
니모닉(Mnemonic) 지갑 개발 본문
니모닉(mnemonic) 이란?
개인키의 안전한 백업을 위해서 인코딩하는 방법 중 하나이다. 그 중 단어 시퀀스를 사용하는 방법을 니모닉(mnemonic)이라고 한다. BIP-39에서 표준화된 방법이다.
니모닉을 사용하는 이유
16진수 시퀀스를 사용할 경우 오류가 발생할 확률이 높다. 반면 단어 목록은 다루기가 매우 쉽다. HD 지갑의 인코딩을 위해 니모닉 단어 목록을 사용하는 것이 오류 없이 고쳐쓰고, 종이에 기록하고, 읽고, 안전하개 내보내고, 개인키들을 다른 지갑으로 가져오는 가장 쉬운 방벙비다.
니모닉 단어 생성
니모닉 단어는 BIP-39에서 정의한 표준화된 절차에 따라 지갑에서 자동으로 생성된다. 지갑은 엔트로피 원천에서 시작해서 체크섬을 추가하고 단어 목록에 엔트로피를 매핑한다.
1. 128~256비트의 무작위 암호화 시퀀스 S를 생성
2. S를 SHA-256으로 해싱한 값을 32비트로 나눈 처음 길이를 체크섬으로 생성
3. 무작위 시퀀스 S의 끝에 체크섬을 추가
4. 시퀀스와 체크섬을 연결한 것을 11비트로 나눔
5. 각각의 11비트 값을 사전에 정의된 2048단어 사전과 매핑
6. 단어의 시퀀스로부터 순서를 유지하면서 니모닉 코드를 생성
7. PBKDF2 키 스트레칭 함수의 첫 번재 파라미터는 6단계에서 생성된 니모닉이다.
8. PBKDF2 키 스트레칭 함수의 두 번째 파라미터는 솔트다. 솔트는 문자열 상수 “mnemonic”과 선택적으로 사용자가 지정한 암호문을 연결하여 구성
9. PBKDF2는 최종 출력으로 512비트 값을 만드는 HMAC-SHA512 알고리즘으로, 2048 해시 라운드를 사용하여 니모닉과 솔트 파라미터를 확장하여, 이 결과로 나온 512비트 값이 시드다.
니모닉 지갑 개발
아래 두 가지 기능을 가지는 니모닉 지갑을 개발한다.
1. 새로운 니모닉 코드를 발급
2. 발급 받은 니모닉 코드와 비밀번호를 입력하면 지갑을 생성
라우팅 (app.js)
const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');
const walletRouter = require('./routes/wallet');
const app = express();
const port = 3000;
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(
cors({
origin: ['http://localhost:3000'],
methods: ['GET', 'POST'],
credentials: true
})
);
app.get('/', function(req, res, next) {
res.status(200).send({"message": "Mnemonic server is running..."});
});
app.use('/wallet', walletRouter);
// catch 404 and forward to error handler
app.use((req, res, next) => {
const err = new Error('Not Found');
err['status'] = 404;
next(err);
});
// error handler
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
errors: {
message: err.message,
},
});
});
app.listen(port, () => {
console.log(`
################################################
🛡️ Server listening on port: ${port} 🛡️
http://localhost:${port}
################################################
`);
});
module.exports = app;
nmemonic코드 생성 및 wallet 생성하는 API (wallet.js)
const express = require('express');
const router = express.Router();
const lightwallet = require("eth-lightwallet");
const fs = require('fs');
// TODO : lightwallet 모듈을 사용하여 랜덤한 니모닉 코드를 얻습니다.
router.post('/newMnemonic', async(req,res) => {
let mnemonic
try {
mnemonic = lightwallet.keystore.generateRandomSeed()
res.json({mnemonic})
} catch(err){
console.log(err);
}
});
// TODO : 니모닉 코드와 패스워드를 이용해 keystore와 address를 생성합니다.
router.post('/newWallet', async(req, res) => {
let password = req.body.password
let mnemonic = req.body.mnemonic
try {
lightwallet.keystore.createVault(
{
password : password,
seedPhrase : mnemonic, // 계정 생성을 위한 니모닉
hdPathString : "m/0'/0'/0'",
},
function (err,ks){
ks.keyFromPassword(
password,
function(err, pwDerivedKey){
ks.generateNewAddress(pwDerivedKey,1);
let keystore = ks.serialize();
let addr = ks.getAddresses().toString();
fs.writeFile('wallet.json', keystore,
function(err,data){
if(err){
res.json({code:999, message:'fail'})
}
else{
res.send({code:1, message:`success! wallet address :${addr}`})
}
}
)
}
)
}
)
}
catch (exception){
console.log(exception)
}
});
module.exports = router;
동작 화면
개발 회고
- Keep
니모닉 코드와 지갑생성 API를 성공적으로 구현했다. 그리고 Postman을 통해 정상적으로 동작함을 확인했다. express를 통한 서버 생성 방법을 다시 한 번 복습할 수 있었다. - Problem
eth-lightwallet 패키지가 워낙 잘 되어있어서 구현하기에 편리했다. 하지만 깊은 이해 없이 라이브러리 기능을 무작정 가져다 쓴 느낌이 있다. - Try
eth-lightwallet의 세부 기능에 대해서 더 공부한다음에 사용해보고 싶다.
Github Repo
https://github.com/jongseokleedev/mnemonic_wallet/blob/master/routes/wallet.js
'BlockChain' 카테고리의 다른 글
Truffle로 ERC 721 개발 (0) | 2022.06.09 |
---|---|
DID(Decentralized Identity, 탈중앙 신원증명) (0) | 2022.06.07 |
블록체인 네트워크/합의 알고리즘 (0) | 2022.05.06 |