このチュートリアルでは、Python の hashlib モジュールの組み込み機能を使用して安全なハッシュを作成する方法を説明します。
ハッシュの重要性と安全なハッシュをプログラムで計算する方法を理解することは、アプリケーション セキュリティの分野で働いていない場合でも役立ちます。しかし、なぜ?
Python プロジェクトに取り組んでいると、パスワードやその他の機密情報をデータベースやソース コード ファイルに保存することに懸念を抱く場面に遭遇する可能性があります。このような場合、機密情報に対してハッシュ アルゴリズムを実行し、情報の代わりにハッシュを保存する方が安全です。
このガイドでは、ハッシュとは何か、および暗号化との違いについて説明します。安全なハッシュ関数のプロパティについても説明します。次に、一般的なハッシュ アルゴリズムを使用して、Python で平文のハッシュを計算します。これを行うには、組み込みの hashlib モジュールを使用します。
以上のことをすべて含めて、始めましょう!
ハッシュとは何ですか?
ハッシュのプロセスではメッセージ文字列が取り込まれ、 hash と呼ばれる固定長の出力が得られます。これは、入力の長さに関係なく、特定のハッシュ アルゴリズムの出力ハッシュの長さが固定されることを意味します。しかし、暗号化とどう違うのでしょうか?
暗号化では、暗号化された出力を提供する暗号化アルゴリズムを使用して、メッセージまたはプレーン テキストが暗号化されます。次に、暗号化された出力に対して復号アルゴリズムを実行して、メッセージ文字列を取得できます。

ただし、ハッシュの動作は異なります。暗号化のプロセスは 可逆的で あり、暗号化されたメッセージから暗号化されていないメッセージに、またはその逆に切り替えることができることを学びました。
暗号化とは異なり、ハッシュは可逆プロセス ではありません 。つまり、ハッシュから入力メッセージに進む ことはできません 。

ハッシュ関数のプロパティ
ハッシュ関数が満たすべきいくつかのプロパティを簡単に見てみましょう。
- 決定的 : ハッシュ関数は 決定的 です。メッセージ m が与えられると、m のハッシュは常に同じになります。
-
Preimage Resistant
: ハッシュは元に戻せない操作ではないと述べたときに、これについてはすでに説明しました。プリイメージ耐性プロパティは、出力ハッシュからメッセージ
m
を見つけることが不可能であることを示しています。 -
衝突耐性
: m1 のハッシュ
m2
m1
のハッシュと等しいような 2 つの異なるメッセージ文字列m1
とm2
を見つけることは困難 (または計算的に不可能) である必要があります。この特性は 衝突耐性 と呼ばれます。 -
Second Preimage Resistant
: これは、メッセージ
m1
と対応するハッシュm2
が与えられた場合、hash(m1) = hash(m2)
なるような別のメッセージm2
を見つけるのは不可能であることを意味します。
Pythonのハッシュライブラリモジュール
Python の組み込み hashlib モジュールは、 SHA アルゴリズム や MD5 アルゴリズムなど、いくつかのハッシュ アルゴリズムとメッセージ ダイジェスト アルゴリズムの実装を提供します。
Python hashlib モジュールのコンストラクターと組み込み関数を使用するには、次のように作業環境にインポートします。
import hashlib
hashlib モジュールは、
algorithms_available
と
algorithms_guaranteed
定数を提供します。これらは、それぞれプラットフォーム上で実装が利用可能および保証されているアルゴリズムのセットを示します。
したがって、
algorithms_guaranteed
、
algorithms_available
のサブセットです。

