- Add generation of rsafp DKIM signatures per

draft-ietf-dcrup-dkim-crypto-02
This commit is contained in:
Scott Kitterman
2017-06-23 18:29:37 -04:00
parent 80f663f02c
commit c7782addd5
5 changed files with 35 additions and 7 deletions
+16 -5
View File
@@ -49,6 +49,7 @@ from dkim.crypto import (
HASH_ALGORITHMS,
parse_pem_private_key,
parse_public_key,
get_rsa_pubkey,
RSASSA_PKCS1_v1_5_sign,
RSASSA_PKCS1_v1_5_verify,
UnparsableKeyError,
@@ -361,7 +362,7 @@ class DomainSigner(object):
#: @param logger: a logger to which debug info will be written (default None)
#: @param signature_algorithm: the signing algorithm to use when signing
def __init__(self,message=None,logger=None,signature_algorithm=b'rsa-sha256',
minkey=1024):
minkey=1024,ktype=b'rsa'):
self.set_message(message)
if logger is None:
logger = get_default_logger()
@@ -382,6 +383,8 @@ class DomainSigner(object):
#: Minimum public key size. Shorter keys raise KeyFormatError. The
#: default is 1024
self.minkey = minkey
#: Key type to use. rsa, rsafp (DCRUP)
self.ktype = ktype
#: Header fields to protect from additions by default.
#:
@@ -620,12 +623,16 @@ class DKIM(DomainSigner):
#: @raise DKIMException: when the message, include_headers, or key are badly
#: formed.
def sign(self, selector, domain, privkey, identity=None,
canonicalize=(b'relaxed',b'simple'), include_headers=None, length=False):
canonicalize=(b'relaxed',b'simple'), include_headers=None,
length=False):
try:
pk = parse_pem_private_key(privkey)
except UnparsableKeyError as e:
raise KeyFormatError(str(e))
if self.ktype == b'rsafp':
pubkey = get_rsa_pubkey(privkey)
else:
pubkey = False
if identity is not None and not identity.endswith(domain):
raise ParameterError("identity must end with domain")
@@ -653,10 +660,13 @@ class DKIM(DomainSigner):
h = self.hasher()
h.update(body)
bodyhash = base64.b64encode(h.digest())
if self.ktype == b'rsafp':
atag = b'rsafp-sha256'
else:
atag = self.signature_algorithm
sigfields = [x for x in [
(b'v', b"1"),
(b'a', self.signature_algorithm),
(b'a', atag),
(b'c', canon_policy.to_c_value()),
(b'd', domain),
(b'i', identity or b"@"+domain),
@@ -665,6 +675,7 @@ class DKIM(DomainSigner):
(b's', selector),
(b't', str(int(time.time())).encode('ascii')),
(b'h', b" : ".join(include_headers)),
pubkey and (b'k', pubkey),
(b'bh', bodyhash),
# Force b= to fold onto it's own line so that refolding after
# adding sig doesn't change whitespace for previous tags.