Package dkim :: Module dknewkey
[hide private]
[frames] | no frames]

Source Code for Module dkim.dknewkey

  1  #!/usr/bin/python 
  2  # This software is provided 'as-is', without any express or implied 
  3  # warranty.  In no event will the author be held liable for any damages 
  4  # arising from the use of this software. 
  5  # 
  6  # Permission is granted to anyone to use this software for any purpose, 
  7  # including commercial applications, and to alter it and redistribute it 
  8  # freely, subject to the following restrictions: 
  9  # 
 10  # 1. The origin of this software must not be misrepresented; you must not 
 11  #    claim that you wrote the original software. If you use this software 
 12  #    in a product, an acknowledgment in the product documentation would be 
 13  #    appreciated but is not required. 
 14  # 2. Altered source versions must be plainly marked as such, and must not be 
 15  #    misrepresented as being the original software. 
 16  # 3. This notice may not be removed or altered from any source distribution. 
 17  # 
 18  # Copyright (c) 2016 Google, Inc. 
 19  # Contact: Brandon Long <blong@google.com> 
 20  # Modified by Scott Kitterman <scott@kitterman.com> 
 21  # Copyright (c) 2017,2018 Scott Kitterman 
 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  # how strong are our keys? 
 38  BITS_REQUIRED = 2048 
 39   
 40  # what openssl binary do we use to do key manipulation? 
 41  OPENSSL_BINARY = '/usr/bin/openssl' 
 42   
43 -def eprint(*args, **kwargs):
44 print(*args, file=sys.stderr, **kwargs)
45
46 -def GenRSAKeys(private_key_file):
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
54 -def GenEd25519Keys(private_key_file):
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 # Yes, pep-8, but let's not make everyone install nacl 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
68 -def ExtractRSADnsPublicKey(private_key_file, dns_file):
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
88 -def ExtractEd25519PublicKey(dns_file, priv_key):
89 """ Given a ed25519 key, extract the bit we should place in DNS. 90 """ 91 import nacl.encoding # Yes, pep-8, but let's not make everyone install nacl 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
98 -def main():
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