Python REPL を開始し、hashlib をインポートし、
algorithms_available
と
algorithms_guaranteed
定数にアクセスします。
>>> hashlib.algorithms_available
# Output
{'md5', 'md5-sha1', 'sha3_256', 'shake_128', 'sha384', 'sha512_256', 'sha512', 'md4',
'shake_256', 'whirlpool', 'sha1', 'sha3_512', 'sha3_384', 'sha256', 'ripemd160', 'mdc2',
'sha512_224', 'blake2s', 'blake2b', 'sha3_224', 'sm3', 'sha224'}
>>> hashlib.algorithms_guaranteed
# Output
{'md5', 'shake_256', 'sha3_256', 'shake_128', 'blake2b', 'sha3_224', 'sha3_384',
'sha384', 'sha256', 'sha1', 'sha3_512', 'sha512', 'blake2s', 'sha224'}
algorithms_guaranteed
実際に
algorithms_available
のサブセットであることがわかります。
Python でハッシュ オブジェクトを作成する

次に、Python でハッシュ オブジェクトを作成する方法を学びましょう。次の方法を使用して、メッセージ文字列の SHA256 ハッシュを計算します。
-
汎用
new()
コンストラクター - アルゴリズム固有のコンストラクター
new() コンストラクターの使用
message
文字列を初期化しましょう。
>>> message = " is awesome!"
ハッシュ オブジェクトをインスタンス化するには、次のように
new()
コンストラクターを使用し、アルゴリズムの名前を渡します。
>>> sha256_hash = hashlib.new("SHA256")
これで、
message
文字列を引数としてハッシュ オブジェクトの
update()
メソッドを呼び出すことができます。
>>> sha256_hash.update(message)
ハッシュ アルゴリズムはバイト文字列でのみ機能するため、これを行うとエラーが発生します。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Unicode-objects must be encoded before hashing
エンコードされた文字列を取得するには、メソッド文字列に対して
encode()
メソッドを呼び出し、それを
update()
メソッド呼び出しで使用します。その後、
hexdigest()
メソッドを呼び出して、メッセージ文字列に対応する sha256 ハッシュを取得できます。
sha256_hash.update(message.encode())
sha256_hash.hexdigest()
# Output:'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
encode()
メソッドを使用してメッセージ文字列をエンコードする代わりに、次のように文字列の先頭に
b
を付けることでメッセージ文字列をバイト文字列として定義することもできます。
message = b" is awesome!"
sha256_hash.update(message)
sha256_hash.hexdigest()
# Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
取得されたハッシュは前のハッシュと同じであり、ハッシュ関数の決定論的な性質が確認されます。
さらに、
message
文字列の小さな変更により、ハッシュが大幅に変化します (「雪崩効果」とも呼ばれます)。
これを確認するために、「awesome」の「a」を「A」に変更して、ハッシュを計算してみましょう。
message = " is Awesome!"
h1 = hashlib.new("SHA256")
h1.update(message.encode())
h1.hexdigest()
# Output: '3c67f334cc598912dc66464f77acb71d88cfd6c8cba8e64a7b749d093c1a53ab'
ハッシュが完全に変化していることがわかります。
アルゴリズム固有のコンストラクターの使用
前の例では、汎用の
new()
コンストラクターを使用し、ハッシュ オブジェクトを作成するアルゴリズムの名前として「SHA256」を渡しました。
そうする代わりに、次に示すように
sha256()
コンストラクターを使用することもできます。
sha256_hash = hashlib.sha256()
message= " is awesome!"
sha256_hash.update(message.encode())
sha256_hash.hexdigest()
# Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
出力ハッシュは、
message
文字列「 は素晴らしい!」について以前に取得したハッシュと同じです。
ハッシュ オブジェクトの属性の調査
ハッシュ オブジェクトには、いくつかの便利な属性があります。
-
digest_size
属性は、ダイジェストのサイズをバイト単位で示します。たとえば、SHA256 アルゴリズムは 256 ビットのハッシュを返します。これは 32 バイトに相当します。 -
block_size
属性は、ハッシュ アルゴリズムで使用されるブロック サイズを指します。 -
name
属性は、new()
コンストラクターで使用できるアルゴリズムの名前です。この属性の値を調べると、ハッシュ オブジェクトにわかりやすい名前がない場合に役立ちます。
前に作成した
sha256_hash
オブジェクトのこれらの属性を確認できます。
>>> sha256_hash.digest_size
32
>>> sha256_hash.block_size
64
>>> sha256_hash.name
'sha256'
次に、Python の hashlib モジュールを使用したハッシュの興味深い応用例をいくつか見てみましょう。
ハッシュ化の実践例

