はじめに
catapult-serverのv0.9.3.1から、公開鍵の導出方法が変わりました。
いままでは、Ed25519+Keccak256だったのが、標準のEd25519に変わりました。
ということで、GoのEd25519ライブラリが使えるんじゃないかと思うので、やってみたいと思います。
秘密鍵から公開鍵とアドレスを導出する
こちらのNIP10を参考にやっていきます。
公開鍵
NIP10に例示してある秘密鍵と公開鍵は、
private: 575dbb3062267eff57c970a336ebbc8fbcfe12c5bd3ed7bc11eb0481d7704ced
public: 2e834140fd66cf87b254a693a2c7862c819217b676d3943267156625e816ec6f
なので、これをやってみる。
package main
import "fmt"
import "encoding/hex"
import "crypto/ed25519"
// https://golang.org/pkg/crypto/ed25519/
func main() {
seed3, _ := hex.DecodeString("575dbb3062267eff57c970a336ebbc8fbcfe12c5bd3ed7bc11eb0481d7704ced")
priv3 := ed25519.NewKeyFromSeed(seed3)
var pub3 interface{} = priv3.Public()
var pub3a ed25519.PublicKey = pub3.(ed25519.PublicKey)
fmt.Println(hex.EncodeToString(pub3a))
}
seed3
に代入しているのが秘密鍵です。
実行結果
2e834140fd66cf87b254a693a2c7862c819217b676d3943267156625e816ec6f
できました。
NIP10にはオールゼロの秘密鍵も例示してあります。
private : 0000000000000000000000000000000000000000000000000000000000000000
public : 3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29
seed3
にオールゼロを代行してみます。
実行結果
3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29
アドレス
次にアドレスです。NIP10には以下のものが例示されています。
public : 2e834140fd66cf87b254a693a2c7862c819217b676d3943267156625e816ec6f
address: TATNE7Q5BITMUTRRN6IB4I7FLSDRDWZA37JGO5UW
ハッシュ化アドレス
次にアドレスです。
NIP10によると、次の手順が必要です。
- 公開鍵をSHA3-256する
- それをRIPEMD160する
- ネットワークIDを付加する
- それをSHA3-256して先頭4バイトを取得する
- 3にそれを付加する
6.の「BASE32する」は次でやります。
package main
import (
"encoding/hex"
"fmt"
"io"
)
import "golang.org/x/crypto/sha3"
import "golang.org/x/crypto/ripemd160"
// https://godoc.org/golang.org/x/crypto/sha3
// https://godoc.org/golang.org/x/crypto/ripemd160
func main() {
var publicKey string = "2e834140fd66cf87b254a693a2c7862c819217b676d3943267156625e816ec6f"
pubByte, _ := hex.DecodeString(publicKey)
hash1 := sha3.Sum256(pubByte)
rip := ripemd160.New()
_, _ = io.WriteString(rip, string(hash1[:]))
hash2 := rip.Sum(nil)
prefix, _ := hex.DecodeString("98")
rawAddress := make([]byte, 20)
copy(rawAddress, hash2)
rawAddress = append(rawAddress[:1], rawAddress[0:]...)
rawAddress[0] = prefix[0]
checksum := sha3.Sum256(rawAddress)
rawAddress = append(rawAddress, checksum[:4]...)
fmt.Println(hex.EncodeToString(rawAddress))
}
実行結果
9826d27e1d0a26ca4e316f901e23e55c8711db20dfd2677696
この段階ではNIP10と一致しているかははっきりとしません。次に行きます。
BASE32
先ほど導出したハッシュ化アドレスをBASE32エンコーディングします。
package main
import (
"encoding/base32"
"encoding/hex"
"fmt"
)
func main() {
address := "9826d27e1d0a26ca4e316f901e23e55c8711db20dfd2677696"
addressByte, _ := hex.DecodeString(address)
encode := base32.StdEncoding.EncodeToString(addressByte)
fmt.Println(encode)
}
実行結果
TATNE7Q5BITMUTRRN6IB4I7FLSDRDWZA37JGO5UW
NIP10と同じものが導出できました。
おわりに
Goに存在する一般的なライブラリ類を使って、秘密鍵から公開鍵とアドレスを導出することができました。
ソースの書き方がメチャクチャなのは許してください。