【Python】Python ~ ハッシュ / hashlib ~

■ はじめに

https://dk521123.hatenablog.com/entry/2020/04/01/000000

で扱ったブロックチェーンの技術として使用されるハッシュについて扱う

目次

【1】ハッシュについて
【2】サンプル
 例1:Hello world
 例2:Login with Salt & Stretching
 例3:Login with hashlib.pbkdf2_hmac
 例4:なんちゃってブロックチェーン

【1】ハッシュについて

* 以下の関連記事を参照のこと

ハッシュ / Hash
https://dk521123.hatenablog.com/entry/2022/09/14/000000

【2】サンプル

例1:Hello world

import hashlib

value = 'Hello world' 
hash_value = hashlib.sha256(value.encode("utf8")).hexdigest()
print(hash_value)

print("*********")

hash_value = hashlib.sha512(value.encode("utf8")).hexdigest()
print(hash_value)

出力結果

64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f4c
*********
b7f783baed8297f0db917462184ff4f08e69c2d5e5f79a942600f9725f58ce1f29c18139bf80b06c0fff2bdd34738452ecf40c488c22a7e3d80cdf6f9c1c0d46

例2:Login with Salt & Stretching

import base64
import hashlib
import os

class Authentication():
  def __init__(self):
    self.db = {}
    self.stretching_number = 100000
    self.salt = base64.b64encode(os.urandom(32))

  def save(self, user_name, user_password):
    self.db[user_name] = self.get_digest(user_password)

  def get_digest(self, target_password):
    password = bytes(target_password, 'utf-8')
    # Point1: Salt
    digest = hashlib.sha256(self.salt + password).hexdigest()

    # Point2: Stretching
    for _ in range(self.stretching_number):
      digest = hashlib.sha256(bytes(digest, 'utf-8')).hexdigest()
    return digest

  def is_login(self, user_name, user_password):
    return self.get_digest(user_password) == self.db.get(user_name)

# 呼び出し
auth = Authentication()

user_name = 'user'
user_password = 'password'

auth.save(user_name, user_password)

print(auth.is_login(user_name, user_password)) # True
print(auth.is_login(user_name, 'ssdddd')) # False

例3:Login with hashlib.pbkdf2_hmac

import base64
import hashlib
import os

class Authentication():
  def __init__(self):
    self.db = {}
    self.stretching_number = 100000
    self.salt = base64.b64encode(os.urandom(32))

  def save(self, user_name, user_password):
    self.db[user_name] = self.get_digest(user_password)

  def get_digest(self, target_password):
    # 例2とは、ここだけ違うだけ
    return hashlib.pbkdf2_hmac(
      'sha256',
      bytes(target_password, 'utf-8'),
      self.salt,
      self.stretching_number
    )

  def is_login(self, user_name, user_password):
    return self.get_digest(user_password) == self.db.get(user_name)

# 呼び出し
auth = Authentication()

user_name = 'user'
user_password = 'password'

auth.save(user_name, user_password)

print(auth.is_login(user_name, user_password))
print(auth.is_login(user_name, 'ssdddd'))

例4:なんちゃってブロックチェーン

import time
import json
import hashlib

class SimpleBlockChain(object):
  # コンストラクタ
  def __init__(self):
    self.chain = []
    self.create_block("init_hash", "")

  def calculate_hash(self, value):
    return hashlib.sha256(value.encode()).hexdigest()

  def create_block(self, previous_hash, source_data):
    data_hash = self.calculate_hash(json.dumps(source_data))
    block = {
      "version": "1.0.0",
      "timestamp": time.time(),
      "previous_hash": previous_hash,
      "data_hash": data_hash,
      "data": source_data
    }
    self.chain.append(block)
    return block

  def append(self, source_data):
    previous_block = self.chain[len(self.chain) - 1]
    previous_hash = previous_block["data_hash"]
    self.create_block(previous_hash, source_data)

  def dump(self):
    for i, block in enumerate(self.chain):
      print(f'{"="*25} Block - [{i}] {"="*25}')
      for key, value in block.items():
        print(f'{key:15} : {value}')
      print(f'{"="*65}')

