This commit is contained in:
cronekorkn 2023-04-28 16:31:33 +02:00
parent 8b296ba6db
commit cadb32cffd
Signed by: cronekorkn
SSH key fingerprint: SHA256:v0410ZKfuO1QHdgKBsdQNF64xmTxOF8osF1LIqwTcVw

View file

@ -8,12 +8,13 @@ from cryptography.utils import int_to_bytes
from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives import serialization as crypto_serialization
from struct import pack, unpack from struct import pack, unpack
from hashlib import sha1, sha256 from hashlib import sha1, sha256
from json import dumps
def long_to_base64(n): def long_to_base64(n):
return urlsafe_b64encode(int_to_bytes(n, None)).decode() return urlsafe_b64encode(int_to_bytes(n, None)).decode()
domain = argv[1] zone = argv[1]
repo = Repository(dirname(dirname(realpath(__file__)))) repo = Repository(dirname(dirname(realpath(__file__))))
#repo = Repository('.') #repo = Repository('.')
@ -22,10 +23,9 @@ protocol = 3
algorithm = 8 algorithm = 8
algorithm_name = 'RSASHA256' algorithm_name = 'RSASHA256'
# Private Key def generate_signing_key_pair(zone, salt=''):
priv = repo.libs.rsa.generate_deterministic_rsa_private_key( priv = repo.libs.rsa.generate_deterministic_rsa_private_key(
b64decode(str(repo.vault.random_bytes_as_base64_for('dnssec' + domain))) b64decode(str(repo.vault.random_bytes_as_base64_for(f'dnssec {salt} ' + zone)))
) )
# https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers # https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers
@ -39,46 +39,47 @@ exponent1 = priv.private_numbers().dmp1
exponent2 = priv.private_numbers().dmq1 exponent2 = priv.private_numbers().dmq1
coefficient = priv.private_numbers().iqmp coefficient = priv.private_numbers().iqmp
print(f""" dnskey = ''.join(priv.public_key().public_bytes(
Private-key-format: v1.3
Algorithm: {algorithm} ({algorithm_name})
Modulus: {long_to_base64(modulo)}
PublicExponent: {long_to_base64(public_exponent)}
PrivateExponent: {long_to_base64(private_exponent)}
Prime1: {long_to_base64(prime1)}
Prime2: {long_to_base64(prime2)}
Exponent1: {long_to_base64(exponent1)}
Exponent2: {long_to_base64(exponent2)}
Coefficient: {long_to_base64(coefficient)}
Created: 20230428110109
Publish: 20230428110109
Activate: 20230428110109
""")
# DNSKEY
pub = priv.public_key()
dnskey = ''.join(pub.public_bytes(
crypto_serialization.Encoding.PEM, crypto_serialization.Encoding.PEM,
crypto_serialization.PublicFormat.SubjectPublicKeyInfo crypto_serialization.PublicFormat.SubjectPublicKeyInfo
).decode().split('\n')[1:-2]) ).decode().split('\n')[1:-2])
value = f"{flags} {protocol} {algorithm} {dnskey}" return {
print(f""" 'dnskey': dnskey,
{domain}. IN DNSKEY {value} 'dnskey_record': f'{zone}. IN DNSKEY {flags} {protocol} {algorithm} {dnskey}',
""") 'privkey': {
'Private-key-format': 'v1.3',
'Algorithm': f'{algorithm} ({algorithm_name})',
'Modulus': long_to_base64(modulo),
'PublicExponent': long_to_base64(public_exponent),
'PrivateExponent': long_to_base64(private_exponent),
'Prime1': long_to_base64(prime1),
'Prime2': long_to_base64(prime2),
'Exponent1': long_to_base64(exponent1),
'Exponent2': long_to_base64(exponent2),
'Coefficient': long_to_base64(coefficient),
'Created': 20230428110109,
'Publish': 20230428110109,
'Activate': 20230428110109,
},
}
# ZSK
# DNSKEY
# DS # DS
# https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a#file-dnskey_to_dsrecord-py-L40 # https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a#file-dnskey_to_dsrecord-py-L40
def _calc_ds(zone, flags, protocol, algorithm, dnskey):
def _calc_ds(domain, flags, protocol, algorithm, dnskey): if zone.endswith('.') is False:
if domain.endswith('.') is False: zone += '.'
domain += '.'
signature = bytes() signature = bytes()
for i in domain.split('.'): for i in zone.split('.'):
signature += pack('B', len(i)) + i.encode() signature += pack('B', len(i)) + i.encode()
signature += pack('!HBB', int(flags), int(protocol), int(algorithm)) signature += pack('!HBB', int(flags), int(protocol), int(algorithm))
@ -103,8 +104,27 @@ def _calc_keyid(flags, protocol, algorithm, dnskey):
return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF
def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey):
keyid = _calc_keyid(flags, protocol, algorithm, dnskey) keyid = _calc_keyid(flags, protocol, algorithm, dnskey)
ds = _calc_ds(domain, flags, protocol, algorithm, dnskey) ds = _calc_ds(zone, flags, protocol, algorithm, dnskey)
print(f"{domain}. IN DS {str(keyid)} {str(algorithm)} 1 {ds['sha1'].lower()}") return[
print(f"{domain}. IN DS {str(keyid)} {str(algorithm)} 2 {ds['sha256'].lower()}") f"{zone}. IN DS {str(keyid)} {str(algorithm)} 1 {ds['sha1'].lower()}",
f"{zone}. IN DS {str(keyid)} {str(algorithm)} 2 {ds['sha256'].lower()}",
]
def generate_dnssec_for_zone(zone):
zsk_data = generate_signing_key_pair(zone, salt='zsk')
ksk_data = generate_signing_key_pair(zone, salt='ksk')
ds_records = dnskey_to_ds(zone, flags, protocol, algorithm, ksk_data['dnskey'])
return {
'zsk_data': zsk_data,
'ksk_data': ksk_data,
'ds_records': ds_records,
}
print(dumps(
generate_dnssec_for_zone(zone),
indent=4,
))