LoginSignup
2
1

More than 3 years have passed since last update.

GoでEd25519+SHA256のアドレス導出してみる(Symbol,Catapult,RC5)

Last updated at Posted at 2020-03-26

はじめに

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によると、次の手順が必要です。

  1. 公開鍵をSHA3-256する
  2. それをRIPEMD160する
  3. ネットワークIDを付加する
  4. それをSHA3-256して先頭4バイトを取得する
  5. 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に存在する一般的なライブラリ類を使って、秘密鍵から公開鍵とアドレスを導出することができました。

ソースの書き方がメチャクチャなのは許してください。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1