def test_sign(self): data = "Hello World!" for algorithm, hash_method in ( ("rsa-sha1", hashlib.sha1,), ("rsa-sha256", hashlib.sha256,), ): stream = MemoryStream(data) headers = Headers() headers.addRawHeader("Originator", "mailto:[email protected]") headers.addRawHeader("Recipient", "mailto:[email protected]") headers.setHeader("Content-Type", MimeType("text", "calendar", **{"component": "VEVENT", "charset": "utf-8"})) request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", self.private_keyfile, algorithm, ("Originator", "Recipient", "Content-Type",), True, True, True, 3600) result = (yield request.sign()) # Manually create what should be the correct thing to sign and make sure signatures match bodyhash = base64.b64encode(hash_method(DKIMUtils.canonicalizeBody(data)).digest()) sign_this = """originator:mailto:[email protected] recipient:mailto:[email protected] content-type:%s ischedule-version:1.0 ischedule-message-id:%s dkim-signature:v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=private-exchange:http/well-known:dns/txt; c=ischedule-relaxed/simple; h=Originator:Recipient:Content-Type:iSchedule-Version:iSchedule-Message-ID; bh=%s; b=""".replace("\n", "\r\n") % (headers.getRawHeaders("Content-Type")[0], request.message_id, request.time, request.expire, algorithm, bodyhash) key = RSA.importKey(open(self.private_keyfile).read()) signature = DKIMUtils.sign(sign_this, key, DKIMUtils.hash_func(algorithm)) self.assertEqual(result, signature) # Make sure header is updated in the request updated_header = "v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=private-exchange:http/well-known:dns/txt; c=ischedule-relaxed/simple; h=Originator:Recipient:Content-Type:iSchedule-Version:iSchedule-Message-ID; bh=%s; b=%s" % (request.time, request.expire, algorithm, bodyhash, signature,) self.assertEqual(request.headers.getRawHeaders("DKIM-Signature")[0], updated_header) # Try to verify result using public key pubkey = RSA.importKey(open(self.public_keyfile).read()) self.assertEqual(DKIMUtils.verify(sign_this, result, pubkey, DKIMUtils.hash_func(algorithm)), None)
def _verify(hdrs, body, keys, result, sign_headers=("Originator", "Recipient", "Content-Type",), manipulate_request=None): for algorithm in ("rsa-sha1", "rsa-sha256",): # Create signature stream = MemoryStream(body) headers = Headers() for name, value in [hdr.split(":", 1) for hdr in hdrs.splitlines()]: headers.addRawHeader(name, value) request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", self.private_keyfile, algorithm, sign_headers, True, True, True, 3600) yield request.sign() # Possibly munge the request after the signature is done if manipulate_request is not None: manipulate_request(request) # Verify signature TestPublicKeyLookup.PublicKeyLookup_Testing.keys = keys data = (yield allDataFromStream(request.stream)) verifier = DKIMVerifier(request.headers, data, key_lookup=(TestPublicKeyLookup.PublicKeyLookup_Testing,)) TestPublicKeyLookup.PublicKeyLookup_Testing({}).flushCache() try: yield verifier.verify() except Exception, e: if result: self.fail("DKIMVerifier:verify failed: %s" % (e,)) else: if not result: self.fail("DKIMVerifier:verify did not fail")
def test_generateSignature(self): data = "Hello World!" for algorithm, hash_method in ( ("rsa-sha1", hashlib.sha1,), ("rsa-sha256", hashlib.sha256,), ): stream = MemoryStream(data) headers = Headers() headers.addRawHeader("Originator", "mailto:[email protected]") headers.addRawHeader("Recipient", "mailto:[email protected]") headers.setHeader("Content-Type", MimeType("text", "calendar", **{"component": "VEVENT", "charset": "utf-8"})) request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", self.private_keyfile, algorithm, ("Originator", "Recipient", "Content-Type",), True, True, True, 3600) # Manually create what should be the correct thing to sign bodyhash = base64.b64encode(hash_method(data).digest()) sign_this = """originator:mailto:[email protected] recipient:mailto:[email protected] content-type:%s ischedule-version:1.0 dkim-signature:v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=%s; b=""".replace("\n", "\r\n") % (headers.getRawHeaders("Content-Type")[0], str(int(time.time())), str(int(time.time() + 3600)), algorithm, bodyhash) result = request.generateSignature(sign_this) key = RSA.importKey(open(self.private_keyfile).read()) signature = DKIMUtils.sign(sign_this, key, DKIMUtils.hash_func(algorithm)) self.assertEqual(result, signature)
def test_body_hash(self): data = "Hello World!" for algorithm, hash_method in ( ( "rsa-sha1", hashlib.sha1, ), ( "rsa-sha256", hashlib.sha256, ), ): stream = str(data) headers = Headers() headers.addRawHeader("Originator", "mailto:[email protected]") headers.addRawHeader("Recipient", "mailto:[email protected]") headers.setHeader( "Content-Type", MimeType("text", "calendar", **{ "component": "VEVENT", "charset": "utf-8" })) request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", "/tmp/key", algorithm, ( "Originator", "Recipient", "Content-Type", ), True, True, True, 3600) hash = base64.b64encode( hash_method(DKIMUtils.canonicalizeBody(data)).digest()) result = (yield request.bodyHash()) self.assertEqual(result, hash)
def test_body_hash(self): data = "Hello World!" for algorithm, hash_method in ( ("rsa-sha1", hashlib.sha1,), ("rsa-sha256", hashlib.sha256,), ): stream = str(data) headers = Headers() headers.addRawHeader("Originator", "mailto:[email protected]") headers.addRawHeader("Recipient", "mailto:[email protected]") headers.setHeader("Content-Type", MimeType("text", "calendar", **{"component": "VEVENT", "charset": "utf-8"})) request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", "/tmp/key", algorithm, ("Originator", "Recipient", "Content-Type",), True, True, True, 3600) hash = base64.b64encode(hash_method(DKIMUtils.canonicalizeBody(data)).digest()) result = (yield request.bodyHash()) self.assertEqual(result, hash)
def _doRequest(options): if options["verbose"]: log.publisher.levels.setLogLevelForNamespace("txdav.caldav.datastore.scheduling.ischedule.dkim", LogLevel.debug) # Parse the HTTP file request = open(options["request"]).read() method, uri, headers, stream = _parseRequest(request) # Setup signing headers sign_headers = options["signing"] if sign_headers is None: sign_headers = [] for hdr in ("Host", "Content-Type", "Originator", "Recipient+"): if headers.hasHeader(hdr.rstrip("+")): sign_headers.append(hdr) else: sign_headers = sign_headers.split(":") dkim = DKIMRequest( method, uri, headers, stream, options["domain"], options["selector"], options["key"], options["algorithm"], sign_headers, True, True, False, int(options["expire"]), ) if options["fake-time"]: dkim.time = "100" dkim.expire = "200" dkim.message_id = "1" yield dkim.sign() s = StringIO() _writeRequest(dkim, s) print(s.getvalue())
def _doRequest(options): if options["verbose"]: log.levels().setLogLevelForNamespace( "txdav.caldav.datastore.scheduling.ischedule.dkim", LogLevel.debug) # Parse the HTTP file with open(options["request"]) as f: request = f.read() method, uri, headers, stream = _parseRequest(request) # Setup signing headers sign_headers = options["signing"] if sign_headers is None: sign_headers = [] for hdr in ("Host", "Content-Type", "Originator", "Recipient+"): if headers.hasHeader(hdr.rstrip("+")): sign_headers.append(hdr) else: sign_headers = sign_headers.split(":") dkim = DKIMRequest( method, uri, headers, stream, options["domain"], options["selector"], options["key"], options["algorithm"], sign_headers, True, True, False, int(options["expire"]), ) if options["fake-time"]: dkim.time = "100" dkim.expire = "200" dkim.message_id = "1" yield dkim.sign() s = StringIO() _writeRequest(dkim, s) print(s.getvalue())