Skip to content

Instantly share code, notes, and snippets.

@gwire
Created December 26, 2016 16:14
Show Gist options
  • Save gwire/3e361f53e44a419ed4cdb91986d91339 to your computer and use it in GitHub Desktop.
Save gwire/3e361f53e44a419ed4cdb91986d91339 to your computer and use it in GitHub Desktop.
takes an RSA public key on stdin and outputs a tinydns / djbdns DKIM record
#!/usr/bin/env python
# tinydkim - takes an RSA public key on stdin and outputs a tinydns / djbdns DKIM record
#
# example: openssl rsa -in test.pem -pubout | ./tinydkim.py -s test -d foo.com
#
# TODO: add support for notes field?
#
# 2016 Lee Maguire
import getopt
import sys
import re
bind = ''
opt_h = ''
opt_t = ''
ttl = "86400"
selector = "selector"
domain = "example.com"
def extractPubKey( key ):
output = ""
key = key.replace('-----BEGIN PUBLIC KEY-----','')
key = key.replace('-----END PUBLIC KEY-----','')
key = key.replace('-----BEGIN RSA PUBLIC KEY-----','')
key = key.replace('-----END RSA PUBLIC KEY-----','')
for c in key:
if not c in ["\r","\n","\t"," "]:
output = output + c
return( output );
def escapeText( text ):
output = ""
for c in text:
if c in ["\r","\n","\t",":"," ","\\","/"]:
output = output + "\\{0:03o}".format(ord(c))
else:
output = output + c
return( output );
def dnsQuotedText( text ):
output = ""
for c in text:
if c in [";"]:
output = output + "\\;"
else:
output = output + c
return( "\"" + output + "\"");
def characterCount( text ):
return( "\\{0:03o}".format(len(text)) );
def tinyTxtRecord( domain, record, ttl):
return(":" + escapeText( domain ) + ":16:" + characterCount( record ) + escapeText( record ) + ":" + ttl);
def dnsTxtRecord( domain, record, ttl):
return(domain + ". " + ttl + " IN TXT " + dnsQuotedText( record ) );
opts, args = getopt.getopt(sys.argv[1:],"hs:d:t:l:b",["selector=","domain=","hash=","testing=","ttl=","bind"])
for opt, arg in opts:
if opt == '-h':
print 'Usage: tinydkim.py -s selector -d example.com -t y < pubkey.pem'
sys.exit()
elif opt in ("-s", "--selector"):
selector = arg
elif opt in ("-d", "--domain"):
domain = arg
elif opt in ("-h", "--hash"):
opt_h = arg
elif opt in ("-t", "--testing"):
opt_t = arg
elif opt in ("-l", "--ttl"):
ttl = arg
elif opt in ("-b", "--bind"):
bind = 1
input_text = "".join(sys.stdin)
rdata = "v=DKIM1"
if opt_h:
rdata = rdata + "; h=" + opt_h
rdata = rdata + "; p=" + extractPubKey( input_text )
if opt_t:
rdata = rdata + "; t=" + opt_t
fqdn = selector + "._domainkey." + domain
line = tinyTxtRecord( fqdn, rdata, ttl )
sys.stdout.write( line + "\n")
## optionally output the format used by lookup tools for comparison
if bind:
line = dnsTxtRecord( fqdn, rdata, ttl )
sys.stdout.write( "\n# " + line + "\n" )
sys.exit(0)
@gwire
Copy link
Author

gwire commented Dec 26, 2016

Example output:

$ openssl genrsa -out test.pem 1024
Generating RSA private key, 1024 bit long modulus
....++++++
............................................................++++++
e is 65537 (0x10001)
$ openssl rsa -in test.pem -pubout | ./tinydkim.py -s test -d foo.com -b
writing RSA key
:test._domainkey.foo.com:16:\343v=DKIM1;\040p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDh4t9Me2ZUPaGkyG\057yqMwLcGzEA9BtG7pVeziGFwzgxSu+3VI85e59ip0JrzV2OFyc+2+rlNc7YDDXSHXvHh7q7BpHaRFD\0576OofN3UPwi0WiWZwLOntM+NdmnNJa9dKU+eOD7Orancn7T\0574mtntC1YQa0PAWGKiL0IxZtSnscIlwIDAQAB:86400

# test._domainkey.foo.com. 86400 IN TXT "v=DKIM1\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDh4t9Me2ZUPaGkyG/yqMwLcGzEA9BtG7pVeziGFwzgxSu+3VI85e59ip0JrzV2OFyc+2+rlNc7YDDXSHXvHh7q7BpHaRFD/6OofN3UPwi0WiWZwLOntM+NdmnNJa9dKU+eOD7Orancn7T/4mtntC1YQa0PAWGKiL0IxZtSnscIlwIDAQAB"
$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment