楕円曲線暗号 秘密鍵、メッセージへの署名
プログラミング・ビットコイン ―ゼロからビットコインをプログラムする方法 (Jimmy Song(著)、中川 卓俊(監修)、住田 和則(監修)、中村 昭雄(監修)、星野 靖子(翻訳)、オライリー・ジャパン)の3章(楕円曲線暗号)、3.11(署名と検証)、3.11.6(署名の作成)、練習問題7の解答をPythonではなく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 {
m := new(big.Int)
exp.DivMod(exp, two, m)
if m.Cmp(one) == 0 {
i.Mul(i, base)
}
base.Mul(base, base)
base.Mod(base, ecc.N())
}
i.Mul(i, base)
i.Mod(i, ecc.N())
return i
}
func main() {
e := big.NewInt(12345)
b := sha256.Sum256([]byte("Programming Bitcoin"))
z := big.NewInt(int64(binary.BigEndian.Uint32(b[:])))
k := big.NewInt(1234567890)
r := ecc.G.ScalarMul(k).X.Num
kInv := pow(k)
s := new(big.Int)
s.Set(r)
s.Mul(s, e)
s.Add(s, z)
s.Mul(s, kInv)
s.Mod(s, ecc.N())
fmt.Printf("署名: (0x%x,0x%x)\n", r, s)
}
入出力結果(Terminal, Zsh)
% go run main.go
署名: (0x2b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef22,0x9d3a74faaa95b4ef3578b00659cf4e7e922398202425e36eab21774d3639dbec)
%