1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
import os
import sys
import json
import hmac
import hashlib
import base64
import binascii
from passlib.utils import saslprep
from argon2.low_level import hash_secret
from argon2.low_level import Type
if len(sys.argv) not in (2, 3):
print("usage: {} password".format(sys.argv[0]))
sys.exit(2)
password = sys.argv[1].encode('ascii')
if len(sys.argv) == 3:
m = hashlib.sha256()
m.update(sys.argv[2].encode('utf8'))
salt = m.digest()[:16]
# salt = binascii.a2b_hex(sys.argv[2].encode('ascii'))
assert len(salt) == 16
else:
salt = os.urandom(16)
hash_data = hash_secret(
secret=password,
salt=salt,
time_cost=4096,
memory_cost=512,
parallelism=1,
hash_len=32,
type=Type.ID,
version=19,
)
_, tag, v, params, othersalt, salted_password = hash_data.decode('ascii').split('$')
assert tag == 'argon2id'
assert v == 'v=19' # argon's version 1.3 is represented as 0x13, which is 19 decimal...
params = {
k: v
for k, v in
[x.split('=') for x in params.split(',')]
}
salted_password = salted_password.encode('ascii')
client_key = hmac.new(salted_password, b"Client Key", hashlib.sha256).digest()
stored_key = hashlib.new('sha256', client_key).digest()
server_key = hmac.new(salted_password, b"Server Key", hashlib.sha256).digest()
# this can be copy-pasted into the config.json for a Crossbar.io
# static-configured scram principal; see the example router config
key = {
"kdf": "argon2id-13",
"memory": int(params['m']),
"iterations": int(params['t']),
"salt": binascii.b2a_hex(salt).decode('ascii'),
"stored-key": binascii.b2a_hex(stored_key).decode('ascii'),
"server-key": binascii.b2a_hex(server_key).decode('ascii'),
}
print(json.dumps(key, indent=4))
|