こんにちは、えたろうです。
「少しだけ易しいMastering Bitcoin」を一通り読んだ方は、Bitcoinの仕組みはだいたい理解できたかと思います。
Bitcoinでブロックチェーンの基本を理解した後、次のステップはやはりEthereumの理解ですよね。
- 「Bitcoinの仕組みはだいたい分かった!ブロックチェーンすげぇ!」という方
- 「Ethereumでスマートコントラクトが実現する云々」「Ethereum上で Dappsを作る云々」というのはよく聞くけど、実際Ethereumってどう動いてるの?という方
を対象にして懇切丁寧に書いて行きます。
第3回では「Ethereumの鍵・addressの生成方法とwalletについて理解する」ことを目標にします。
「少しだけ易しいMastering Bitcoin 第4章」のEthereum版だと思って読んでください。
秘密鍵→公開鍵→Address
Ethereumの「秘密鍵→公開鍵→Ethereum Address」の作成方法はBitcoinのそれとほとんど似通っており、以下の図のような手順で行われます。
①
256bit (32byte) の乱数を生成し、それを秘密鍵とします。(当然ですが、秘密鍵は絶対に秘匿すべき鍵なので、暗号学的に安全な乱数生成器を用いて、オフラインで生成します)
例:秘密鍵k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
②
秘密鍵kを楕円曲線のスカラー倍算にかけ、その結果として得た座標 (x, y) のx座標とy座標をくっつけたものを64byteの公開鍵とします。
(「公開鍵」として扱う場合には以下の式のように、それに接頭辞 " 04 " を付与して、65byteの公開鍵としますが、「アドレスを生成するための公開鍵」としてアドレス生成の1過程で使用する場合には04をprefixにはしません。)
ちなみにEthereumはBitcoinと同じsecp256k1という楕円曲線を使用しています。
例:K = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0
③
公開鍵Kを一方向性ハッシュ関数である Keccak-256関数に通して32byteのハッシュ値を算出します。
例:Keccak256(K) = 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9
④
③の後ろから20byteを取り出し、この数字列が16進数であることを示す0xを接頭辞として付与し、Ethereum Addressとします。
例:Ethereum Address = 0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
このような手順で生成されたEthereum Addressは HEX形式(Hexadecimal:16進数)のAdressと呼ばれます。
気づいた方も多いかと思いますが、このHEX形式のEthereum AddressにはCheck Sumが付与されていません。(BitcoinのアドレスにはCheck Sumが付与されていました)
つまり、送金などの際にEthereum Addressを打ち間違えると、その打ち間違えを検知することができず、送金額分のEthereumが消滅してしまうことになります。
EthereumのAddressがcheck sumを持たない理由は、そもそもHEX形式のAddressは読みに食い・覚えにくいものであるため、将来的にAddressをより可読性の高いENS: Ethereum Name Serviceというネーム形式に移行するためだと言われています。
これは、簡単にいうと”etarou.work.eth”のような任意の文字列が、Ethereumのアドレスに1:1で対応している形式です。これは現在のWebでいう「個別のserverのIPアドレスがドメインに1:1で対応しており、ユーザーは読みやすくて覚えやすいURL使ってサーバーにアクセスできる」のに相当します。
これによってユーザーは読みづらいHEX形式のアドレスを利用する代わりに、記憶のしやすい文字列をAddressとして使えるようになるのです。
※ Ethereumで使用されているハッシュ関数はKeccak-256という関数であると説明しました。説明しました。
実は、Ethereumのソースコード内ではハッシュ関数がSHA3と書かれていることが多いのですが、EthereumはNIST標準FIPS-202 SHA-3を使用してはおらず、オリジナルのKeccak-256を使用していることに注意する必要があります。
Ethereumが開発されていた当初、Ethereumはハッシュ関数としてNIST標準FIPS-202 SHA-3を使用する予定だったのですが、その時にちょうど有名な告発者であるスノーデンが「NISTが不正に乱数生成器のランダム性を弱めている」という告発をしたことによって、NISTにおいてSHA3の標準化が遅れてしまいました。
そのため、EthereumはSHA3が標準化されるのを待つことができず、オリジナル実装のKeccak-256を使用することを決め、実装したのです。
ハッシュ関数がEthereumオリジナル実装のものなのか、NIST標準のものなのかを判断する方法は、空文字列を引数に渡して、出力結果を見ることです。
それぞれ以下のような出力になります。
Keccak256("")=
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
SHA3("")=
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
現在Ethereumでは、ソースコード内のSHA3と書かれている部分を紛らわしいのでKeccak-256に変えようという動きもあります。
Capitals-Based Checksum
「EthereumはENS(Ethereum Name Service)にすぐ移行するからCheck Sumなんて要らねーぜえ!」と調子に乗ったは良いものの、ENSの開発が予想以上に遅かったため、「あれ、これ当分はCheck Sum無いと送り間違えの被害どんどん大きくなるやん!」ということになりました。
Check Sumがデフォルトで付与されるEthereum Addressの生成方法であるICAP(Inter exchange Client Address Protocol)形式が提案されましたが、このICAP形式へは移行が必要で、ほとんどのUser、ウォレットや取引所が旧来のHEX形式のEthereum Addressを利用し、ICAPはなかなか広まりませんでした。(ICAPに関しては後述)
そこで「HEX形式のAddressに互換性を持ったままチェックサムを付与できる」Capitals-based checksumという打ち間違え検出の方法がEIP55で提案されました。
GitHubでCapitals-based checksumのコードを見ることができます。
Capitals-based checksumとは以下の例のように「HEX形式のAddressの英文字の一部を大文字に変換する」という処理でチェックサムを付与します。
変換前:0x001d3f1ef858377ae7329997bd3ecf1f324ba0f9
変換後:0x001d3F1ef858377Ae7329997BD3ECF1f324bA0F9
HEX形式では英文字の大文字と小文字を区別しないので、このように変換したとしても旧来のHEX形式で動いているウォレットや取引所で問題なく利用することができます。
Capitals-Based Checksumの仕組み
Capitals-Based Checksumを付与するためには上記の図のように変換します。
・HEX形式のEthereum Address = 001d3f1ef827552ae1114027bd3ecf1f086ba0f9
・Keccak-256("001d3f1ef827552ae1114027bd3ecf1f086ba0f9")
= 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1
だったとすると、
それら2つを左揃えで比較して見て、ハッシュ値のその桁の値が8以上(8,9,A,B,C,D,E,F)担っている英文字を大文字に変換し、
変換後のアドレス = 0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
となります。
このような変換を施したアドレスを使用することによって、アドレスの打ち間違えを検出することができます。
具体的には、以下の手順で打ち間違いが検出されます。
⓪
あるウォレットからあなたがEthereumを送金する際に、送金先アドレス欄にもし上記の
0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
というEthereumアドレスを間違えて
0x001d3F1ef827552Qe1114027BD3ECF1f086bA0F9
と打ってしまったとしましょう。
①
ウォレットは、打ち込まれたCapitals-Based Checksumが付与されているEthreumアドレスの英字部分を以下のように全て小文字にします。
0x001d3f1ef827552qe1114027bd3ecf1f086ba0f9
②
ウォレットは①をCapitals-Based Checksum変換します。(①から接頭辞0xを取り除き、Keccak256ハッシュ関数に通した結果と比較して、ハッシュ値が8以上の桁数の英字を大文字にしていきます)
ここでアドレスが打ち間違えである場合、元々の正しいアドレス
0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
がCapitals-Based Checksum変換された時とは全く違うハッシュ値が出力されます。
そのため、もちろん大文字になる部分が異なるので変換の結果として得られるアドレスが打ち込んだアドレスである
0x001d3F1ef827552Qe1114027BD3ECF1f086bA0F9
とは全く異なるものになってしまいます。
③
これによってウォレットは打ち込まれたアドレスが「正常にCapitals-Based Checksum変換されたものでは無い」、つまり、打ち間違えであると判断することができます。
このような仕組みで成り立つCapitals-based checksumは99.986%の精度で誤りを検出できるとされており、githubを見ても分かる通り実装も簡単なことから、Ethereum Addressのチェックサムとして広く活用されています。
ICAP(Inter exchange Client Address Protocol)
ICAP(Inter exchange Client Address Protocol)は、
・チェックサムを付与してEthereum Addressの打ち間違いを検出可能に
・IBAN(International Bank Account Number)という現在の国際送金の送金先の表示規格に準じてEthereumアドレスを表記する
方法として提案されました。
※ IBAN形式とは
ZZ XX AAA BBB CCCCCCCCCCCC
ZZ:国コード
XX : チェックサム
AAA : 銀行コード
BBB : 支店コード
CCCCCCCCCCCC : 口座番号
という最大34文字の形式で送金先を表す規格です。
ICAPには大きく以下の3つの種類があります。
Direct ICAPコード
Ethereum上のアドレスはIBANの国コードの部分にXE (Extended Ethereum)を入れます。
それに続けてチェックサムとして2つの数字を入れ、その後に元々のHEX形式のEthereum Addressをbig-endian方式で変換したものをアドレスとしてくっつけます。
このようにして作成する最大34文字のアドレスがDirect ICAPコードです。
例: XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJDA(34文字)
Basic ICAPコード
チェックサム無しで、IBAN形式にも則っていないICAPコードです。
意味がないためほとんど使用されていません。
例: XE18CHDJBPLTBCJ03FE9O2NS0BPOJVQCU2P (35文字).
Indirect ICAPコード
Direct ICAPコードよりも、より人間が読みやすい形式にしたアドレス形式です。
最初の4桁はDirect ICAPコードと同じように XE + チェックサムで構成されますが、それ以降アドレスを示す部分が、「資産の種類を示す3文字」「4文字のネームーサービス名」「そして9文字のアカウント名」と区分分けされているため、人間に読みやすいアドレス表示形式となっています。
例: XE ## ETH XNAK ITOETAROU(20文字)
しかし、このIndirect ICAPコード表示形式だと、実際に送金しようとした時に本当のEthereum AddressであるHEX形式のアドレスをこのIndirect ICAPアドレスからは求めることができません。
つまり、 「ITOETAROUに対応するHEX形式アドレスはこれです」と教えてくれるデータベースが必要ということになります。
このような種類を持つICAP方式ですが、「そもそも旧来のHEX形式と互換性がないので移行が必要」という点からあまり導入が進んでいません。
また、Indirect ICAP形式は、「人間にわかりやすいアドレス形式にする」という取り組みは良いのですが、対応アドレスを保持しておくデータベースをどう作成してどこに保存するのかという問題があり、開発があまり進んでいない状況です。
ENS(Ethereum Name Service)
ENS(Ethereum Name Service)は、Ethereum Addressに対して任意の文字列を対応させて、送金時にその文字列を使って送金することができるようにする技術です。
インターネットでは、私たちは世界のどこかにあるWebサーバーにアクセスしてWebページを見たり、サービスを利用したりしている訳ですが、Webサーバーにアクセスするのには本来はIPアドレス(0.0.0.0 〜 255.255.255.255)という数字の羅列をブラウザに打ち込まなければなりません。
しかし、DNS (Domain Name Server)というドメイン名とIPアドレスを紐づける仕組みが存在することによって、私たちはブラウザにURLを打ち込むことでWebサーバーにアクセスすることができるのです。
これと同じことをEthereum ネットワーク上で実現するのがENSだと思ってください。
具体的には
0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
のようなHEX形式のEthereum Addressを
etarou.work.eth
のような可読性のある形で扱うことができます。
(設定する任意の文字列は7文字以上である必要があり、CheckSumはありません)
ENSの取得
インターネットのドメインと同じようにENSも二つ同じものが存在してはならず、そのため、人気のある文字列は多くの人が求め、争奪戦となります。
ENSの取得申請は、My Ether Walletなどのウォレットから誰でも行うことができます。
ENSの取得はオークション形式で、以下のような手順で行われます。
①
取得したい任意のドメイン名を選択決め、それと紐付けるイーサリアムアドレスを選択します。そして、自分がオークションで支払える最大額のETH = 入札額を指定します。(この時、オークションのトランザクションを処理するために0.01ETHが別に必要です。)
②
オークションが開始されます。
開始から3日間はそのドメインが欲しいユーザーの名前と入札額は公開されません。
③
開始から3日経った後の2日間は、入札者は自分の入札額を任意で公開することができます。入札額を公開した場合は、もし落札に成功したら、落札者は2番目に高い入札額と自分の入札額の差額の返金を受けることができます。
④
合計5日間のオークションが終了すると、落札額分のETHがロックされることで、ドメインが落札者のものとして確定します。
③で入札額を公開していた場合は、ここで差額の返金を受けることができます。
また、もし入札者が自分だけだった場合には、トランザクションの処理にかかる0.01ETH以外の全てのETHが返金されます。
このような手順で落札したドメイン名は1年間所有権が有効になります。
落札から1年が経過した時点で、落札者は所有権を放棄すると、オークションによってロックされていたETHが返却されます。
もちろん1年以上ドメイン名を所有できるような機能も開発されています。
過去に落札されたドメインの中には、
exchange.eth:6,660ETH や foundation.eth:300ETH
など人気があって高額で落札されたものも多くあります。
Wallet
少しだけ易しいMastering Bitcoin 第4章でも学んだ通り、暗号通貨のウォレットとは「実際にその中にBitcoinやEtherを持つのではなく、あくまでユーザーの秘密鍵を保持するキーホルダーのようなもの」でした。
ウォレットにおいて最も重要な部分は「秘密鍵をどのように保持するか」という部分なので、そこに関してはEthereumで使用されるウォレットの仕組みもBitcoinで使用されるウォレットと全く同じです。
ただ、もちろんウォレットが行う処理などは少しずつ異なります。
Bitcoinのウォレットと比較したEtherumのウォレットの特徴は以下の通りです。
①
Bitcoinウォレットは自分のBitcoinアドレスに紐づくUTXOを集計することで残高参照していたが、Ethereumのウォレットは自分のEOAアドレスのBalanceを参照して残高参照する。
②
Bitcoinウォレットは1つのSeedからBitcoinアドレスをトランザクションの度に生成していたが、EtherumのウォレットはEOAアカウントアドレスをトランザクションの度に生成する。
(トランザクションの度にaddressを変更するのはプライバシー保護のためだが、EthereumではEOAにNonceというデータカラムがあり、一人の人が1つのEOAを使い続けることを想定していると考えられる。トランザクションの度にEOAアカウントを新しく生成しないという場合も多くあると思う)
③
BitcoinのウォレットとEthereumのウォレットでは生成するトランザクションの構造がもちろん異なる。
(「【第4回】Bitcoinを通じて理解するEthereum - TransactionとBlock」で解説 )
④
Ethereumのウォレットは多くの場合、ERC20規格に従ったトークンを扱えるようになっている。この場合、そのトークンコントラクトアカウントに残高参照をしたり、トランザクションを送ったりする機能が実装されている。
(「【第7回】Bitcoinを通じて理解するEthereum - 独自トークンとは」で解説 )
※秘密鍵を効率よくセキュアに保持するための技術と仕組みについては「少しだけ易しいMastering Bitcoin 第4章」で全て解説してありますので、そちらを参照して下さい。
第3回では「Ethereumの鍵・addressの生成方法とwalletについて理解する」ことを目標にしてきました。
BitcoinとEthereumの「秘密鍵・公開鍵・Address・Wallet」の役割は基本的に同じですが、その生成方法などにある細かな技術的な違いを理解して頂けたかと思います。
次回は「Ethereumのトランザクション・ブロックの構造とトランザクション実行の流れを深く理解する」ことを目標に書いていきます。
続き↓
0コメント