サルでもわかる?ブロックチェーン復習

ブロックチェーンについて復習します
これを読めばサルでもわかるかも?

1618 views

ウォレットは秘密鍵を管理している

「ウォレット」は暗号資産をもっとるわけではないで
資産に紐づく秘密鍵をもっとる
ウォレットの状態によって、ウォレットを分類することができるわ

  • ホットウォレット:インターネットと接続している
  • コールドうぉれと:インターネットと非接続

ウォレットの安全性と利便性

「ウォレット」が秘密鍵を持っている以上、「安全性」は重要や。
加えて、資産の移動や受取が頻繁故、「利便性」も重要や。
理想は「安全性」「利便性」の両立やけど,,,,難しいのが現状やで。

ホットウォレットの場合

  • 利便性:高い
  • 安全性:比較的低い

インターネットに接続しているため、送金等の資産移動が楽。
インターネットに接続している以上、安全性が問題。
実際、暗号資産の流出事件のほとんどはホットウォレットのハッキングや。

コールドウォレット

  • 利便性:比較的低い
  • 安全性:高い

オフライン管理故、外部からのハッキングは心配不要
オフライン故、送金時にオンラインにするなど、追加処理が必須
=>利便性は比較的低い

こうやって見てみると

なかなか完璧は難しいんやなぁ、、、
そこで「分けて管理する」方法が出てきたんや!!
具体的には

  • 公開鍵やアドレス:ホットウォレットで管理
  • 秘密鍵     :コールドウォレットで管理

とかやな。
これらの方式の命名等は次項で説明するわ。

決定性ウォレットと非決定性ウォレット

非決定性ウォレット

非決定性ウォレットは、ウォレット内で秘密鍵と公開鍵を1対1の関係で生成する仕組みのウォレットや。
公開鍵の数だけ秘密鍵を所持する必要がある。
ウォレットが管理すべき秘密鍵の数がおおくなる。
ランダムに公開鍵を生成するため、「ランダムウォレット」と呼ぶ。

  • 「秘密鍵」をなくした場合、対をなす「公開鍵」は使用不可になる。
  • また、一度紛失したら「秘密鍵」を復旧が極めて困難。

決定性ウォレット

決定性ウォレットは「シード」と呼ばれる1つの乱数を元に複数の鍵を生成する。
親に当たる「秘密鍵」から子供に当たる「秘密鍵」を次々に生成する方式や。
鍵同士に依存関係が生まれ、大元のシードさえバックアップをとれば「秘密鍵」が復元可能やで!!

”シードさえ、バックアップを取れば「秘密鍵」が復元可能”
この性質をさらに追及したのが「HDウォレット(階層的決定性ウォレット)」や

HDウォレット(階層的決定性ウォレット)

概要

HDウォレットは「シード」と呼ばれる乱数から多くの鍵を生成するんや。
決定性ウォレットとの大きな違いは、「一つの親鍵から複数の子鍵を生成する」点や。
これにより、ツリー構造になるんやで。

マスター秘密鍵/マスター公開鍵/チェーンコード

HDウォレットにおいて、最初に生成される「秘密鍵」と「公開鍵」を下記のように記述する。

  • 最初に作成される「秘密鍵」:マスター秘密鍵
  • 最初に作成される「公開鍵」:マスター公開鍵

乱数であるシードから「マスター秘密鍵」/「マスター公開鍵」が生成される過程は以下の通り。

HMAC-SHA512は、「データ」と「キー」のペアで入力し、「512ビット」のハッシュ値を出力する関数やで。
「キー」のほうは固定しているんや。

  • 出力されたビットの前半:「マスター秘密鍵」
  • 出力されたビットの後半:「マスターチェーンコード」

チェーンコードとは、子鍵を生成する際に「キー」として入力するんやで

Pythonで生成してみる

[入力]

import os
import binascii
import hmac
import hashlib
import ecdsa

#シードの作成
seed = os.urandom(32)
#キー
root_key = b"Bitcoin seed"

#512ビットのハッシュ値を作成する処理
def hmac_sha512(data,key_message):
    hash = hmac.new(data,key_message,hashlib.sha512).digest()
    return hash

#秘密鍵から公開鍵を作成する処理
def create_pubkey(private_key):
    publickey = ecdsa.SigningKey.from_string(private_key,curve=ecdsa.SECP256k1).verifying_key.to_string()
    return publickey

#マスター作成。
master = hmac_sha512(seed,root_key)

#前半256ビットでマスター秘密鍵を取得する
master_secretkey = master[:32]

#後半256ビットでマスターチェーンコードを取得する
master_chaincode = master[32:]

#マスター公開鍵作成
master_publickey = create_pubkey(master_secretkey)
master_publickey_integer = int.from_bytes(master_publickey[32:],byteorder="big")

#圧縮公開鍵生成
if master_publickey_integer % 2 ==0:
    master_publickey_x = b"\x02" + master_publickey[:32]
