#はじめに
こんちわ、らいうです!
Ask mona 3.0のようなログイン機能を実装したいと思い、数日格闘していました。
今日、なんとかサンプルプロジェクトができたので、メモを残しておきます。
ソースに関してはこちら
https://github.com/Raiu1210/mpurse_login
#環境
・Mac OS Mojave
・node -v -> v10.16.0
・vue -V -> 3.9.2
・python 2.7.10
node.jsに関してはもうやってる人も多いと思いますがnvmを使って、プロジェクトごとにバージョンを切り替えられるようにしておきましょう。
また、bitcoreやbitcoin-jsなどのモジュールをnpm installする際にpython2.系が必要になるっぽいです。
僕は、Macのセットアップでデフォのpython2.7をアンインストールしてpyenvでpython3系を使っていたので、エラーが出ました。
pyenvでlocalを2.7.10を指定しました。
#やったことの流れ
プロジェクトの土台に関しては
https://qiita.com/y4u0t2a1r0/items/a6aea444efc8e8e65293
この記事を参考にしながら作っていきました。
この記事でローカル環境において
・node.jsで構築したバックエンドとVue.jsで作ったフロントがPOST通信できるようにします。
上の記事で作ったフロント側を、前に僕が書いた記事で作ったものに置き換えてhttps対応などすることで
window.mpurseインスタンスが使える(インジェクトされる)ようにします。
https://qiita.com/Raiu1210/items/b4031624e3829c8bd672
バックエンドもhttps化するために
https://kaworu.jpn.org/javascript/node.js%E3%81%AB%E3%82%88%E3%82%8BHTTPS%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9
この記事を参考にしました。
上でリンクを張った僕の記事で、opensslを使ってオレオレ証明書をそろえますが、同じ証明書に対してパスを通せばOKでした。
フロントエンド
処理のイメージとしては
・フロントでメッセージにmpurseで署名をする
・バックエンドにPOSTする
内容
・メッセージ
・アドレス
・署名
・署名結果を待つ、受け取る
といった形です。
import axios from 'axios'
export default () => {
return axios.create({
baseURL: 'https://localhost:3000/'
})
}
これは、参考にして作ったものとほとんど変わらないですね
これが署名を作ってPOSTする関数です。
HelloWorld.vueで作ったボタンを押した際に呼ばれます
import Api from './index'
export default {
async ask_verify_sig () {
var date = new Date();
var a = date.getTime();
var address = await window.mpurse.getAddress()
var message = "Please sign this message :" + a
var signature = await window.mpurse.signMessage(message);
const item = { address: address, message: message, signature: signature }
return Api().post('/verify', item)
}
}
現在のタイムスタンプを取得して、署名メッセージを作成します。
そして、それを引数としてmpurseのsignMessage()に渡します。
その後、itemにAddress, message, signatureを入れてPOSTします。
trueが返ってきた場合とfalseが返ってきた場合で適当なメッセージを決めて,alertするようにしました。
これで目に見えてデカデカと確認できます。
#バックエンド
バックエンドではbitcoinjs-messageを使って、署名を検証しました。
python3系を使っている人は注意。pyenvなどでこのディレクトリ内では2系にしましょう。
それを確認したら
npm install bitcoinjs-message
しましょう。
const express = require('express')
const bodyParser = require('body-parser')
const bitcoinMessage = require('bitcoinjs-message')
const cors = require('cors')
const app = express()
const messagePrefix = "\x19Monacoin Signed Message:\n"
var fs = require('fs');
var https = require('https');
app.use(bodyParser.json())
app.use(cors())
var options = {
key: fs.readFileSync('../../../work/ssl/localhost.key'),
cert: fs.readFileSync('../../../work/ssl/localhost.crt')
};
var server = https.createServer(options,app);
app.post('/verify', function(req, res) {
var date = new Date();
var a = date.getTime();
var address = req.body.address
var message = req.body.message
var signature = req.body.signature
var result = message.split(':');
var time_diff = a - parseInt(result[1], 10)
var is_varify = bitcoinMessage.verify(message, address, signature, messagePrefix)
console.log(is_varify)
if(time_diff < 6000 && is_varify) {
var return_message = true
} else {
var return_message = false
}
res.send({
message: return_message
})
})
server.listen(3000);
まず
const bitcoinMessage = require('bitcoinjs-message')
で、bitcoinjs-messageをインポートしてきます。
そして大事なのが
const messagePrefix = "\x19Monacoin Signed Message:\n"
これのおかげでモナコインに対応してくれます。
ここに関しては
海野('A`)ヴァー山猿:https://twitter.com/CryptoMonkey_ja
さんが教えてくれました!
ありがとうございます!
bitcoin-js-messageとbitcore-messageでの検証の仕方を教えてくれました
https://gist.github.com/fkfk/7652bb480197036c31bac186f697bd65
そして検証に関して、一応
署名が直近1分以内に行われた場合にtrueを返すようにしてみました。
ただ、https通信でないとmpurseは使えないので、正直この機能はいらないかもしれません。
future work
今日、脇Pからアドバイスもらって
https://github.com/cryptocoinjs/coininfo
こんなものがあるそうです。
Monacoinに限らずAltcoinを扱う場合にとても便利そうでした。
次はこれ使ってみようと思っているので、またその時は記事書きます。
# ざっくりこんなかんじ
とまあ、さっくり書いてみました。
十分な説明でなかったらコメントやtwitterでDMしてください。
twitter : https://twitter.com/Mr_1484