ブロックチェーン学習ロードマップ

ブロックチェーンにおけるアドレス生成の技術:公開鍵暗号、ハッシュ化、HDウォレットの仕組み

Tags: ブロックチェーン, アドレス生成, 公開鍵暗号, ハッシュ関数, HDウォレット, 暗号技術, 秘密鍵, 公開鍵

はじめに

ブロックチェーン技術において、資産の送受信やスマートコントラクトとのインタラクションを行う際には、「アドレス」が不可欠です。アドレスは、ブロックチェーン上の特定の場所を指し示す識別子であり、Web開発におけるユーザーIDやメールアドレスのように機能しますが、その生成プロセスは公開鍵暗号に基づいた独自の技術によって実現されています。

本記事では、ブロックチェーンアドレスがどのようにして技術的に生成されるのか、その基礎となる公開鍵暗号から、アドレスへの変換プロセス、そして実用的なアドレス管理に用いられるHDウォレット(Hierarchical Deterministic Wallet)の仕組みまでを掘り下げて解説します。

ブロックチェーンアドレス生成の基礎:公開鍵暗号ペア

ブロックチェーンアドレスの生成は、まず暗号技術における公開鍵暗号ペアの生成から始まります。このペアは、秘密鍵(Private Key)公開鍵(Public Key)から構成されます。

秘密鍵は、その名の通り、所有者だけが知っているべき情報です。これは、デジタル署名を作成するために使用され、ブロックチェーン上での資産の移動やスマートコントラクトの実行など、トランザクションに正当な所有者であることを証明するために不可欠です。秘密鍵を失うことは、その秘密鍵に対応するアドレスに紐づく資産へのアクセス権を失うことを意味します。

公開鍵は、秘密鍵から数学的に導出される情報で、誰でも知ることができます。公開鍵は、送金先のアドレスを生成するための元情報となります。また、秘密鍵で作成されたデジタル署名が、対応する公開鍵によって検証可能であることを保証します。

ビットコインやイーサリアムをはじめ、多くのブロックチェーンでは、この鍵ペアの生成に楕円曲線暗号(ECC: Elliptic Curve Cryptography)が用いられています。特にビットコインではsecp256k1という特定の楕円曲線パラメータが採用されています。ECCを用いることで、比較的小さな鍵サイズで高いセキュリティ強度を実現しています。

技術的には、秘密鍵は非常に大きなランダムな整数として生成されます。この秘密鍵を、定義された楕円曲線上の特定の点(G)に対してスカラー倍算という演算を適用することで、対応する公開鍵(Q = dG, dは秘密鍵、Gはベースポイント)が計算されます。この計算は一方向性があり、公開鍵から秘密鍵を効率的に逆算することは極めて困難です。

公開鍵からアドレスへの変換プロセス

生成された公開鍵は、多くの場合、そのままアドレスとして使用されるわけではありません。セキュリティやアドレスの長さを最適化するために、いくつかの段階を経てアドレスに変換されます。このプロセスには、主にハッシュ関数が利用されます。

一般的な変換プロセスは以下のようになります(ブロックチェーンの種類によって詳細は異なります)。

  1. 公開鍵の取得: まず、秘密鍵から圧縮または非圧縮形式の公開鍵を計算します。
  2. ハッシュ化(1回目): 公開鍵を特定のハッシュ関数でハッシュ化します。ビットコインではSHA-256が使用されます。 H1 = SHA-256(公開鍵)
  3. ハッシュ化(2回目): 1回目のハッシュ結果を、別のハッシュ関数(ビットコインではRIPEMD-160)でさらにハッシュ化します。この結果が「公開鍵ハッシュ」または「ハッシュ化された公開鍵」と呼ばれるものです。 H2 = RIPEMD-160(H1) この2段階のハッシュ化により、元の公開鍵を特定されにくくし、アドレスの長さを短縮する効果があります。
  4. ネットワークバイトとチェックサムの付加: ハッシュ化された公開鍵の前に、そのアドレスがどのネットワーク(メインネット、テストネットなど)用かを示すバージョンバイト(ネットワークバイト)を付加します。さらに、そのデータ全体(バージョンバイト + ハッシュ化された公開鍵)のハッシュ値を計算し、その最初の数バイトをチェックサムとしてデータの末尾に付加します。チェックサムは、アドレス入力時のタイプミスなどによるエラーを検出するために使用されます。 データ = バージョンバイト + H2 チェックサム = SHA-256(SHA-256(データ)) の最初の4バイト エンコード対象 = データ + チェックサム
  5. エンコード: 最後に、このエンコード対象データを特定の方法(ビットコインではBase58Checkエンコード)で文字列に変換します。Base58Checkは、数字の'0'、大文字の'I'、大文字の'O'、小文字の'l'など、視覚的に紛らわしい文字を除外した58種類の英数字を使用するエンコード方式です。

このプロセスを経て、最終的なブロックチェーンアドレス文字列が生成されます。

イーサリアムのアドレス生成プロセスは少し異なります。イーサリアムでは、公開鍵(非圧縮形式)のKeccak-256ハッシュを取り、そのハッシュ値の最後の20バイトをアドレスとして使用します。

# イメージ(ビットコインの場合)
# 秘密鍵(ランダムな256ビット整数)
private_key = generate_random_number(256)

# 秘密鍵から公開鍵を計算(ECC)
public_key = calculate_public_key(private_key) # 例: 65バイト (0x04 + X座標 + Y座標)

# 公開鍵をハッシュ化 (SHA-256 -> RIPEMD-160)
hashed_public_key = ripemd160(sha256(public_key)) # 例: 20バイト