else:
    master_publickey_x = b"\x03" + master_publickey[:32]

print("マスター秘密鍵")
print(binascii.hexlify(master_secretkey))
print("\n")
print("マスターチェーンコード")
print(binascii.hexlify(master_chaincode))
print("\n")
print("マスター公開鍵")
print(binascii.hexlify(master_publickey_x))

[出力]

マスター秘密鍵
b'bf67f78c9f5d838b2f3b1953d56f81324f58818587ced8875dd2563934c827d9'


マスターチェーンコード
b'ccfd590c7ebff8d449740b665073ab3198536aa61af83028451a3ed9737dd4ab'


マスター公開鍵
b'033d9074680b4b352f614ae60fe8f2762009cdae2401048140b24a997e63735325'

子鍵の生成

生成されたチェーンコードは子鍵を生成する際にキーとして「HMAC-SHA512」に入力されるんやで。下は子鍵(子秘密鍵、子公開鍵)を生成するプロセスや。


インデックスは「子鍵」が○○番目を表す。

生成してみる

[入力]

import os
import binascii
import hmac
import hashlib
import ecdsa

#シードの作成
seed = os.urandom(32)
#キー
root_key = b"Bitcoin seed"

#512ビットのハッシュ値を作成する処理
def hmac_sha512(data,key_message):
    hash = hmac.new(data,key_message,hashlib.sha512).digest()
    return hash

#秘密鍵から公開鍵を作成する処理
def create_pubkey(private_key):
    publickey = ecdsa.SigningKey.from_string(private_key,curve=ecdsa.SECP256k1).verifying_key.to_string()
    return publickey

#マスター作成。
master = hmac_sha512(seed,root_key)

#前半256ビットでマスター秘密鍵を取得する
master_secretkey = master[:32]

#後半256ビットでマスターチェーンコードを取得する
master_chaincode = master[32:]

#マスター公開鍵作成
master_publickey = create_pubkey(master_secretkey)
master_publickey_integer = int.from_bytes(master_publickey[32:],byteorder="big")

#圧縮公開鍵生成
if master_publickey_integer % 2 ==0:
    master_publickey_x = b"\x02" + master_publickey[:32]
else:
    master_publickey_x = b"\x03" + master_publickey[:32]

print("マスター秘密鍵")
print(binascii.hexlify(master_secretkey))
print("\n")
print("マスターチェーンコード")
print(binascii.hexlify(master_chaincode))
print("\n")
print("マスター公開鍵")
print(binascii.hexlify(master_publickey_x))

index = 0
index_bytes = index.to_bytes(8,"big")

#データ作成
data = master_publickey_x + index_bytes

result_hmac512 = hmac_sha512(data,master_chaincode)

#親秘密鍵とHMAC-SHA512の結果の前半部を足す
sum_integer = int.from_bytes(master_secretkey,"big") + int.from_bytes(result_hmac512[:32],"big")

p = 2 ** 256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1
#子秘密鍵の作成(マスターの一つ下の階層)
child_secretkey = (sum_integer % p).to_bytes(32,"big")

print("\n")
print("子秘密鍵")
print(binascii.hexlify(child_secretkey))

[出力]

マスター秘密鍵
b'657909799f0698d426f066b26773669ebaa94fc2946ce75087ae8d14120e3a99'


マスターチェーンコード
b'bf661180bc56e9bb84a77b5b101f016ab55743d72fd7d074f17756e9b2219e93'


マスター公開鍵
b'03ac2c75bedcee624b61131dd632489d1363e9f177899d050825f659cca0b14eef'


子秘密鍵
b'4daf171f158af639fde4cefb9f4c8308e9bdc56d0fac3aa150509d4a2b05e043'

拡張鍵

概要

「拡張鍵」とは、秘密鍵や公開鍵にチェーンコードなどの情報をセットした鍵や。
通常の秘密鍵や公開鍵よりも情報面/機能面において拡張されている。

なんであるの?

「HDウォレット」を異なるサーバー間で移動するために導入したんや。
「子鍵」を生成するには、「親鍵」と「チェーンコード」と「インデクス」が必要。
「拡張鍵」ならこれらすべてをカバーできる

強化導出鍵

概要

「強化導出鍵」は子鍵を生成する際に、HMAC-SHA512のデータとして、秘密鍵を利用するんや。
「拡張鍵」で「圧縮公開鍵」を利用する場合、HMAC-SHA512のデータでは「公開鍵」が「親秘密鍵」になる。

Page 7 of 9.

前のページ 次のページ



[添付ファイル]


お問い合わせ

プロフィール

owl

自己紹介

駆け出しエンジニア
だいたいweb系をかじってる
最近ちょとブロックチェーンに興味出てきた

サイト/ブログ

https://github.com/owl0109

ツイッター

@kijiken1