イーサリアムアドレス 〜EIP-55によるチェックサムの導入〜

目次

    はじめに

    今回の連載記事では、イーサリアムの”アドレス”について解説します。読者の皆さんは、自分が保有するイーサリアムアドレスについて気にかけたことはありますでしょうか?イーサリアムアドレスは0xから始まる合計42文字の文字列です。これを正確に記憶している人はなかなかいないのではないでしょうか。

    イーサリアムに限らず仮想通貨におけるアドレスは、銀行口座の口座番号のようなものです。送金・受金の際に、この長いアドレスを1文字でも打ち間違えてしまうと、保有する仮想通貨を失うことになりかねません。このような背景から、打ち間違えた際に誤りを検出する技術や、より覚えやすい文字列に置き換える技術が開発されています。

    連載記事の前半では、イーサリアムアドレス生成の流れと現状取り入れられている誤り検出の技術(Capitals-based checksum)を解説します。

    後半では、イーサリアムのアドレスを国際送金の基準に準じ、より扱いやすくするICAPコードや、覚えやすい文字列に置き換えるENS(Ethereum Name Service)について解説します。

    必要な知識

    本連載記事を読み進めるにあたり、必要となる前提知識について、簡単に解説します。秘密鍵/公開鍵・一方向ハッシュ関数・チェックサムといった用語について既に知っている場合、読み飛ばしていただいて構いません。

    秘密鍵/公開鍵

    暗号技術を用いて、他者に知られたくないコミュニケーションをしたい場合は、内容を暗号化および復号化する必要があります。暗号化と復号化には、それぞれ”鍵”が必要となります。

    暗号化と復号化に同じ鍵を用いる場合は、共通鍵認証と呼ばれています。一方で、イーサリアムをはじめとする仮想通貨においては、暗号化と復号化に異なる鍵を用いる公開鍵認証と呼ばれる暗号方式が利用されています。公開鍵認証自体にはいくつかのアルゴリズムが存在しますが、イーサリアムでは、楕円曲線DSA(ECDSA)を採用しています。

    この公開鍵認証においては、秘密鍵と公開鍵と呼ばれる二つの鍵が存在します。両者の特徴は以下の通りです。

    秘密鍵

    • 他者には知られてはいけない鍵(銀行の暗証番号に相当)
    • ランダムに生成

    公開鍵

    • 他者に知られても良い鍵(銀行の口座番号に相当)
    • 秘密鍵を元にして生成
    • 公開鍵から秘密鍵を推測することは困難

    より詳しく知りたい場合は、ビットコインやイーサリアムの保管、仮想通貨の公開鍵と秘密鍵が参考になります。

    一方向性ハッシュ関数

    ハッシュ関数(要約関数)とは、ある任意の長さのインプットのデータを与えた時に、アウトプットとして固定長の文字列や数値列に変換する関数です。インプットとアウトプットは、それぞれ”メッセージ”と”ハッシュ値”と呼ばれます。このハッシュ関数の重要な特徴として、”一方向性”が挙げられます。

    一方向性とは、メッセージからハッシュ値はアルゴリズムによって計算されるものの、ハッシュ値からメッセージを逆に計算することは非常に困難であることを意味しています。このような特徴から、一方向性ハッシュ関数と呼ばれています。またハッシュ関数にインプットするメッセージが僅かでも変化すると、アウトプットされるハッシュ値が大きく変化することから、データ改竄の検出等に使うことが可能です。

    一方向ハッシュ関数の重要な特徴を以下にまとめます

    • ハッシュ値は固定長の文字列/数値列となる
    • メッセージが僅かでも変化するとハッシュ値は大きく異なる
    • ハッシュ値からメッセージを推測することは非常に困難

    チェックサム

    インターネットをはじめとする情報通信においては、必ずしも送信したデータが正確に受信されるとは限りません。データの一部が誤って受信側に伝わることは頻繁にあることです。そのような状況が生じた時に、受け取ったデータが”誤っている”ことを検出できれば、送信側に対して再度送信を要求するなどの対応を取ることが可能になります。このような誤り検出を可能にする手法の一つが、チェックサムです。

    チェックサムの仕組みを簡略化して説明します。

    例として、”462565”というデータを送信するとします。ただし、”462565”をそのまま送信するのではなく、ある数字Sを追加して誤り検出をできるようにします。

    まず”462565”のそれぞれの桁の合計値をSとして、それを計算します。

     

    S = 4+6+2+5+6+5

      = 28

     

    この合計値 S を送信するデータ”462565”の末尾に付けて送信することにしましょう。送信データは、”462565+S” = “46256528”となります。このチェックサムの仕組みを、受信側が理解していれば、受信したデータの一部が誤っていた場合に誤りを検出することができます(データの合計値と付加したSの間に不一致が生じるため)。
    例えば、チェックサムをつけた状態の正しいデータは”46256528”ですが、何らかの原因によって”46256628”とデータが受信されたとします。

     

    正しいデータ:”46256528”

    誤ったデータ:”46256628”

     

    この時、誤ったデータのチェックサムを取り除き、”462566”の合計値S’を計算してみましょう。

     

    S’ =  4+6+2+5+6+6

      = 29

     

    受信したデータ“46256628”から、チェックサムSは28であることが分かっています。一方で、誤ったデータを元に再度計算して求めたチェックサムS’は29です。この違いから、データに誤りがあることがわかります。

    上記の例では非常に簡略化した例を用いてチェックサムの概念を紹介しました。イーサリアムにおいては、Capitals-based checksumと呼ばれる手法を用いることで、入力したアドレスが誤っているかどうかをその場で判断することができます。Capitals-based checksumについては、後ほど詳しく説明することとします。

    イーサリアムアドレス生成

    生成の手順

    前節において解説した前提知識を用いて、イーサリアムのアドレス生成の手順を説明します。手順は以下の通りです。

    ※以下で用いられるアドレス等の文字列は、Mastering Ethereumから利用しています。

     

    • 秘密鍵 k を生成(32バイト)
      例:k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

     

    • 秘密鍵 k から楕円曲線DSA(ECDSA)を用いて公開鍵 K を生成(64バイト)
      例:K = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

     

    • 公開鍵 K から一方向性ハッシュ関数 Keccak-256を用いてハッシュ値を計算(32バイト)

       例:Keccak256(K) = 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9

     

    • 先頭12バイトの文字を消去し20バイトのイーサリアムアドレスを取得

       例:001d3f1ef827552ae1114027bd3ecf1f086ba0f9

     

    • アドレスが16進数であることを示すために 接頭辞”0x”をアドレスに付加

       例:0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

     

    さてこのようにして得られるイーサリアムアドレスは、HEX(16進数)形式のアドレスと呼ばれています。HEX形式のアドレス生成においては、チェックサムを付加するステップはありません。つまり1文字でもアドレスを打ち間違えた場合には、誤りを検出することができず、ETHを失うことになります。

    イーサリアムがチェックサムを持たない理由

    イーサリアムのアドレスがチェックサムを持たない理由として、将来的にアドレスをより可読性の高いネーム形式(ENS: Ethereum Name Service)に移行するためだと言われています。ネーム形式とは、”consensysmediajapan.eth”のような任意の文字列が、あるHEX形式のアドレスに対応している形式です。ユーザーはHEX形式のアドレスを利用する代わりに、より可読性が高く、記憶のしやすい文字列を使えるようになります。これは現在のインターネットのURLのドメインに相当する概念です。

    加えて、イーサリアムアドレスはICAP(Inter exchange Client Address Protocol)形式のアドレスといったフォーマットも検討されています。このICAP形式のアドレスは、デフォルトでチェックサムが付加されていることから、誤りを検出することが可能になっています。

    上述のENSとICAPについては、連載の後半で詳しく説明します。

    EIP-55

    イーサリアムはICAP形式を用いることで、誤り検出が可能になると述べました。しかしICAPへの移行はあまり進んでおらず、多くのユーザー、取引所、ウォレットがHEX形式のアドレスを利用しているのが現状です。

    しかしICAP形式が広まるまでHEX形式のイーサリアムアドレスの誤り検出ができないのは大きな問題です。そこで2016年1月にイーサリアム創設者のVitalik Buterin氏が提案したのが、Capitals-based checksumと呼ばれる誤り検出方法です。これはEIP-55において議論され、最終的に正式に採択されています。

    Capitals-based checksumとは

    Capitals-based checksumとは、HEX形式アドレスのローマ字の小文字を、ある一定の手順によって大文字に置き換えることで、誤り検出の機能を持たすことが可能なチェックサムです。変換されたアドレスは大文字・小文字が混在していますが、小文字のみのHEX形式アドレスと下位互換性があります。

    つまりCapitals-based checksumに対応していない取引所やウォレットおいて、Capitals-based checksumに基づいて変換されたアドレスを用いても何も問題は生じません。

    先ほどアドレス生成の流れで説明したアドレスをCapitals-based checksumを用いて変化すると以下のように変換されます。ローマ字の一部が大文字に変換されています。

    変換前:0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
    変換後:0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

    自分のイーサリアムアドレスを取引所やウォレットで確認してみましょう。おそらく大文字と小文字が混在したアドレスが表示されているのではないでしょうか?これはCapitals-based checksumによって誤り検出を可能にした形式のHEXアドレスなのです。

    Capitals-based checksumの仕組み

    Capitals-based checksumによってアドレスを変換する方法と誤りを検出する方法を解説します。

    アドレス変換方法

    • 変換前のイーサリアムアドレスから接頭辞である”0x”を削除し、一方向性ハッシュ関数Keccak-256を計算してハッシュ値を得ます。

      ハッシュ値 = Keccak-256(“イーサリアムアドレス”)

      ハッシュ値 = Keccak-256("001d3f1ef827552ae1114027bd3ecf1f086ba0f9")
      = 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1

     

    • アドレスのローマ字部分に対応するハッシュ値の値が、16進数で8以上の場合(8,9,A,B,C,D,E,F)は、アドレスのローマ字の小文字を大文字にします。

     

    表1:ハッシュ値と変換後アドレスの関係

    表1にアドレスとハッシュ値の先頭10文字を示しました。アドレスの4文字目はローマ字の”d”です。対応するハッシュ値は6ですので、8以下ですので大文字には変換しません。次にアドレスの6文字目を考えてみましょう。対応するハッシュ値はcですので、これは16進数では8以上の値です。よってアドレスのローマ字を大文字に変換します。この手順によって、アドレスの全てのローマ字を大文字に変換するかを確認します。この際、比較されるハッシュ値は先頭20バイト(40文字)のみです。これはアドレスの長さが20バイト(40文字)であるためです。

    誤り検出方法

    次に誤り検出の方法について説明します。今、変換されたアドレスの一部を誤ってウォレットにタイプしたとしましょう。最後から2文字目”F”を誤って”E”とタイプしてしまいました。

     

    正しいアドレス:0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

    誤ったアドレス:0x001d3F1ef827552Ae1114027BD3ECF1f086bA0E9

     

    誤ったアドレス(を全て小文字に置き換えて)の再度ハッシュ値を計算します。使用する一方向ハッシュ関数は、アドレス変換時と同じくKeccak-256です。

     

    ハッシュ値(誤)  = Keccak-256(”誤ったアドレス”)



    ハッシュ値(誤) = Keccak-256( "001d3f1ef827552ae11114027bd3ecf1f086ba0e9")

    = 5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927

     

    このハッシュ値(誤)を、正しいアドレスの場合のハッシュ値(正)と比較してみます。

     

    ハッシュ値(正):23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1

     

    ハッシュ値(誤):5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927

     

    たった1値文字のアドレス違いから、全く異なるハッシュ値が得られました。このハッシュ関数の特性が誤り検出をする際のキーポイントとなります。

    表2:アドレスの入力を誤った場合のハッシュ値(誤)と変換後アドレス

    誤ったアドレスに基づいて得られたハッシュ値(誤)を元にして、もう一度元のアドレスの大文字小文字を変換しました。表1と表2の変換後アドレスを比較してみましょう。先ほどまでは小文字であったdが大文字に変換されていることがわかります(4文字目)。他にも大文字であったFが小文字に(6文字目)、小文字であったeが大文字(8文字目)などに変換されてしまっています。

    上記の例に示したように、正しくCapitals-based checksumによって変換さえれていたアドレスを1文字でも打ち間違えると、元のアドレスとは異なった位置のローマ字が大文字・小文字に変換されてしまいます。

    この違いを検出することで、入力されたアドレスに誤りがあることを示すことができます。Capitals-based checksumは99.986%の精度で誤りを検出できるとされています。また実装も簡単なことから、現状ではイーサリアムアドレスのチェックサムとして活用されています。

    まとめ

    イーサリアムアドレスに関する連載の前半では、アドレス生成の流れとCapitals-based checksumを利用したアドレスの誤り検出について説明しました。連載の後半では、ICAPやENSといった将来的なイーサリアムのアドレスの進展について解説します。

    コメントする

    メールアドレスが公開されることはありません。