Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Calculate DS record from DNSKEY with Python 3
"""
Generate a DNSSEC DS record based on the incoming DNSKEY record
The DNSKEY can be found using for example 'dig':
$ dig DNSKEY secure.widodh.nl
The output can then be parsed with the following code to generate a DS record
for in the parent DNS zone
Author: Wido den Hollander <wido@widodh.nl>
Many thanks to this blogpost: https://www.v13.gr/blog/?p=239
"""
import struct
import base64
import hashlib
DOMAIN = 'secure.widodh.nl'
DNSKEY = '257 3 8 AwEAAckZ+lfb0j6aHBW5AanV5A0V0IfF99vAKFZd6+fJfEChpZtjnItWDnJLPa3/LAFec/tUhLZ4jgmzaoEuX3EQQgI1V4kp9SYf8HMlFPP014eO+AnjkYFGLE2uqHPx/Tu7/pO3EyKwTXi5fMadROKuo/mfat5AEIhGjteGGO93DhnOa6kcqj5RHYJBh5OZ/GoZfbeYHK6Muur1T16hHiI12rYGoqJ6ZW5+njYprG6qwp6TZXxJyE7wF1JdD+Zhbjhf0Md4zMEysP22wBLghBaX6eDIBh/7jU7dw1Ob+I42YWk+X4NSiU3sRYPaq1R13JEK4zVqQtL++UVtgRPEbfj5RQ8='
def _calc_keyid(flags, protocol, algorithm, dnskey):
st = struct.pack('!HBB', int(flags), int(protocol), int(algorithm))
st += base64.b64decode(dnskey)
cnt = 0
for idx in range(len(st)):
s = struct.unpack('B', st[idx:idx+1])[0]
if (idx % 2) == 0:
cnt += s << 8
else:
cnt += s
return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF
def _calc_ds(domain, flags, protocol, algorithm, dnskey):
if domain.endswith('.') is False:
domain += '.'
signature = bytes()
for i in domain.split('.'):
signature += struct.pack('B', len(i)) + i.encode()
signature += struct.pack('!HBB', int(flags), int(protocol), int(algorithm))
signature += base64.b64decode(dnskey)
return {
'sha1': hashlib.sha1(signature).hexdigest().upper(),
'sha256': hashlib.sha256(signature).hexdigest().upper(),
}
def dnskey_to_ds(domain, dnskey):
dnskeylist = dnskey.split(' ', 3)
flags = dnskeylist[0]
protocol = dnskeylist[1]
algorithm = dnskeylist[2]
key = dnskeylist[3].replace(' ', '')
keyid = _calc_keyid(flags, protocol, algorithm, key)
ds = _calc_ds(domain, flags, protocol, algorithm, key)
ret = list()
ret.append(str(keyid) + ' ' + str(algorithm) + ' ' + str(1) + ' '
+ ds['sha1'].lower())
ret.append(str(keyid) + ' ' + str(algorithm) + ' ' + str(2) + ' '
+ ds['sha256'].lower())
return ret
print(dnskey_to_ds(DOMAIN, DNSKEY))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment