##アドレスの生成
ランダムな秘密鍵を元にECDSAを用いて公開鍵を作成。
公開鍵をKeccac-256を用いてハッシュ化し、末尾20バイトを抜き出す。その頭に16進法を表すプレフィックス"0x"をつけることでアドレスを生成する。
一つのアカウントと秘密鍵、公開鍵、アドレスが一対一で対応している。アドレスから公開鍵を作成することや公開鍵から秘密鍵を生成することはできない。
##電子署名
作成者の保証と内容の非改竄性を実現するための仕組み。
署名生成と署名検証(https://ja.wikipedia.org/wiki/%E9%9B%BB%E5%AD%90%E7%BD%B2%E5%90%8D)
##ethereumにおける署名検証
文書とアドレスから署名shaと検証に使うデータv,r,sを作成する
function signString(text) {
//文書をハッシュ化
let sha = '0x' + web3.sha3(text);
/*アカウントのアドレス(ここではマイナーのアドレス)とハッシュ値を渡して署名(132文字)を作成*/
let sig = web3.eth.sign(coinbase, sha);
//プレフィックス"0x"を取り除く
sig = sig.substr(2, sig.length);
//前半64文字にプレフィックス"0x"をつける
let r = '0x' + sig.substr(0, 64);
//後半64文字にプレフィックス"0x"をつける
let s = '0x' + sig.substr(64, 64);
//末尾2文字を16進法に変換し27を足す
let v = web3.toDecimal(sig.substr(128, 2)) + 27;
return {sha, v, r, s};
}
署名からアドレスを復元する
contract Test {
function check(bytes32 data, uint8 v, bytes32 r, bytes32 s) constant returns(address) {
return ecrecover(data, v, r, s);
}
}
検証対象のアドレスと復元したアドレスが一致しているか確認することによって署名を検証する。
##ecrecoverのソースコード
exports.ecrecover = function (msgHash, v, r, s) {
//r,sを結合させる
const signature = Buffer.concat([exports.setLength(r, 32), exports.setLength(s, 32)], 64)
const recovery = v - 27
if (recovery !== 0 && recovery !== 1) {
throw new Error('Invalid signature v value')
}
const senderPubKey = secp256k1.recover(msgHash, signature, recovery)
return secp256k1.publicKeyConvert(senderPubKey, false).slice(1)
}
##参考
(https://web3js.readthedocs.io/en/1.0/web3-eth.html)
(https://github.com/ethereumjs/ethereumjs-util/blob/master/index.js)
(https://github.com/ethereum/web3.js/issues/392)