-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnsec3hash.py
executable file
·68 lines (51 loc) · 1.71 KB
/
nsec3hash.py
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
63
64
65
66
67
68
#!/usr/bin/env python3
"""
nsec3 hash calculator
"""
import os
import sys
import hashlib
import base64
import dns.name
B32_TO_EXT_HEX = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
b'0123456789ABCDEFGHIJKLMNOPQRSTUV')
def usage():
"""Print usage string and exit"""
print("""\
Usage: {0} <salt> <algorithm> <iterations> <domain-name>
salt: salt in hexadecimal string form
algorithm: must be 1 (SHA1)
iterations: number of iterations of the hash function
domain-name: the domain-name
""".format(PROGNAME))
sys.exit(1)
def hashalg(algnum):
"""Return hash function corresponding to hash algorithm number"""
if algnum == 1:
return hashlib.sha1
else:
raise ValueError("unsupported NSEC3 hash algorithm {}".format(algnum))
def nsec3hash(name, algnum, salt, iterations, binary_out=False):
"""Compute NSEC3 hash for given domain name and parameters"""
if iterations < 0:
raise ValueError("iterations must be >= 0")
wire_name = dns.name.from_text(name).canonicalize().to_wire()
wire_salt = bytes.fromhex(salt)
hashfunc = hashalg(algnum)
digest = wire_name
while iterations >= 0:
digest = hashfunc(digest + wire_salt).digest()
iterations -= 1
if binary_out:
return digest
output = base64.b32encode(digest)
output = output.translate(B32_TO_EXT_HEX).decode()
return output
if __name__ == '__main__':
PROGNAME = os.path.basename(sys.argv[0])
if len(sys.argv) != 5:
usage()
SALT, ALGNUM, ITERATIONS, NAME = sys.argv[1:5]
ALGNUM = int(ALGNUM)
ITERATIONS = int(ITERATIONS)
print(nsec3hash(NAME, ALGNUM, SALT, ITERATIONS))