公開鍵・秘密鍵をPythonで生成してみよう

公開鍵暗号方式暗号化と復号化で異なる鍵を用いる暗号方式で、ビットコインのブロックチェーンにおいて様々な場面に利用されています。

公開鍵暗号方式とは

公開鍵暗号方式では「秘密鍵」と「公開鍵」の2種類が存在します。

公開鍵暗号方式

秘密鍵とは自分だけが持っていて他人に教えてはいけない鍵で、公開鍵は他人に公開している鍵です。情報の暗号化・復号化のプロセスは以下のようになります。

まず情報の送信者は受信者の公開鍵で使って暗号化します。そして受信者は送信された情報を自分の秘密鍵で復号化することで中身を確認することができます。

公開鍵暗号方式は鍵を他者に配送する手間がないメリットがある一方、暗号化や復号化の処理が複雑で高速化が難しいというデメリットがあります。

公開鍵・秘密鍵の作り方

それでは公開鍵・秘密鍵が実際にどのように生成されるかをPythonを使って実装してみましょう。

基本的に公開鍵は秘密鍵を元に暗号化されて生成されています。

公開鍵・秘密鍵

秘密鍵は乱数

秘密鍵は乱数(ビットコインでは1〜2256までの整数)によって生成されています。ブロックチェーンにおいて秘密鍵とは銀行口座のパスワードのようなものであるため乱数生成のランダムさには細心の注意が払われています。

Pythonではosとcodecsを利用して秘密鍵を生成することができます。

import os
import codecs

private_key = os.urandom(32)
private_key_hex = codecs.encode(private_key, 'hex')

print(private_key)
#=> b'(L\xc7\x11\x05,\xc6L\x16D\xcb\xed\x8f\x84\xa6\xca\xc9#\x82\xf63\x9b\xa1\xffo\xc9\xe6\xb1\xf7]\xe2\xb3'
print(private_key_hex)
#=> b'284cc711052cc64c1644cbed8f84a6cac92382f6339ba1ff6fc9e6b1f75de2b3'

private_keyでは32バイトの乱数を生成し、private_key_hexは秘密鍵の可読性を高めるためにバイナリデータを16進数に変換しています。

公開鍵を楕円曲線暗合から生成する

公開鍵は乱数から生成した秘密鍵を楕円曲線暗号という高度な暗号技術によって暗号化することで生成されます。

ここでは楕円曲線暗合の詳細は省略しますが、ハッシュ関数と同様に出力結果(公開鍵)から入力(秘密鍵)を推測できない仕組みとなっています。

楕円曲線暗合はPythonではecdsaというサードパーティのライブラリを使って暗号化することができます。ecdsaとは楕円曲線暗合(Elliptic Curve Digital Signature Algorithm)の頭文字をとっています。

import os
import codecs
from ecdsa import NIST256p
from ecdsa import SigningKey


private_key = os.urandom(32)
private_key_hex = codecs.encode(private_key, 'hex')
public_key = SigningKey.from_string(private_key, curve=NIST256p).to_string()
public_key_hex = codecs.encode(public_key, 'hex')

print(private_key_hex)
#=> b'34623bac3222a48a0e2fb94999f72bf8db0f567c62a76908ae075b8ef1de8240'
print(public_key_hex)
#=> b'728d657eabe4ae79c16e1d09efa104aa42c7b23ff5bdb95ae3f1d0688979d6ff'

このうち

public_key = SigningKey.from_string(private_key, curve=NIST256p).to_string()

の部分で公開鍵を生成しています。’NIST256p’という楕円曲線をつかって秘密鍵から公開鍵を生成しているという理解で十分です。

このようにしてブロックチェーンの公開鍵・秘密鍵は乱数と楕円曲線暗合を用いて生成されています。

コメント

タイトルとURLをコピーしました