개인 키를 WIF 형식으로 변환하는 프로세스를 Python으로 구현

9551 단어 파이썬Bitcoin

소개



글꼴로 비트코인이나 블록체인이라는 것이 유행하고 있는 것 같네요. 유행을 늦추지 않게(지금 뭐라든지 말하지 말고 ), 최근비트코인과 블록체인이라는 책을 읽기 시작했습니다.

이 책에서 WIF 형식(Wallet Import Format)이라는 형식이 등장했습니다. 비트코인 지갑은 개인 키를 이 형식으로 처리합니다. 이번에 복습을 겸해 비밀키를 WIF 형식으로 변환하는 처리를 Python으로 구현해 보았습니다.

구현



구체적으로는 Bitcoin Wiki의 Wallet import format 라는 페이지에 쓰여진 내용을 코드에 일으켰습니다.
from base58 import b58encode, b58decode
from binascii import hexlify, unhexlify
from hashlib import sha256
import unittest


def encode_private_key_as_wif(private_key):
  """
  秘密鍵 (16 進数文字列) を WIF 形式に変換する。
  """

  # 先頭の 0x80 は秘密鍵をエンコードする際の version byte を表す。
  key = '80' + private_key
  tmp = key

  # SHA-256 関数を 2 回適用する。
  tmp = sha256(unhexlify(tmp)).hexdigest()
  tmp = sha256(unhexlify(tmp)).hexdigest()

  # 末尾の 8 バイトをチェックサムとする。
  checksum = tmp[0:8]

  wif_private_key = b58encode(unhexlify(key + checksum))

  return wif_private_key


def decode_wif_private_key(wif_private_key):
  """
  秘密鍵 (WIF 形式) を 16 進数文字列に変換する。
  """
  tmp = hexlify(b58decode(wif_private_key)).decode('utf-8')
  # version byte とチェックサムを取り除く。
  private_key = tmp[2:-8]

  # b58decode の代わりに b58decode_check を使う場合
  # tmp = hexlify(b58decode_check(wif_private_key)).decode('utf-8')
  # private_key = tmp[2:]

  return private_key


def verify_checksum(wif_private_key):
  """
  秘密鍵のチェックサムを検証する。
  """
  b58decoded = hexlify(b58decode(wif_private_key)).decode('utf-8')
  tmp = b58decoded[:-8]
  tmp = sha256(unhexlify(tmp)).hexdigest()
  tmp = sha256(unhexlify(tmp)).hexdigest()

  return b58decoded[-8:] == tmp[:8]


class WIFTest(unittest.TestCase):
  """
  WIF 形式に関する関数の動作を検証するための単体テスト。
  検証のための値は https://en.bitcoin.it/wiki/Wallet_import_format から借用している。
  """

  def test_encode_private_key_as_wif(self):
    private_key = '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d'
    wif_private_key = encode_private_key_as_wif(private_key)

    self.assertEqual('5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ', wif_private_key)

  def test_decode_wif_private_key(self):
    wif_private_key = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'
    private_key = decode_wif_private_key(wif_private_key)

    self.assertEqual('0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d', private_key)

  def test_verify_checksum(self):
    valid_wif_private_key = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'
    invalid_wif_private_key = 'SHueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'

    self.assertTrue(verify_checksum(valid_wif_private_key))
    self.assertFalse(verify_checksum(invalid_wif_private_key))


if __name__ == '__main__':
  unittest.main()

이 Python 스크립트를 실행하려면 base58라는 라이브러리가 필요합니다.
$ pip install base58

스크립트를 실행하면 unittest 단위 테스트가 실행됩니다.
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

참고


  • Bitcoin Wiki » Wallet import format
  • 좋은 웹페이지 즐겨찾기