まずハッシュ値とは何か!
ハッシュ化とは入力データを一定の手順で計算し決まった長さの文字列を出力する事。
入力データが一緒だとハッシュ値も同じ。
メリット!
データ確認ー文字列をハッシュ下するメリットとしては入力値の長さが関係なくハッシュ値の長さは同じなため、例えば膨大なファイルが二つあるとして、そのファイルが同じ内容か確認するとき、ハッシュ値に変えて確認すると早い。パスワード管理ー同じ文字列をハッシュ化するとハッシュ値は同じなものの、ハッシュ値から元の文字列には戻せないため、パスワード管理などに使用されることが多い。
暗号化とは違うのか
ハッシュ化は暗号化とは違います。
例えばパスワードを設定し何かしらで鍵をかけて暗号化します。ここまでは同じですが暗号化は鍵を開けると元の入力データを復元することができます。
ハッシュ値はもとに戻すことを前提に作られてないからです。
ハッシュ化の方法
まずハッシュ化するにあたってsaltと言う概念が存在します。saltは言えばどこでもドアみたいなものです。
例えばのび太の部屋(元の入力データ)からどこにも場所を指定せずにどこでもドアを開けるとそのままドアの裏側に続くだけです。ですが行きたい場所(salt)を指定して開けると指定したところに続きます。saltを指定すると指定しないのと違うハッシュ値得られると言うわけです!(例えがイマイチでしたが)
なのでもしパスワード管理にハッシュ値が使われる場合はセキュリティを強化するために全ユーザーに違うランダムなsaltが設けられます。それに付け加えてその計算を何回もします。
例えばこんな感じ
secret_code
→(ソルトを使ってハッシュ化)c73729c...
→(それをまたハッシュ化) bf5c75e6...
...
を繰り返すみたいな感じです。何回繰り返すかは iterations = (何回)って感じで指定されます。一般的には、数千から数十万回程度のイテレーションが推奨されます。安全性が重要なシステムではより多いイテレーション回数が採用される場合もあります!
また、同じソルトを使用しても、イテレーション回数が異なれば異なるハッシュ値が生成されます。セキュリティ上の理由から、一意でランダムなソルトを使用し、適切なイテレーション回数を選択することが重要です。
パスワードハッシュ生成によく使われる安全な関数です。
hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)
hash_name
:ハッシュ関数の名前を指定します。例えば、"sha256"や"sha512"などの文字列を指定します。
password
:ハッシュ化するパスワードをバイト列で指定します。文字列をバイト列に変換するには、encode()メソッドを使用します。例えば、"password".encode()のように指定します。
salt
:ソルトとして使用するランダムなバイト列を指定します。ソルトはハッシュの強度を高めるために使用されます。一意でランダムなバイト列を生成して指定します。
iterations
:ハッシュ計算のイテレーション回数を指定します。イテレーション回数が多いほどハッシュ計算にかかる時間が増え、セキュリティが向上します。適切なイテレーション回数は、安全性とパフォーマンスのバランスを考慮して設定する必要があります。
dklen
:出力する派生キーの長さを指定します。デフォルトでは、ハッシュ関数の出力長になります。特定の長さを指定する場合には、バイト数で指定します。
hashlib.pbkdf2_hmac()
関数は、上記の引数を指定して呼び出すことで、PBKDF2-HMACアルゴリズムを使用したハッシュ化を行います。この関数はパスワードハッシュ化や鍵派生に使用され、セキュリティ上の目的で利用されます。
なのでこのように使うことができます。
import hashlib
# パスワード
password = "Secret123"
# ソルト (ランダムなデータ)
salt = b"1a3f5b2e"
# ハッシュ関数とイテレーション回数の指定
hash_function = hashlib.sha256
iterations = 100000
# PBKDF2-HMACでハッシュ化
key = hashlib.pbkdf2_hmac(hash_function.__name__, password.encode(), salt, iterations)
# ハッシュ値の表示
print(key.hex())