弱いパスワードハッシュ

計算コストが不足したパスワードハッシュ

説明

計算コストの低い汎用ハッシュをパスワードに直接使うと、攻撃者は漏えいしたハッシュに対して大量の候補を短時間で試せます。特に弱いパスワードや使い回されたパスワードは、推測によって特定される危険が高まります。

想定される影響

  • パスワードの解析: 高速なハッシュでは、多数の候補を低いコストで試せます。
  • アカウントの乗っ取り: 特定されたパスワードでアカウントに侵入されるおそれがあります。
  • 情報漏えい: 侵害されたアカウントから機密データにアクセスされる可能性があります。

対処方法

  • Argon2id、bcrypt、scrypt、十分な反復回数のPBKDF2など、意図的に計算コストを高めたパスワード専用の方式を使ってください。
  • 汎用ハッシュと用途を区別してください。SHA-256はファイルやメッセージの完全性確認に使えますが、パスワード保存には速すぎるため直接使用しないでください。
  • パスワードごとにランダムなソルトを管理する検証済みのライブラリを使い、運用環境でコスト設定を測定してください。
  • OWASPやNISTなどの最新のセキュリティ指針に従ってください。

例

パスワードのハッシュ化

変更前

MD5:

python
# パスワードにMD5を使用する不適切な例
import hashlib

password = b'mypassword'
hashed_password = hashlib.md5(password).hexdigest()

SHA-1:

python
# パスワードにSHA-1を使用する不適切な例
import hashlib

password = "mypassword"
hashed_password = hashlib.sha1(password.encode()).hexdigest()

変更後

Bcrypt:

python
# bcryptによるパスワードハッシュ
import bcrypt

def hash_password(password):
    salt = bcrypt.gensalt(rounds=12)
    hashed = bcrypt.hashpw(password.encode(), salt)
    return hashed

password = "mysecretpassword"
hashed_password = hash_password(password)

Argon2:

python
# Argon2によるパスワードハッシュ
from argon2 import PasswordHasher

def hash_password(password):
    ph = PasswordHasher()
    return ph.hash(password)

password = "mysecretpassword"
hashed_password = hash_password(password)

一般データの完全性確認用ハッシュ(パスワード以外)

python
# SHA-256はパスワードではなく一般データの完全性確認に使用
import hashlib

document = b'document contents'
document_digest = hashlib.sha256(document).hexdigest()

解説:

  • 変更前: MD5とSHA-1はパスワード保存に適していません。SHA-256、SHA-512、SHA-3などの高速な汎用ハッシュを直接使う場合も、オフラインでの推測に必要なコストが低くなります。
  • 変更後: パスワードには、コストを調整でき、個別のソルトを使うbcryptやArgon2idなどの専用方式を利用します。SHA-256の例は、パスワード以外の一般データの完全性確認用として分けています。

参考資料