4

パスワードのハッシュ化には、mitsuhiko の pbkdf2 の実装を使用します。

def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None):
    """Returns a binary digest for the PBKDF2 hash algorithm of `data`
    with the given `salt`.  It iterates `iterations` time and produces a
    key of `keylen` bytes.  By default SHA-1 is used as hash function,
    a different hashlib `hashfunc` can be provided.
    """
    hashfunc = hashfunc or hashlib.sha1
    mac = hmac.new(data, None, hashfunc)
    def _pseudorandom(x, mac=mac):
        h = mac.copy()
        h.update(x)
        return map(ord, h.digest())
    buf = []
    for block in xrange(1, -(-keylen // mac.digest_size) + 1):
        rv = u = _pseudorandom(salt + _pack_int(block))
        for i in xrange(iterations - 1):
            u = _pseudorandom(''.join(map(chr, u)))
            rv = starmap(xor, izip(rv, u))
        buf.extend(rv)
    return ''.join(map(chr, buf))[:keylen]

この関数は、base64 でエンコードされてデータベースに保存されるバイナリ ダイジェストを返します。また、ユーザーがログインすると、base64 文字列が Cookie として設定されます。

この関数は、パスワード ハッシュの比較に使用されます。

def comparePasswords(password1, password2):
    if len(password1) != len(password2):
        return False
    diff = 0
    for x, y in izip(password1, password2):
        diff |= ord(x) ^ ord(y)
    return diff == 0

バイナリ ハッシュと base64 文字列の比較で、セキュリティの点で違いがあるのだろうか? たとえば、ユーザーがログインすると、送信されたパスワードのバイナリ ダイジェストを計算し、データベースから base64 文字列をデコードしてから 2 つのバイナリ ハッシュを比較しますが、ユーザーが base64 文字列の Cookie を持っている場合は、それを a 文字列と直接比較しますデータベース。

2 番目の質問は塩についてです。

os.urandom はバイナリ文字列を返しますが、ハッシュ生成で使用する前に base64 でエンコードします。これを行ってソルトをバイナリ形式で使用してはならない理由はありますか?

4

1 に答える 1

10

質問1に答えるには:バイトを比較する場合とbase64でエンコードされた文字列を比較する場合のセキュリティに大きな違いはありません...nまたはn*4/3要素を比較しているだけです。base64 を使用するとランタイムは4/3長くなりますが、時間はわずかです :)

そうは言っても、同様の「一定時間」比較関数に関する python 開発者の議論があり、彼らはいくつかの VM レベルの落とし穴にぶつかりました - 入力がunicodeではなく文字列である場合bytes、特にユニコードに非 ASCII 文字が含まれている場合、まだいくつかの微妙なタイミング攻撃が存在する可能性があります (短絡等価攻撃よりも数桁少ない)。そのため、可能であれば (バイナリ データであれ、ASCII エンコードされた base64 データであれ) バイトに固執します。ただし、 PBKDF2 の場合、比較関数が無効にするように設計されたタイミング攻撃は、パスワード ハッシュ検証ではなく HMAC 署名に適用されるため、あまり心配する必要はありません。

質問 2 に答えるには: のような安全でない構造のmd5(salt+password)場合、最初にソルトをエンコードすると、攻撃者が既存の ASCII md5 テーブルを使用してダイジェスト全体を攻撃できるようになります。生のバイナリ ソルトを使用すると、そのようなテーブルが役に立たなくなります。nただし、PBKDF2-HMAC は、saltにエントロピーのビットが含まれていることだけが問題となる十分なマングリングを行います。それがn/8raw バイトの形式であろうと、 n/6base64 文字であろうと、セキュリティには影響しません。

その他の注意事項: あなたが投稿した内容に関連するいくつかの点を追加したかっただけです...

  1. セキュリティ上の理由から、PBKDF2-HMAC ハッシュ関数として SHA1 の代わりに SHA256/512 を使用し、セキュリティのために >= 10,000 ラウンド (2012 年現在) を使用することを強くお勧めします。

  2. Cookie でダイジェストを送信するという考え (ソルトなしでも) は、潜在的に安全ではないと思います...誰かがその Cookie を盗んだ場合 (クロスサイトスクリプティング攻撃など)、ユーザーとしてログインする可能性があります (ただし、アプリケーションのセキュリティ設定の残りの部分はわかりません)。ランダムに生成されたセッション ID (例: Beaker ) を持つセッション層を使用することは、良い代替手段かもしれません。

  3. Passlib PBKDF2consteqの実装を使用することをお勧めします。PBKDF2 ルーチンは mitsuhiko のルーチンよりも約 5 倍速く、存在する場合はM2Cryptoを利用できます。(免責事項: 私は Passlib の作成者です) . また、既製のpbkdf2-sha256パスワード ハッシュ関数も備えていますが、ダイジェストを Cookie で送信する場合はあまり役に立ちません。

于 2012-08-06T17:01:08.730 に答える