暗号通貨eXPerience Chain(XPChain、XPC)、Discord上で使えるウォレットbotやInsightも公開されて、ますます楽しくなってきた。
私は技術系オタクだから、暗号のコードとか見るとちょっと(かなり)わくわくする。
XPC自体の活用アイデアとかはあまり出てこないけど...まあ、まだテストネットなので慌てない慌てない。
ということでテストネットだからこそということで、いろいろ弄って遊び倒す。
ある意味これもXPCの活用(?)かもしれない。
RPCコマンドを使ったrainもどきとかトランザクションの生成→署名→送信あたりはやったので、いよいよウォレットの外(Bitcoin系のライブラリとInsight)でいろいろやっていきたい。
と、その前に、アドレスや秘密鍵の関係を把握しておくことに。
※以下、XPC固有というわけではなく、Bitcoin 0.17~系にほぼ共通のはず(そもそもソースがBitcoinからフォークしてるので、ブロック構造とか使ってる暗号技術とかほほ同じのため)
※あくまで私が弄るために集めた最小限の知識やコードしか書いてないので、必ず他のサイトも参考にすること
※以下、バイト列はhex表記(ef0102dc...等)とする
秘密鍵
BitcoinもXPChainも、(テストネットの)秘密鍵のダンプフォーマットはこんなの。
cXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(52文字の英数)
これはBase58Checkでエンコードされているので、デコードする
$ echo -n cXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | base58 -d | xxd -p -c 38
efXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXPPCCCCCCCC(efから始まる38バイト)
中身は
- 先頭1バイト:バージョン(テストネットは0xEF、メインネットは0x80)
- 続く32バイト:秘密鍵本体
- 1バイト:0x01(圧縮された公開鍵を使うというフラグ)
- 4バイト:チェックサム
ちなみに秘密鍵本体からウォレットに取り込めるダンプフォーマットにするには、チェックサムを除いた34バイトを
$ echo efXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXPP | xxd -p -r | base58 -c
のようにすればOK。
(補足:base58コマンドはpython導入後、pip install base58で入れておく)
公開鍵生成
どんどんいくよー。
秘密鍵から公開鍵(非圧縮)を生成。
302e...とかどこから出てきたの?と思ったけど、まだそこは調べてない。
secp256k1かBitcoinかのパラメータ?
$ openssl ec -inform DER -text -noout -in <(cat <(echo -n "302e0201010420") <(echo -n "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") <(echo -n "a00706052b8104000a") | xxd -r -p) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d '\n' && echo
04XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY(04から始まる65バイト)
長い...。長すぎる!ということで圧縮。
先頭の04を除く64バイトは、前半がx、後半がy。
(この辺、参考資料でxを削るといいつつyを削ってるのでよく分からない)
とにかく、yが偶数(最後のビットが0)だったら02、奇数(最後のビットが1)だったら03を先頭にして、xの値をくっつける。
03XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(33バイト、yが奇数だった場合)
これで公開鍵(圧縮)が準備できた
アドレス生成
アドレスは、公開鍵にsha256かけてripemd160かけて、bech32形式に変換すればOK。
まずはsha256とripemd160。
(1回で強引にやろうとしてダメコードっぽくなってるけど気にしない)
$ echo 03XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | xxd -r -p | openssl sha256 | sed 's/(stdin)=\s//' | xxd -r -p | openssl ripemd160 | sed 's/(stdin)=\s//'
81bc838ef3fb8b1ad6adf3ab0649f7ec5d4fd4f4(20バイト)
何故2回ハッシュをかけてるのかとか、その辺はまだよくわかってない。
そして実は上記のアドレスバイトは実際にテストネットで私が使ってるもの。
あとはこれをbech32に変換すると
txpc1qsx7g8rhnlw93444d7w4svj0ha3w5l4854kmza3
ここに、今絶賛テスト中のXPChain testnetで実際に送金できる。
まあ、テストだから1円にもならないけど、なんとなく符号...もとい富豪気分。
応用
こうやってウォレット外で秘密鍵・公開鍵・アドレスを生成できると、ウォレットではできない(技術的というよりセキュリティ的に?)面白いことができる。
例えば、数学問題の解をバイト列にしたものを秘密鍵としてアドレスまで生成して、アドレスに送金しておく。
数学問題を出題して、一番最初に解けた人がバイト列をダンプフォーマットに変換し、自分のウォレットにインポートして、(別の)自分のアドレスに送れば、賞金ゲット。
...まあ、メインネットでやるとしたら賭博法とか税金とかの問題が出てくるかもしれないけど、今はテストネット。気にせず存分に試せる。
あとは、番外編として、デタラメなbech32アドレスをチェックサム無視してデコードし、再エンコードしてGOXアドレス(誰も秘密鍵を持っていないであろうアドレス)を生成することもできる。
例えば
txpc1q45643755643725465437472456437245cdj36q
txpc1qdustcandustcandustcandustcandusttej9f4
等。
後者のほうに実際に送ってみたトランザクションがこれ→a0d7f32243a45dc253eea61ecbfb2a9afcb93ec11ae5228f287cd5daa6a164d3
冗談抜きでGOXなので、メインネットでは御法度だし、テストネットでもせいぜい数十~数百XPC程度にしておくべき。
総括
- bitcoin系の秘密鍵・公開鍵・アドレスの関係が少し分かった
- 自由に秘密鍵を作れるようになった
- 任意のアドレスを作れるようになった(ただし秘密鍵はない)
- た~のし~♪
- そしてまた夜更かし...今日こそ早く寝ようと思ったのに
- 下不下不
- 文鳥へふへふ
出典、参考(順不同)
- Bech32 Demo
Bitcoinアドレスの生バイト⇔bech32変換
ちなみにこれはwitness非対応版らしく、witness対応&タグをデフォルトでXPChain mainnet用に改造したバージョンを作成。 - How to Generate a Bitcoin Address
手動で鍵静生成、アドレス変換する。実はほぼこれの翻訳 - BIP 173
bech32アドレスの仕様 - What encoding or format is the private key in Dumpprivkey?
秘密鍵ダンプフォーマット
コメント