暗号化とハッシュ化 (hashlib, secretsモジュール) について
データのセキュリティは、現代のソフトウェア開発において極めて重要な課題です。特に、パスワードの保護や機密情報の処理には、暗号化やハッシュ化の技術が不可欠です。Python
では、これらの作業を容易にするために、標準ライブラリとしてhashlib
モジュールとsecrets
モジュールが提供されています。
この記事では、Python
でのハッシュ化と暗号学的な乱数生成について、hashlib
モジュールとsecrets
モジュールを用いた具体的な使用方法を解説します
暗号化とハッシュ化の違い
まず、暗号化とハッシュ化の違いを理解しておきましょう。
- 暗号化: データを秘匿するために、元のデータを変換して第三者が読めない形式にする方法です。復号化キーがあれば元のデータに戻すことが可能です。暗号化の主な目的は、データの秘匿性を保つことです。
- ハッシュ化: データを一方向に変換し、元のデータに戻すことができないようにする方法です。ハッシュ化はデータの整合性をチェックしたり、パスワードを安全に保存するために使われます。ハッシュ化の目的はデータの改ざん防止です。
Python
では、暗号化のために外部ライブラリ(例:cryptography
)を使用しますが、ここでは主にハッシュ化と暗号学的乱数生成について取り上げます。
hashlib
モジュールによるハッシュ化
Python
のhashlib
モジュールは、SHA(Secure Hash Algorithm)やMD5などの標準的なハッシュ関数を提供しています。これらのハッシュ関数は、入力データから固定長のハッシュ値(ダイジェスト)を生成し、その値がデータの指紋のように機能します。
SHA-256によるハッシュ化
次に、hashlib
を使って、文字列をSHA-256アルゴリズムでハッシュ化する例を紹介します。SHA-256は、非常に強力な暗号学的ハッシュアルゴリズムで、広く使われています。
import hashlib
# ハッシュ化するデータ
data = "hello world"
# SHA-256でハッシュ化
hash_object = hashlib.sha256(data.encode())
hash_hex = hash_object.hexdigest()
print(f"SHA-256: {hash_hex}")
実行結果
SHA-256: b94d27b9934d3e08a52e52d7da7dabfadec78e6e42b1fe5ebd5edc308e41e1f8
ポイント
sha256()
: SHA-256アルゴリズムを使用してハッシュを計算します。encode()
: 文字列をバイト列に変換するために使用します。ハッシュ関数はバイト列を入力として受け取る必要があるため、文字列をハッシュ化する場合はこの変換が必要です。hexdigest()
: ハッシュ値を16進数文字列として取得します。
MD5によるハッシュ化
MD5はかつて非常に広く使われたハッシュアルゴリズムですが、現在ではセキュリティ上の脆弱性が発見されており、機密データのハッシュ化には推奨されていません。しかし、チェックサムなどの用途にはまだ使用されることがあります。
import hashlib
# ハッシュ化するデータ
data = "hello world"
# MD5でハッシュ化
hash_object = hashlib.md5(data.encode())
hash_hex = hash_object.hexdigest()
print(f"MD5: {hash_hex}")
実行結果
MD5: 5eb63bbbe01eeed093cb22bb8f5acdc3
他のハッシュアルゴリズム
hashlib
では、他にも多くのハッシュアルゴリズムがサポートされています。例えば、sha1
、sha224
、sha512
なども使用可能です。
hashlib.sha1(data.encode()).hexdigest() # SHA-1
hashlib.sha512(data.encode()).hexdigest() # SHA-512
secrets
モジュールによる安全な乱数生成
Python
のsecrets
モジュールは、暗号学的に安全な乱数生成を目的としたモジュールです。これは、パスワードやトークン、APIキーなどのセキュリティに関連するデータを生成する際に利用されます。random
モジュールも乱数生成を提供しますが、secrets
はセキュリティ面でより強力な乱数を生成します。
暗号学的に安全なトークンの生成
次の例では、secrets
を使って暗号学的に安全なトークンを生成します。これらのトークンは、ユーザー認証やセッションID、APIキーなどの生成に適しています。
import secrets
# 32バイトの安全なトークンを生成
token = secrets.token_hex(32)
print(f"Generated Token: {token}")
実行結果
Generated Token: 9f3e22c65e77d1c089c82e9ad6b2a1a0a4df90b5b8946f9f9b4df1e92f4b5c64
安全なランダム値の生成
パスワード生成やセキュリティに関わるランダムな選択を行う場合にもsecrets
モジュールを使います。次に、1〜10の範囲で暗号学的に安全な乱数を生成する例です。
import secrets
# 1から10までのランダムな整数を生成
random_number = secrets.randbelow(10) + 1
print(f"Random Number: {random_number}")
安全なパスワード生成
次の例では、指定された文字列から暗号学的に安全な方法でランダムなパスワードを生成します。
import secrets
import string
# 使用する文字のセットを定義
alphabet = string.ascii_letters + string.digits + string.punctuation
# 12文字の安全なパスワードを生成
password = ''.join(secrets.choice(alphabet) for i in range(12))
print(f"Generated Password: {password}")
実行結果
Generated Password: P7a!K3f%9rZq
パスワードハッシュ化とソルト
パスワードの保存において、セキュリティを高めるために、ソルトと呼ばれるランダムな値を追加してハッシュ化する方法が一般的です。これにより、同じパスワードでも異なるハッシュ値が生成されるため、辞書攻撃やレインボーテーブル攻撃を防ぐことができます。
ソルト付きパスワードハッシュ
次に、secrets
で生成したソルトを使ってパスワードをハッシュ化する例を示します。
import hashlib
import secrets
# ソルトの生成
salt = secrets.token_hex(16)
# パスワードのハッシュ化
password = "my_secure_password"
hash_object = hashlib.sha256((salt + password).encode())
password_hash = hash_object.hexdigest()
print(f"Salt: {salt}")
print(f"Hashed Password: {password_hash}")
実行結果
Salt: 4e6f1d7e02d0412b52aab23b9faeed84
Hashed Password: d1e3f3d7fe53e9a5a6799a9ed5b20a6c10914d0e80d161446015dc492d9c44d4
この方法では、パスワードのハッシュを保存する際に、ソルトも一緒に保存しておきます。次回、ユーザーがログインしたときには、そのソルトを使ってパスワードを再度ハッシュ化し、保存されたハッシュ値と比較することで認証を行います
hashlib
とsecrets
の使いどころ
-
hashlib
: パスワードのハッシュ化、ファイルの整合性チェック(例: SHA-256によるチェックサム)、データの改ざん防止に使用します。特に、データの改ざんを検出するためにハッシュ値を保存する場合に便利です。 -
secrets
: パスワードやトークンの生成、暗号学的に安全な乱数生成に使用します。random
モジュールはセキュリティ目的には不向きですが、secrets
はこれらの用途に最適です。
まとめ
Python
のhashlib
モジュールとsecrets
モジュールは、データのセキュリティを高めるために重要な役割を果たします。hashlib
は強力なハッシュアルゴリズムを提供し、パスワードや機密情報をハッシュ化して保護するのに適しています。また、secrets
は、パスワードやトークンの生成、暗号学的に安全な乱数生成を行うためのツールです。
hashlib
を使ってデータをハッシュ化し、整合性を保つsecrets
を使って、安全なパスワードやトークンを生成- ソルトを追加することで、パスワードのセキュリティを向上
参照:
hashlib公式ドキュメント参照:
secrets公式ドキュメント