# ネットワークバイトとチェックサムを追加
version_byte = b'\x00' # メインネットの場合
data_with_version = version_byte + hashed_public_key
checksum = sha256(sha256(data_with_version))[:4]
address_bytes = data_with_version + checksum # 例: 1 + 20 + 4 = 25バイト

# Base58Checkエンコード
address = base58_encode(address_bytes) # 例: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'

階層的決定性ウォレット(HDウォレット)の仕組み

ブロックチェーンアドレスを生成する基本的な仕組みは理解できましたが、実際に多くのユーザーが利用するウォレットは、単一の秘密鍵とアドレスだけを管理しているわけではありません。通常、ウォレットは複数のアドレスを生成・管理します。初期のウォレットでは、複数の秘密鍵を独立して生成・管理していましたが、これはバックアップや管理が煩雑になるという問題がありました。

この問題を解決するために考案されたのが、階層的決定性ウォレット(HDウォレット)です。HDウォレットは、単一のシード(Seed)と呼ばれる短いフレーズ(例えば、12単語や24単語のニーモニックフレーズ)から、無限に近い数の鍵ペア(秘密鍵と公開鍵)を決定論的(Deterministically)かつ階層的(Hierarchical)に導出する仕組みです。

HDウォレットの技術要素

HDウォレットの根幹をなす技術は、主に以下の要素から構成されます。

  1. シード(Seed): HDウォレットのすべての鍵を生成するための唯一の元情報です。通常、ランダムなバイト列から生成され、管理しやすいようにBIP-39で定義された単語リストに基づいたニーモニックフレーズに変換されます。
  2. マスターキーペア: シードから導出される最初の鍵ペアです。これ以降のすべての鍵は、このマスターキーペアと後述するチェーンコードから派生します。
  3. 拡張公開鍵(Extended Public Key, xpub)と拡張秘密鍵(Extended Private Key, xprv): HDウォレットでは、公開鍵と秘密鍵だけでなく、「チェーンコード(Chain Code)」と呼ばれる32バイトの追加情報とセットで管理されます。このセットを「拡張鍵(Extended Key)」と呼びます。
    • 拡張公開鍵 (xpub): 公開鍵 + チェーンコード。これだけで、対応するすべての子公開鍵と子アドレスを導出できます(ただし、対応する秘密鍵なし)。残高監視などに利用できます。
    • 拡張秘密鍵 (xprv): 秘密鍵 + チェーンコード。これがあれば、対応するすべての子秘密鍵、子公開鍵、子アドレスを導出できます。ウォレットの復元にはこれが(またはシード)が必要です。
  4. 鍵導出プロセス: 親の拡張鍵と、子鍵を特定するための「インデックス」という番号を用いて、子となる拡張鍵を決定論的に生成するプロセスです。このプロセスでは、HMAC-SHA512などのハッシュ関数が使用されます。親の秘密鍵とチェーンコード、子インデックスを入力として、子秘密鍵と子チェーンコードを計算します。子公開鍵は子秘密鍵から導出できます。
  5. 導出パス(Derivation Path): 鍵の階層的な構造を示すパス表現です。例えば、m/purpose'/coin_type'/account'/change/address_index のような形式で、特定の用途(purpose)、通貨(coin_type)、アカウント番号(account)、チェーン(change, 例: 外部受信用か内部お釣り用か)、アドレスのインデックス(address_index)を指定して、特定の鍵を導出します。BIP-44などの規格で標準的なパス構造が定義されています。
# イメージ(HDウォレットでの子鍵導出)
# 親の拡張秘密鍵 (親秘密鍵 + 親チェーンコード)
parent_xprv = (parent_private_key, parent_chain_code)

# 子鍵インデックス
child_index = 0

# HMAC-SHA512を使用して子鍵を計算
# データ = 親公開鍵 || 子インデックス (0xFFFFFFFF以下は通常導出、それ以上は強化導出)
# キー = 親チェーンコード
I = hmac_sha512(parent_chain_code, parent_public_key || child_index)

# HMACの結果Iを左右32バイトずつに分割
I_left = I[:32]   # 子秘密鍵の基となる部分
I_right = I[32:]  # 子チェーンコード

# 子秘密鍵 = (親秘密鍵 + I_left) mod 曲線次数
child_private_key = (parent_private_key + integer(I_left)) % curve_order

# 子チェーンコード = I_right
child_chain_code = I_right

# 子拡張秘密鍵 = (child_private_key, child_chain_code)
# 子公開鍵 = calculate_public_key(child_private_key)

# 子拡張公開鍵 = (child_public_key, child_chain_code)

HDウォレットの利点

まとめ

ブロックチェーンにおけるアドレスは、単なるランダムな文字列ではなく、公開鍵暗号とハッシュ化という高度な暗号技術に基づいて生成されています。秘密鍵から公開鍵が導出され、その公開鍵が特定のハッシュ関数を経てアドレスに変換されるプロセスは、ブロックチェーンのセキュリティと整合性を支える重要な要素です。

さらに、実用的なウォレットでは、単一のシードから複数の鍵ペアを効率的かつ決定論的に生成・管理できるHDウォレットの仕組みが広く採用されています。これにより、ユーザーはバックアップやアドレス管理の負担を軽減しつつ、プライバシーに配慮したアドレス運用が可能となっています。

これらの技術的な仕組みを理解することは、ブロックチェーン上の資産管理の原則や、ウォレットがどのように機能しているのかを深く理解するために不可欠です。次のステップとして、これらの鍵ペアがどのようにトランザクションの電子署名に利用され、その署名がどのように検証されるのかといったトピックを学習すると、ブロックチェーンの技術的な全体像がより明確になるでしょう。