ソフトウェアとファイルの整合性の検証
開発者として、私たちは常にソフトウェア パッケージをダウンロードしてインストールします。これは、Linux ディストリビューションで作業しているか、Windows や Mac で作業しているかに関係なく当てはまります。
ただし、ソフトウェア パッケージの一部のミラーは 信頼できない場合があります 。ダウンロード リンクの横にハッシュ (またはチェックサム) が表示されます。また、ハッシュを計算して公式ハッシュと比較することで、ダウンロードしたソフトウェアの整合性を検証できます。
これはマシン上のファイルにも適用できます。ファイルの内容がわずかに変更されただけでもハッシュは大幅に変化します。ハッシュを検証することでファイルが変更されたかどうかを確認できます。
以下に簡単な例を示します。作業ディレクトリにテキスト ファイル「my_file.txt」を作成し、それにコンテンツを追加します。
$ cat my_file.txt
This is a sample text file.
We are going to compute the SHA256 hash of this text file and also
check if the file has been modified by
recomputing the hash.
次に、ファイルを読み取りバイナリ モード (
'rb'
) で開き、ファイルの内容を読み取り、次に示すように SHA256 ハッシュを計算します。
>>> import hashlib
>>> with open("my_file.txt","rb") as file:
... file_contents = file.read()
... sha256_hash = hashlib.sha256()
... sha256_hash.update(file_contents)
... original_hash = sha256_hash.hexdigest()
ここで、変数
original_hash
、現在の状態の「my_file.txt」のハッシュです。
>>> original_hash
# Output: '53bfd0551dc06c4515069d1f0dc715d002d451c8799add29f3e5b7328fda9f8f'
次に、ファイル「my_file.txt」を変更します。 「going」という単語の前にある余分な先頭の空白を削除できます。 🙂
ハッシュを再度計算し、
computed_hash
変数に保存します。
>>> import hashlib
>>> with open("my_file.txt","rb") as file:
... file_contents = file.read()
... sha256_hash = hashlib.sha256()
... sha256_hash.update(file_contents)
... computed_hash = sha256_hash.hexdigest()
次に、
computed_hash
が
original_hash
と等しいかどうかをアサートする単純なassert ステートメントを追加できます。
>>> assert computed_hash == original_hash
ファイルが変更された場合 (この場合は当てはまります)、AssertionError が返されるはずです。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
パスワードなどの機密情報をデータベースに保存するときにハッシュを使用できます。データベースに接続するときのパスワード認証でハッシュを使用することもできます。入力されたパスワードのハッシュを正しいパスワードのハッシュと比較して検証します。
結論
このチュートリアルが、Python を使用した安全なハッシュの生成について学習するのに役立つことを願っています。重要なポイントは次のとおりです。
-
Python の hashlib モジュールは、いくつかのハッシュ アルゴリズムのすぐに使用できる実装を提供します。
hashlib.algorithms_guaranteed
を使用して、プラットフォームで保証されているアルゴリズムのリストを取得できます。 -
ハッシュ オブジェクトを作成するには、一般的な
new()
コンストラクターを構文hashlib.new("algo-name")
で使用できます。あるいは、SHA 256 ハッシュの場合はhashlib.sha256()
のように、特定のハッシュ アルゴリズムに対応するコンストラクターを使用することもできます。 -
ハッシュするメッセージ文字列とハッシュ オブジェクトを初期化した後、ハッシュ オブジェクトに対して
update()
メソッドを呼び出し、続いてhexdigest()
メソッドを呼び出してハッシュを取得できます。 - ハッシュは、ソフトウェア アーティファクトやファイルの整合性をチェックしたり、機密情報をデータベースに保存したりする場合に便利です。
次に、Python でランダム パスワード ジェネレーターをコーディングする方法を学びます。