PBKDF2 key stretching (2000)#

A key derived from a password is only as hard to find as the password. Burt Kaliski’s PBKDF2, in RFC 2898, cannot add entropy, but it makes every guess expensive: it iterates HMAC c times, and mixes in a salt so that one precomputed table cannot serve every user,

\[U_1 = \mathrm{HMAC}(P, S \,\|\, 1), \quad U_j = \mathrm{HMAC}(P, U_{j-1}), \quad T = U_1 \oplus \cdots \oplus U_c .\]

The honest user pays c HMAC calls once; an attacker trying N passwords pays N times c. BIP39 stretches seed phrases this way with 2048 iterations. Here a three-digit PIN is cracked at increasing iteration counts.

import time

import matplotlib.pyplot as plt

import blockchainkit as bk

The same password, different salts#

alice = bk.wallets.pbkdf2(b"042", b"alice's salt", 10, 32)
bob = bk.wallets.pbkdf2(b"042", b"bob's salt", 10, 32)
print("alice", alice.hex()[:16], "bob", bob.hex()[:16])
assert alice != bob
alice bb8dcf6d9b44a816 bob b3912ad5ac011953

Exercise#

How many iterations make cracking a six-digit PIN cost as many HMAC calls as cracking an unstretched nine-digit one? What does that say about stretching against a long, random password? A worked solution is in Exercises: wallets.

Total running time of the script: (0 minutes 0.209 seconds)

Gallery generated by Sphinx-Gallery