1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Generates new domainkeys pairs.
24
25 """
26
27
28 from __future__ import print_function
29 import os
30 import subprocess
31 import sys
32 import tempfile
33 import argparse
34 import hashlib
35 import base64
36
37
38 BITS_REQUIRED = 2048
39
40
41 OPENSSL_BINARY = '/usr/bin/openssl'
42
44 print(*args, file=sys.stderr, **kwargs)
45
47 """ Generates a suitable private key. Output is unprotected.
48 You should encrypt your keys.
49 """
50 eprint('generating ' + private_key_file)
51 subprocess.check_call([OPENSSL_BINARY, 'genrsa', '-out', private_key_file,
52 str(BITS_REQUIRED)])
53
55 """Generates a base64 encoded private key for ed25519 DKIM signing.
56 Output is unprotected. You should protect your keys.
57 """
58 import nacl.signing
59 import nacl.encoding
60 import os
61 skg = nacl.signing.SigningKey(seed=os.urandom(32))
62 eprint('generating ' + private_key_file)
63 priv_key = skg.generate()
64 with open(private_key_file, 'w') as pkf:
65 pkf.write(priv_key.encode(encoder=nacl.encoding.Base64Encoder).decode("utf-8"))
66 return(priv_key)
67
69 """ Given a key, extract the bit we should place in DNS.
70 """
71 eprint('extracting ' + private_key_file)
72 working_file = tempfile.NamedTemporaryFile(delete=False).name
73 subprocess.check_call([OPENSSL_BINARY, 'rsa', '-in', private_key_file,
74 '-out', working_file, '-pubout', '-outform', 'PEM'])
75 try:
76 with open(working_file) as wf:
77 y = ''
78 for line in wf.readlines():
79 if not line.startswith('---'):
80 y+= line
81 output = ''.join(y.split())
82 finally:
83 os.unlink(working_file)
84 with open(dns_file, 'w') as dns_fp:
85 eprint('writing ' + dns_file)
86 dns_fp.write("v=DKIM1; k=rsa; h=sha256; p={0}".format(output))
87
89 """ Given a ed25519 key, extract the bit we should place in DNS.
90 """
91 import nacl.encoding
92 pubkey = priv_key.verify_key
93 output = pubkey.encode(encoder=nacl.encoding.Base64Encoder).decode("utf-8")
94 with open(dns_file, 'w') as dns_fp:
95 eprint('writing ' + dns_file)
96 dns_fp.write("v=DKIM1; k=ed25519; p={0}".format(output))
97
99 parser = argparse.ArgumentParser(
100 description='Produce DKIM keys.',)
101 parser.add_argument('key_name', action="store")
102 parser.add_argument('--ktype', choices=['rsa', 'ed25519'],
103 default='rsa',
104 help='DKIM key type: Default is rsa')
105 args=parser.parse_args()
106
107 key_name = args.key_name
108 key_type = args.ktype
109 private_key_file = key_name + '.key'
110 dns_file = key_name + '.dns'
111
112 if key_type == 'rsa':
113 GenRSAKeys(private_key_file)
114 ExtractRSADnsPublicKey(private_key_file, dns_file)
115 elif key_type == 'ed25519':
116 priv_key = GenEd25519Keys(private_key_file)
117 ExtractEd25519PublicKey(dns_file, priv_key)
118 else:
119 eprint("Unknown key type - no key generated.")
120
121
122 if __name__ == '__main__':
123 main()
124