Skip to content

Instantly share code, notes, and snippets.

@orip
Created June 9, 2021 21:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save orip/e26bef3aa0348bb7f454996d1144d552 to your computer and use it in GitHub Desktop.
Save orip/e26bef3aa0348bb7f454996d1144d552 to your computer and use it in GitHub Desktop.
Test vectors for iterated HMAC-SHA-256 used as a salted hash algorithm with CPU stretching
# Iterated HMAC-SHA-256 password hashing homebrew
# Important: avoid this. Use argon2 or scrypt instead (CPU+mem stretching) or PBKDF2 or bcrypt (just CPU)
def iterated_hmacsha256(password, salt, extra_rounds):
import hmac, hashlib
current = salt
for i in range(1 + extra_rounds): # extra rounds beyond the first
current = hmac.new(key=password, msg=current, digestmod=hashlib.sha256).digest()
return current
# These vectors have been verified with multiple implementations
test_vectors = [
{"password": "very secret", "salt_hex": "33c177c69050b61066215084a34816ae", "extra_rounds": 321, "result_hex": "84b8be66436b9b5072df17e1dd216faef3d8460e25c2a3f659ac6aae6642a42e"},
{"password": "very secret", "salt_hex": "33c177c69050b61066215084a34816ae", "extra_rounds": 10000, "result_hex": "2eb68f678bc1d5b4b3050b032e2cd2f9e7de9ed57232c312901813e70ec3a910"},
{"password": "", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "8e111d21005bf86277073244e449309bb46571eb6c540320c18fea9c52cf9424"},
{"password": "A", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "0248a03e7e3b85a9e60846c5c06b137a9c7291a4662e629e0c4d086e37b59350"},
{"password": "As", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "67707f4c668f68a25aaff744cdfaae0a8806fd27722ef045d42865e8182ec0f4"},
{"password": "As_", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "371b90c051e7e9086d89ed21b457ed9fe97e7701eca4e7348cb44df20eae0fe3"},
{"password": "As_c", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "eb14fd73ad2e747a8746e0644a02ca71b9bf73a0222a7c9a4f1d6ce86bfa1694"},
{"password": "As_c]", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "e004cbe22f44b6eb543e784b846815213cd3d31809a506e2c944a7fedc8ac773"},
{"password": "As_c]K", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "ae5bebbed836efa77e5b4779097fbfdb1859624e7f5774cf6c2114aaa7ea14d2"},
{"password": "As_c]K5", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "ec102ee587d745eead06452ee0a8fd4fd8aaf4d2ea803f9e87918e1e0233223f"},
{"password": "As_c]K5$", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "a1e5d6ef1d5bc87c66b128fb6afd069e3f9a88c6a58ad65b3908b1820e61f044"},
{"password": "As_c]K5$J", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "c64cc5f045211f877c81a7a38bc58a71e9160548b2d25f3efdb8372769852212"},
{"password": "As_c]K5$JI", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "3da9f519e45aedb871625e369effeddd954691d8bd73cd206dbdd1edfe89daa4"},
{"password": "As_c]K5$JIm", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "376a5517bf8adc58ed5de0630a72c6e6a244f32f58c9f68435146b9119f0e134"},
{"password": "As_c]K5$JIm_", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "369e02f4a36f705760d42ed5ec3fe6640fe99418d2185c9cb4545ea244ff6d43"},
{"password": "As_c]K5$JIm_]", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "e9ebf9e9abd86ee3b466927e42bddae8eb34102b99bf16e3fa4f7a7ebd236371"},
{"password": "As_c]K5$JIm_]3", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "3db9c7eb5acdadcce96638fc17b04f1ff909cbd0989b73cfc07bb30754939a8a"},
{"password": "As_c]K5$JIm_]3o", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "7cdd235f4a7ffc9fa942c48e784344ad033454ee23b42d3f0fec7007161ba1d7"},
{"password": "As_c]K5$JIm_]3oL", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "f89b8d269d796b664885d4aba104c3b3a7e9063578c1b83bf6786a6c5501dff5"},
{"password": "As_c]K5$JIm_]3oL6", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "27e4ee3acee63ab154cb86d2f1fcdef5771348cd650015f1aad30d37ef643006"},
{"password": "As_c]K5$JIm_]3oL68", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "3cb5e627b2beb4ac5394ebc5e5a684af8eda672340c11571adaf353698a5749c"},
{"password": "As_c]K5$JIm_]3oL68V", "salt_hex": "010203", "extra_rounds": 100, "result_hex": "d1228e8462488b188175b884fe46de1529a829f73bede78546ba62fe09972817"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 0, "result_hex": "ce369a05c759c288465cc2ef274a1508c515dc87ad28c4c1658048e2fa3fa2f8"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 1, "result_hex": "e15a958bb97dc0df409d8629ab32bc2de4750da850efb8f8576b246536e9990e"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 2, "result_hex": "94e65add43759e1d4d68c829d518a320cf0dd1e5908cc429559ef9288af9d1e3"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 3, "result_hex": "91f528157275ca0d30435d1e64b73f54732dfdfe6861179af849531560a51ab5"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 4, "result_hex": "6ba4d409b02c556fab6a1b4f0ff8011beae551d72d6e156dc93f674c34e55028"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 5, "result_hex": "ec0e907230e71b976fdc5bc4e2e60d2a5ce60cde2b5324c4b3a82ee9b9f70f2a"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 6, "result_hex": "3ebfdf4b70c691cfa22b6f49a09ee0c7b88b6f82b66a968f95bdcfc09159001d"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 7, "result_hex": "5d57ea29e3f86fde30bb96182143d78e2e82e0dba33f896e849fdc01c30082e4"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 8, "result_hex": "012b570c617d237099aef822dfeb383928dfb83a605a6e74093bfaf120024f2d"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 9, "result_hex": "d81b2ed1a08b35fa2ccbb15274eb83afc229c1c6e80c8f1ff95bee225287dd64"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 10, "result_hex": "f2d8e1c2fbf72dc378855e2f86f4cf30b80302da339930a21c0e40beb8512ef6"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 11, "result_hex": "27e8c35d6fefc77bb382412ad0bc5414129590b692d7bc6e3aef519e02ad1420"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 12, "result_hex": "fd2f7d2d7490ef6ac078712c08fe9db7590c12d76163ef45c62751b772e79f0d"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 13, "result_hex": "f3e8e20d53e05b516ead13141b575a37d63e796251197f6bf83442e214723727"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 14, "result_hex": "f3f7e8ac8491e6807ff3cb7a966f13c0828d0ae3e81d9dd0290e2ba99f2dde86"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 15, "result_hex": "e267e89b7796464520b050e0384a695abe146f154bb3f656319e1d7f31ca3939"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 16, "result_hex": "dc239ddf195a8f4a3f7b1ce6b2d193a29b7c6e24d7e65f9d4e11202c51436e6c"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 17, "result_hex": "88138424c253bee4d4f3c1558024194c188c3c3919e137ba021aa74bbc906383"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 18, "result_hex": "fa82dc04adb0739974cd3c3d70b2e4f49be296fcd8f571e5a10aae957a46e6f2"},
{"password": "very secret", "salt_hex": "010203", "extra_rounds": 19, "result_hex": "5af99dd2ca7ad8632b59249fa51cb87d15124539ef3cc4dd45cf2e0cc5d1b05d"},
]
def test():
for v in test_vectors:
actual = iterated_hmacsha256(
password = v["password"].encode("utf-8"),
salt = bytes.fromhex(v["salt_hex"]),
extra_rounds = v["extra_rounds"],
)
expected = bytes.fromhex(v["result_hex"])
assert actual == expected, "got result %s for test vector %s"%(actual.hex(), v)
print("All test vectors match")
if __name__ == "__main__":
test()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment