From f8f500718befb8594a90e42d62af27097ea542a1 Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Fri, 28 Apr 2023 13:57:45 +0200 Subject: [PATCH 1/9] wip --- bin/dnssec | 45 ++++++++++++++++++++++++++++++++++++++++++ bundles/bind/README.md | 26 ++++++++++++++++++++++++ libs/rsa.py | 9 ++++----- 3 files changed, 75 insertions(+), 5 deletions(-) create mode 100755 bin/dnssec create mode 100644 bundles/bind/README.md diff --git a/bin/dnssec b/bin/dnssec new file mode 100755 index 0000000..3015fed --- /dev/null +++ b/bin/dnssec @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +from os.path import realpath, dirname +from bundlewrap.repo import Repository +from base64 import b64decode, urlsafe_b64encode +from jwkest import long_to_base64 +from cryptography.utils import int_to_bytes + +def long_to_base64(n): + return urlsafe_b64encode(int_to_bytes(n, None)).decode() + +#repo = Repository(dirname(dirname(realpath(__file__)))) +repo = Repository('.') +domain = 'ckn.li' + +pk = repo.libs.rsa.generate_deterministic_rsa_private_key( + b64decode(str(repo.vault.random_bytes_as_base64_for('dnssec' + domain))) +) + +# https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers +# https://crypto.stackexchange.com/a/21104 +public_exponent = pk.private_numbers().public_numbers.e +modulo = pk.private_numbers().public_numbers.n +private_exponent = pk.private_numbers().d +prime1 = pk.private_numbers().p +prime2 = pk.private_numbers().q +exponent1 = pk.private_numbers().dmp1 +exponent2 = pk.private_numbers().dmq1 +coefficient = pk.private_numbers().iqmp + +print(f""" +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +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 +""") diff --git a/bundles/bind/README.md b/bundles/bind/README.md new file mode 100644 index 0000000..5f69096 --- /dev/null +++ b/bundles/bind/README.md @@ -0,0 +1,26 @@ +## DNSSEC + +https://wiki.debian.org/DNSSEC%20Howto%20for%20BIND%209.9+#The_signing_part +https://blog.apnic.net/2021/11/02/dnssec-provisioning-automation-with-cds-cdnskey-in-the-real-world/ +https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a + +```python +import dns.dnssec +algorithm = dns.dnssec.RSASHA256 +``` + +```python +import cryptography +pk = cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key(key_size=2048, public_exponent=65537) +``` + +## Nomenclature + +### parent + +DNSKEY: + the public key + +DS + + diff --git a/libs/rsa.py b/libs/rsa.py index e2666fb..a16e065 100644 --- a/libs/rsa.py +++ b/libs/rsa.py @@ -1,7 +1,6 @@ # https://stackoverflow.com/a/18266970 from Crypto.PublicKey import RSA -from Crypto.Hash import HMAC from struct import pack from hashlib import sha3_512 from cryptography.hazmat.primitives.serialization import load_der_private_key @@ -23,12 +22,12 @@ class PRNG(object): @cache_to_disk(30) -def _generate_deterministic_rsa_private_key(secret_bytes): - return RSA.generate(2048, randfunc=PRNG(secret_bytes)).export_key('DER') +def _generate_deterministic_rsa_private_key(secret_bytes, key_size): + return RSA.generate(key_size, randfunc=PRNG(secret_bytes)).export_key('DER') @cache -def generate_deterministic_rsa_private_key(secret_bytes): +def generate_deterministic_rsa_private_key(secret_bytes, key_size=2048): return load_der_private_key( - _generate_deterministic_rsa_private_key(secret_bytes), + _generate_deterministic_rsa_private_key(secret_bytes, key_size), password=None, ) -- 2.39.5 From 354663396991939ec182537ca4a811effa6e90ea Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Fri, 28 Apr 2023 13:58:14 +0200 Subject: [PATCH 2/9] wip --- bin/dnssec | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/dnssec b/bin/dnssec index 3015fed..45482a0 100755 --- a/bin/dnssec +++ b/bin/dnssec @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -from os.path import realpath, dirname from bundlewrap.repo import Repository from base64 import b64decode, urlsafe_b64encode from jwkest import long_to_base64 -- 2.39.5 From 1bf795c2627e7b766cd9f2cad9e3b4b0f9bbb3df Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Fri, 28 Apr 2023 14:23:19 +0200 Subject: [PATCH 3/9] wip --- bin/dnssec | 60 ++++++++++++++++++++++++++++-------- bundles/opendkim/metadata.py | 2 -- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/bin/dnssec b/bin/dnssec index 45482a0..ab30120 100755 --- a/bin/dnssec +++ b/bin/dnssec @@ -1,31 +1,38 @@ #!/usr/bin/env python3 +from sys import argv +from os.path import realpath, dirname from bundlewrap.repo import Repository from base64 import b64decode, urlsafe_b64encode -from jwkest import long_to_base64 from cryptography.utils import int_to_bytes +from cryptography.hazmat.primitives import serialization as crypto_serialization +from struct import pack +from hashlib import sha1, sha256 + def long_to_base64(n): return urlsafe_b64encode(int_to_bytes(n, None)).decode() -#repo = Repository(dirname(dirname(realpath(__file__)))) -repo = Repository('.') -domain = 'ckn.li' +domain = argv[1] +repo = Repository(dirname(dirname(realpath(__file__)))) +#repo = Repository('.') -pk = repo.libs.rsa.generate_deterministic_rsa_private_key( +# Private Key + +priv = repo.libs.rsa.generate_deterministic_rsa_private_key( b64decode(str(repo.vault.random_bytes_as_base64_for('dnssec' + domain))) ) # https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers # https://crypto.stackexchange.com/a/21104 -public_exponent = pk.private_numbers().public_numbers.e -modulo = pk.private_numbers().public_numbers.n -private_exponent = pk.private_numbers().d -prime1 = pk.private_numbers().p -prime2 = pk.private_numbers().q -exponent1 = pk.private_numbers().dmp1 -exponent2 = pk.private_numbers().dmq1 -coefficient = pk.private_numbers().iqmp +public_exponent = priv.private_numbers().public_numbers.e +modulo = priv.private_numbers().public_numbers.n +private_exponent = priv.private_numbers().d +prime1 = priv.private_numbers().p +prime2 = priv.private_numbers().q +exponent1 = priv.private_numbers().dmp1 +exponent2 = priv.private_numbers().dmq1 +coefficient = priv.private_numbers().iqmp print(f""" Private-key-format: v1.3 @@ -42,3 +49,30 @@ Created: 20230428110109 Publish: 20230428110109 Activate: 20230428110109 """) + +# DNSKEY + +pub = priv.public_key() + +dnskey = ''.join(pub.public_bytes( + crypto_serialization.Encoding.PEM, + crypto_serialization.PublicFormat.SubjectPublicKeyInfo +).decode().split('\n')[1:-2]) + +value = f"256 3 8 {dnskey}" +print(f""" +{domain}. IN DNSKEY {value} +""") + +# DS +# https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a#file-dnskey_to_dsrecord-py-L40 + +signature = bytes() +for i in domain.split('.'): + signature += pack('B', len(i)) + i.encode() + +signature += pack('!HBB', 256, 3, 8) +signature += dnskey.encode() + +print(sha1(signature).hexdigest().upper()) +print(sha256(signature).hexdigest().upper()) diff --git a/bundles/opendkim/metadata.py b/bundles/opendkim/metadata.py index 151f7c2..052c4fe 100644 --- a/bundles/opendkim/metadata.py +++ b/bundles/opendkim/metadata.py @@ -1,7 +1,5 @@ -from os.path import join, exists from re import sub from cryptography.hazmat.primitives import serialization as crypto_serialization -from cryptography.hazmat.primitives.asymmetric import rsa from base64 import b64decode -- 2.39.5 From b1ea126c2adbc0d1c19e3520c3e3f57d414295a8 Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Fri, 28 Apr 2023 14:40:04 +0200 Subject: [PATCH 4/9] wip --- bin/dnssec | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/bin/dnssec b/bin/dnssec index ab30120..b76028f 100755 --- a/bin/dnssec +++ b/bin/dnssec @@ -6,7 +6,7 @@ from bundlewrap.repo import Repository from base64 import b64decode, urlsafe_b64encode from cryptography.utils import int_to_bytes from cryptography.hazmat.primitives import serialization as crypto_serialization -from struct import pack +from struct import pack, unpack from hashlib import sha1, sha256 @@ -17,6 +17,11 @@ domain = argv[1] repo = Repository(dirname(dirname(realpath(__file__)))) #repo = Repository('.') +flags = 256 +protocol = 3 +algorithm = 8 +algorithm_name = 'RSASHA256' + # Private Key priv = repo.libs.rsa.generate_deterministic_rsa_private_key( @@ -36,7 +41,7 @@ coefficient = priv.private_numbers().iqmp print(f""" Private-key-format: v1.3 -Algorithm: 8 (RSASHA256) +Algorithm: {algorithm} ({algorithm_name}) Modulus: {long_to_base64(modulo)} PublicExponent: {long_to_base64(public_exponent)} PrivateExponent: {long_to_base64(private_exponent)} @@ -59,7 +64,7 @@ dnskey = ''.join(pub.public_bytes( crypto_serialization.PublicFormat.SubjectPublicKeyInfo ).decode().split('\n')[1:-2]) -value = f"256 3 8 {dnskey}" +value = f"{flags} {protocol} {algorithm} {dnskey}" print(f""" {domain}. IN DNSKEY {value} """) @@ -67,12 +72,39 @@ print(f""" # DS # https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a#file-dnskey_to_dsrecord-py-L40 -signature = bytes() -for i in domain.split('.'): - signature += pack('B', len(i)) + i.encode() -signature += pack('!HBB', 256, 3, 8) -signature += dnskey.encode() +def _calc_ds(domain, flags, protocol, algorithm, dnskey): + if domain.endswith('.') is False: + domain += '.' -print(sha1(signature).hexdigest().upper()) -print(sha256(signature).hexdigest().upper()) + signature = bytes() + for i in domain.split('.'): + signature += pack('B', len(i)) + i.encode() + + signature += pack('!HBB', int(flags), int(protocol), int(algorithm)) + signature += b64decode(dnskey) + + return { + 'sha1': sha1(signature).hexdigest().upper(), + 'sha256': sha256(signature).hexdigest().upper(), + } + +def _calc_keyid(flags, protocol, algorithm, dnskey): + st = pack('!HBB', int(flags), int(protocol), int(algorithm)) + st += b64decode(dnskey) + + cnt = 0 + for idx in range(len(st)): + s = unpack('B', st[idx:idx+1])[0] + if (idx % 2) == 0: + cnt += s << 8 + else: + cnt += s + + return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF + +keyid = _calc_keyid(flags, protocol, algorithm, dnskey) +ds = _calc_ds(domain, flags, protocol, algorithm, dnskey) + +print(f"{domain}. IN DS {str(keyid)} {str(algorithm)} 1 {ds['sha1'].lower()}") +print(f"{domain}. IN DS {str(keyid)} {str(algorithm)} 2 {ds['sha256'].lower()}") -- 2.39.5 From 8b296ba6db41a612ba4c26c4c355114bacdcf085 Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Fri, 28 Apr 2023 15:26:16 +0200 Subject: [PATCH 5/9] wip --- bundles/bind/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bundles/bind/README.md b/bundles/bind/README.md index 5f69096..bd78bcc 100644 --- a/bundles/bind/README.md +++ b/bundles/bind/README.md @@ -23,4 +23,7 @@ DNSKEY: DS +### sub +ZSK/KSK: + https://www.cloudflare.com/de-de/dns/dnssec/how-dnssec-works/ -- 2.39.5 From cadb32cffddf5cb898b780a849e52729800feb21 Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Fri, 28 Apr 2023 16:31:33 +0200 Subject: [PATCH 6/9] wip --- bin/dnssec | 118 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 49 deletions(-) diff --git a/bin/dnssec b/bin/dnssec index b76028f..a935bbf 100755 --- a/bin/dnssec +++ b/bin/dnssec @@ -8,12 +8,13 @@ from cryptography.utils import int_to_bytes from cryptography.hazmat.primitives import serialization as crypto_serialization from struct import pack, unpack from hashlib import sha1, sha256 +from json import dumps def long_to_base64(n): return urlsafe_b64encode(int_to_bytes(n, None)).decode() -domain = argv[1] +zone = argv[1] repo = Repository(dirname(dirname(realpath(__file__)))) #repo = Repository('.') @@ -22,63 +23,63 @@ protocol = 3 algorithm = 8 algorithm_name = 'RSASHA256' -# Private Key +def generate_signing_key_pair(zone, salt=''): + priv = repo.libs.rsa.generate_deterministic_rsa_private_key( + b64decode(str(repo.vault.random_bytes_as_base64_for(f'dnssec {salt} ' + zone))) + ) -priv = repo.libs.rsa.generate_deterministic_rsa_private_key( - b64decode(str(repo.vault.random_bytes_as_base64_for('dnssec' + domain))) -) + # https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers + # https://crypto.stackexchange.com/a/21104 + public_exponent = priv.private_numbers().public_numbers.e + modulo = priv.private_numbers().public_numbers.n + private_exponent = priv.private_numbers().d + prime1 = priv.private_numbers().p + prime2 = priv.private_numbers().q + exponent1 = priv.private_numbers().dmp1 + exponent2 = priv.private_numbers().dmq1 + coefficient = priv.private_numbers().iqmp -# https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers -# https://crypto.stackexchange.com/a/21104 -public_exponent = priv.private_numbers().public_numbers.e -modulo = priv.private_numbers().public_numbers.n -private_exponent = priv.private_numbers().d -prime1 = priv.private_numbers().p -prime2 = priv.private_numbers().q -exponent1 = priv.private_numbers().dmp1 -exponent2 = priv.private_numbers().dmq1 -coefficient = priv.private_numbers().iqmp + dnskey = ''.join(priv.public_key().public_bytes( + crypto_serialization.Encoding.PEM, + crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ).decode().split('\n')[1:-2]) + + return { + 'dnskey': dnskey, + '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 -print(f""" -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.PublicFormat.SubjectPublicKeyInfo -).decode().split('\n')[1:-2]) - -value = f"{flags} {protocol} {algorithm} {dnskey}" -print(f""" -{domain}. IN DNSKEY {value} -""") # DS # https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a#file-dnskey_to_dsrecord-py-L40 - -def _calc_ds(domain, flags, protocol, algorithm, dnskey): - if domain.endswith('.') is False: - domain += '.' +def _calc_ds(zone, flags, protocol, algorithm, dnskey): + if zone.endswith('.') is False: + zone += '.' signature = bytes() - for i in domain.split('.'): + for i in zone.split('.'): signature += pack('B', len(i)) + i.encode() 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 -keyid = _calc_keyid(flags, protocol, algorithm, dnskey) -ds = _calc_ds(domain, flags, protocol, algorithm, dnskey) +def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey): + keyid = _calc_keyid(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()}") -print(f"{domain}. IN DS {str(keyid)} {str(algorithm)} 2 {ds['sha256'].lower()}") + return[ + 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, +)) -- 2.39.5 From 96c2df1c09ff9c508b1409b64a06c496464fde27 Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Fri, 28 Apr 2023 16:34:39 +0200 Subject: [PATCH 7/9] wip --- bin/dnssec | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/bin/dnssec b/bin/dnssec index a935bbf..c56c18f 100755 --- a/bin/dnssec +++ b/bin/dnssec @@ -16,20 +16,22 @@ def long_to_base64(n): zone = argv[1] repo = Repository(dirname(dirname(realpath(__file__)))) -#repo = Repository('.') flags = 256 protocol = 3 algorithm = 8 algorithm_name = 'RSASHA256' +# ZSK/KSK DNSKEY +# +# https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers +# https://crypto.stackexchange.com/a/21104 + def generate_signing_key_pair(zone, salt=''): priv = repo.libs.rsa.generate_deterministic_rsa_private_key( 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://crypto.stackexchange.com/a/21104 public_exponent = priv.private_numbers().public_numbers.e modulo = priv.private_numbers().public_numbers.n private_exponent = priv.private_numbers().d @@ -64,14 +66,9 @@ def generate_signing_key_pair(zone, salt=''): }, } -# ZSK - - -# DNSKEY - - # DS +# # https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a#file-dnskey_to_dsrecord-py-L40 def _calc_ds(zone, flags, protocol, algorithm, dnskey): @@ -113,6 +110,8 @@ def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey): f"{zone}. IN DS {str(keyid)} {str(algorithm)} 2 {ds['sha256'].lower()}", ] +# Result + def generate_dnssec_for_zone(zone): zsk_data = generate_signing_key_pair(zone, salt='zsk') ksk_data = generate_signing_key_pair(zone, salt='ksk') -- 2.39.5 From 13e52027cf1d0f0d7a0009a8d4fc66e2cf03c25d Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Thu, 4 May 2023 12:46:37 +0200 Subject: [PATCH 8/9] wip --- bin/dnssec | 96 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/bin/dnssec b/bin/dnssec index c56c18f..7d49b43 100755 --- a/bin/dnssec +++ b/bin/dnssec @@ -1,5 +1,10 @@ #!/usr/bin/env python3 +# https://medium.com/iocscan/how-dnssec-works-9c652257be0 +# https://de.wikipedia.org/wiki/RRSIG_Resource_Record +# https://metebalci.com/blog/a-minimum-complete-tutorial-of-dnssec/ +# https://bind9.readthedocs.io/en/latest/dnssec-guide.html + from sys import argv from os.path import realpath, dirname from bundlewrap.repo import Repository @@ -9,6 +14,7 @@ from cryptography.hazmat.primitives import serialization as crypto_serialization from struct import pack, unpack from hashlib import sha1, sha256 from json import dumps +from cache_to_disk import cache_to_disk def long_to_base64(n): @@ -27,21 +33,21 @@ algorithm_name = 'RSASHA256' # https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers # https://crypto.stackexchange.com/a/21104 -def generate_signing_key_pair(zone, salt=''): - priv = repo.libs.rsa.generate_deterministic_rsa_private_key( +def generate_signing_key_pair(zone, salt): + privkey = repo.libs.rsa.generate_deterministic_rsa_private_key( b64decode(str(repo.vault.random_bytes_as_base64_for(f'dnssec {salt} ' + zone))) ) - public_exponent = priv.private_numbers().public_numbers.e - modulo = priv.private_numbers().public_numbers.n - private_exponent = priv.private_numbers().d - prime1 = priv.private_numbers().p - prime2 = priv.private_numbers().q - exponent1 = priv.private_numbers().dmp1 - exponent2 = priv.private_numbers().dmq1 - coefficient = priv.private_numbers().iqmp + public_exponent = privkey.private_numbers().public_numbers.e + modulo = privkey.private_numbers().public_numbers.n + private_exponent = privkey.private_numbers().d + prime1 = privkey.private_numbers().p + prime2 = privkey.private_numbers().q + exponent1 = privkey.private_numbers().dmp1 + exponent2 = privkey.private_numbers().dmq1 + coefficient = privkey.private_numbers().iqmp - dnskey = ''.join(priv.public_key().public_bytes( + dnskey = ''.join(privkey.public_key().public_bytes( crypto_serialization.Encoding.PEM, crypto_serialization.PublicFormat.SubjectPublicKeyInfo ).decode().split('\n')[1:-2]) @@ -49,7 +55,8 @@ def generate_signing_key_pair(zone, salt=''): return { 'dnskey': dnskey, 'dnskey_record': f'{zone}. IN DNSKEY {flags} {protocol} {algorithm} {dnskey}', - 'privkey': { + 'privkey': privkey, + 'privkey_file': { 'Private-key-format': 'v1.3', 'Algorithm': f'{algorithm} ({algorithm_name})', 'Modulus': long_to_base64(modulo), @@ -112,6 +119,7 @@ def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey): # Result +#@cache_to_disk(30) def generate_dnssec_for_zone(zone): zsk_data = generate_signing_key_pair(zone, salt='zsk') ksk_data = generate_signing_key_pair(zone, salt='ksk') @@ -123,7 +131,65 @@ def generate_dnssec_for_zone(zone): 'ds_records': ds_records, } -print(dumps( +print( generate_dnssec_for_zone(zone), - indent=4, -)) +) + + +# ######################### + +# from dns import rrset, rdatatype, rdata +# from dns.rdataclass import IN +# from dns.dnssec import sign, make_dnskey +# from dns.name import Name +# from dns.rdtypes.IN.A import A + +# data = generate_dnssec_for_zone(zone) +# zone_name = Name(f'{zone}.'.split('.')) +# assert zone_name.is_absolute() + +# # rrset = rrset.from_text_list( +# # name=Name(['test']).derelativize(zone_name), +# # origin=zone_name, +# # relativize=False, +# # ttl=60, +# # rdclass=IN, +# # rdtype=rdatatype.from_text('A'), +# # text_rdatas=[ +# # '100.2.3.4', +# # '10.0.0.55', +# # ], +# # ) + +# rrset = rrset.from_rdata_list( +# name=Name(['test']).derelativize(zone_name), +# ttl=60, +# rdatas=[ +# rdata.from_text( +# rdclass=IN, +# rdtype=rdatatype.from_text('A'), +# origin=zone_name, +# tok='1.2.3.4', +# relativize=False, +# ), +# A(IN, rdatatype.from_text('A'), '10.20.30.40') +# ], +# ) + +# # for e in rrset: +# # print(e.is_absolute()) + +# dnskey = make_dnskey( +# public_key=data['zsk_data']['privkey'].public_key(), +# algorithm=algorithm, +# flags=flags, +# protocol=protocol, +# ) + +# sign( +# rrset=rrset, +# private_key=data['zsk_data']['privkey'], +# signer=Name(f'{zone}.'), +# dnskey=dnskey, +# lifetime=99999, +# ) -- 2.39.5 From cdf79c2bd853b4a32448945c43b66248452ad867 Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Mon, 8 May 2023 16:27:32 +0200 Subject: [PATCH 9/9] wip --- bin/test | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100755 bin/test diff --git a/bin/test b/bin/test new file mode 100755 index 0000000..f8f6ae3 --- /dev/null +++ b/bin/test @@ -0,0 +1,47 @@ +import dns.zone +import dns.rdatatype +import dns.rdataclass +import dns.dnssec + +# Define the zone name and domain names +zone_name = 'example.com.' +a_name = 'www.example.com.' +txt_name = 'example.com.' +mx_name = 'example.com.' + +# Define the DNSKEY algorithm and size +algorithm = 8 +key_size = 2048 + +# Generate the DNSSEC key pair +keypair = dns.dnssec.make_dnskey(algorithm, key_size) + +# Create the zone +zone = dns.zone.Zone(origin=zone_name) + +# Add A record to zone +a_rrset = zone.get_rdataset(a_name, rdtype=dns.rdatatype.A, create=True) +a_rrset.add(dns.rdataclass.IN, dns.rdatatype.A, '192.0.2.1') + +# Add TXT record to zone +txt_rrset = zone.get_rdataset(txt_name, rdtype=dns.rdatatype.TXT, create=True) +txt_rrset.add(dns.rdataclass.IN, dns.rdatatype.TXT, 'Hello, world!') + +# Add MX record to zone +mx_rrset = zone.get_rdataset(mx_name, rdtype=dns.rdatatype.MX, create=True) +mx_rrset.add(dns.rdataclass.IN, dns.rdatatype.MX, '10 mail.example.com.') + +# Create the DNSKEY record for the zone +key_name = f'{keypair.name}-K{keypair.fingerprint()}' +dnskey_rrset = dns.rrset.RRset(name=keypair.name, rdclass=dns.rdataclass.IN, rdtype=dns.rdatatype.DNSKEY) +dnskey_rrset.ttl = 86400 +dnskey_rrset.add(dns.rdataclass.IN, dns.rdatatype.DNSKEY, keypair.key, key_name=key_name) + +# Add the DNSKEY record to the zone +zone.replace_rdataset(keypair.name, dnskey_rrset) + +# Sign the zone with the DNSSEC key pair +dns.dnssec.sign_zone(zone, keypair, inception=0, expiration=3600) + +# Print the resulting zone with the RRSIG records +print(zone.to_text()) -- 2.39.5