楕円曲線暗号 Goによる署名の作成
プログラミング・ビットコイン ―ゼロからビットコインをプログラムする方法 (Jimmy Song(著)、中川 卓俊(監修)、住田 和則(監修)、中村 昭雄(監修)、星野 靖子(翻訳)、オライリー・ジャパン)の3章(楕円曲線暗号)、3.11(署名と検証)、3.11.6(署名の作成)をPytrhonではなくGoで署名を作成してみる。
コード
package main
import (
"bitcoin/ecc"
"crypto/sha256"
"encoding/binary"
"fmt"
"math/big"
)
func pow(x *big.Int) *big.Int {
i := big.NewInt(1)
exp := new(big.Int)
exp.Set(ecc.N())
exp.Sub(exp, big.NewInt(2))
base := new(big.Int)
base.Set(x)
one := big.NewInt(1)
two := big.NewInt(2)
for exp.Cmp(one) != 0 {
r := new(big.Int)
r.Set(exp)
r.Mod(exp, two)
if r.Cmp(one) == 0 {
i.Mul(i, base)
exp.Sub(exp, one)
}
base.Mul(base, base)
base.Mod(base, ecc.N())
exp.Div(exp, two)
}
i.Mul(i, base)
i.Mod(i, ecc.N())
return i
}
func main() {
eBytes := sha256.Sum256([]byte("my secret"))
zBytes := sha256.Sum256([]byte("my message"))
e := binary.BigEndian.Uint64(eBytes[:])
eInt := big.NewInt(int64(e))
z := binary.BigEndian.Uint64(zBytes[:])
zInt := big.NewInt(int64(z))
k := big.NewInt(1234567890)
r := ecc.G.ScalarMul(k).X.Num
kInv := new(big.Int)
kInv.Set(pow(k))
s := new(big.Int)
s.Set(r)
s.Mul(s, eInt)
s.Add(zInt, s)
s.Mul(s, kInv)
s.Mod(s, ecc.N())
point := ecc.G.ScalarMul(eInt)
fmt.Println(point)
fmt.Printf("z = 0x%x\nr = 0x%x\ns = 0x%x\n", z, r, s)
}
入出力結果(Terminal, Zsh)
% go run main.go
S256Point(10e83f4150adc34779367355a7b17cabdda5f46e23cb7dd032da94b27ad40fa6, e7fab2554ce9edee23901ccbba86b0303305a5343618135ece134a0041490ec8)
z = 0xea38e30f75767d7e
r = 0x2b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef22
s = 0xb4a951689f001626959b04d1bc0404c70b88281428e46e9ab918c850ad78d75e
%