if __name__ == '__main__':
  print("block_chain1 ***************")
  block_chain1 = SimpleBlockChain()
  block_chain1.append({"a": 100, "b": 200 })
  block_chain1.append({"a": 150, "b": 300 })
  block_chain1.dump()
  print("block_chain2 ***************")
  block_chain2 = SimpleBlockChain()
  block_chain2.append({"a": 100, "b": 200 })
  block_chain2.append({"a": 150, "b": 300 })
  block_chain2.dump()
  print("block_chain3 ***************")
  block_chain3 = SimpleBlockChain()
  block_chain3.append({"a": 100, "b": 200 })
  block_chain3.append({"a": 900, "b": 700 })
  block_chain3.dump()

出力結果

block_chain1 ***************
========================= Block - [0] =========================
version         : 1.0.0
timestamp       : 1588487323.1843338
previous_hash   : init_hash
data_hash       : 12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126
data            : 
=================================================================
========================= Block - [1] =========================
version         : 1.0.0
timestamp       : 1588487323.1843338
previous_hash   : 12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126
data_hash       : b37cccb4aaafc33c5aac1f76d9156b446e999ed7ec94b51531027e5c91663ade
data            : {'a': 100, 'b': 200}
=================================================================
========================= Block - [2] =========================
version         : 1.0.0
timestamp       : 1588487323.1843338
previous_hash   : b37cccb4aaafc33c5aac1f76d9156b446e999ed7ec94b51531027e5c91663ade
data_hash       : 601ad2b78be074952288232fa83fdb61b7f8b9f5eb9ce91a9a9e5691e52891ca
data            : {'a': 150, 'b': 300}
=================================================================
block_chain2 ***************
========================= Block - [0] =========================
version         : 1.0.0
timestamp       : 1588487323.1911669
previous_hash   : init_hash
data_hash       : 12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126
data            :
=================================================================
========================= Block - [1] =========================
version         : 1.0.0
timestamp       : 1588487323.1911669
previous_hash   : 12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126
data_hash       : b37cccb4aaafc33c5aac1f76d9156b446e999ed7ec94b51531027e5c91663ade
data            : {'a': 100, 'b': 200}
=================================================================
========================= Block - [2] =========================
version         : 1.0.0
timestamp       : 1588487323.1911669
previous_hash   : b37cccb4aaafc33c5aac1f76d9156b446e999ed7ec94b51531027e5c91663ade
data_hash       : 601ad2b78be074952288232fa83fdb61b7f8b9f5eb9ce91a9a9e5691e52891ca
data            : {'a': 150, 'b': 300}
=================================================================
block_chain3 ***************
========================= Block - [0] =========================
version         : 1.0.0
timestamp       : 1588487323.198975
previous_hash   : init_hash
data_hash       : 12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126
data            :
=================================================================
========================= Block - [1] =========================
version         : 1.0.0
timestamp       : 1588487323.198975
previous_hash   : 12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126
data_hash       : b37cccb4aaafc33c5aac1f76d9156b446e999ed7ec94b51531027e5c91663ade
data            : {'a': 100, 'b': 200}
=================================================================
========================= Block - [2] =========================
version         : 1.0.0
timestamp       : 1588487323.198975
previous_hash   : b37cccb4aaafc33c5aac1f76d9156b446e999ed7ec94b51531027e5c91663ade
data_hash       : a23e7c3a279bd7a5b90a3c8659705573b3293583bbc3848bc525ef008686795a
data            : {'a': 900, 'b': 700}
=================================================================

関連記事

Python ~ HMAC ~
https://dk521123.hatenablog.com/entry/2022/10/08/002750
ハッシュ / Hash
https://dk521123.hatenablog.com/entry/2022/09/14/000000
ブロックチェーン ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2020/04/01/000000
Java】ハッシュで暗号化する
https://dk521123.hatenablog.com/entry/2014/08/02/234119
md5sum ~ MD5ハッシュ値を返す ~
https://dk521123.hatenablog.com/entry/2017/01/30/220600
パスワード について
https://dk521123.hatenablog.com/entry/2016/06/15/232436