Add basic end-to-end tests.

This commit is contained in:
William Grant
2011-03-12 11:22:37 +11:00
9 changed files with 114 additions and 10 deletions
+1
View File
@@ -0,0 +1 @@
/.testrepository
+4
View File
@@ -0,0 +1,4 @@
[DEFAULT]
test_command=PYTHONPATH=. python -m subunit.run $LISTOPT $IDOPTION dkim.tests.test_dkim
test_id_option=--load-list $IDFILE
test_list_option=--list
+11
View File
@@ -21,6 +21,17 @@ To build and install pydkim:
python setup.py install python setup.py install
TESTING
To run pydkim's test suite:
PYTHONPATH=. python dkim/tests/test_dkim.py
Alternatively, if you have testrepository installed:
testr init
testr run
USAGE USAGE
The pydkim library offers one module called dkim. The sign() function takes an The pydkim library offers one module called dkim. The sign() function takes an
+2 -10
View File
@@ -396,7 +396,7 @@ def sign(message, selector, domain, privkey, identity=None, canonicalize=(Simple
return sig + "\r\n" return sig + "\r\n"
def verify(message, debuglog=None): def verify(message, debuglog=None, dnsfunc=dnstxt):
"""Verify a DKIM signature on an RFC822 formatted message. """Verify a DKIM signature on an RFC822 formatted message.
@param message: an RFC822 formatted message (with either \\n or \\r\\n line endings) @param message: an RFC822 formatted message (with either \\n or \\r\\n line endings)
@@ -548,7 +548,7 @@ def verify(message, debuglog=None):
print >>debuglog, "body hash mismatch (got %s, expected %s)" % (base64.b64encode(bodyhash), sig['bh']) print >>debuglog, "body hash mismatch (got %s, expected %s)" % (base64.b64encode(bodyhash), sig['bh'])
return False return False
s = dnstxt(sig['s']+"._domainkey."+sig['d']+".") s = dnsfunc(sig['s']+"._domainkey."+sig['d']+".")
if not s: if not s:
return False return False
a = re.split(r"\s*;\s*", s) a = re.split(r"\s*;\s*", s)
@@ -629,11 +629,3 @@ def verify(message, debuglog=None):
assert len(v) == len(sig2) assert len(v) == len(sig2)
# Byte-by-byte compare of signatures # Byte-by-byte compare of signatures
return not [1 for x in zip(v, sig2) if x[0] != x[1]] return not [1 for x in zip(v, sig2) if x[0] != x[1]]
if __name__ == "__main__":
message = """From: greg@hewgill.com\r\nSubject: test\r\n message\r\n\r\nHi.\r\n\r\nWe lost the game. Are you hungry yet?\r\n\r\nJoe.\r\n"""
print rfc822_parse(message)
sig = sign(message, "greg", "hewgill.com", open("/home/greg/.domainkeys/rsa.private").read())
print sig
print verify(sig+message)
#print sign(open("/home/greg/tmp/message").read(), "greg", "hewgill.com", open("/home/greg/.domainkeys/rsa.private").read())
View File
+8
View File
@@ -0,0 +1,8 @@
Received: from localhost
Message-ID: <example@example.com>
Date: Mon, 01 Jan 2011 01:02:03 +0400
From: Test User <test@example.com>
To: somebody@example.com
Subject: Testing
This is a test message.
+15
View File
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDkHlOQoBTzWRiGs5V6NpP3idY6Wk08a5qhdR6wy5bdOKb2jLQi
Y/J16JYi0Qvx/byYzCNb3W91y3FutACDfzwQ/BC/e/8uBsCR+yz1Lxj+PL6lHvqM
KrM3rG4hstT5QjvHO9PzoxZyVYLzBfO2EeC3Ip3G+2kryOTIKT+l/K4w3QIDAQAB
AoGAH0cxOhFZDgzXWhDhnAJDw5s4roOXN4OhjiXa8W7Y3rhX3FJqmJSPuC8N9vQm
6SVbaLAE4SG5mLMueHlh4KXffEpuLEiNp9Ss3O4YfLiQpbRqE7Tm5SxKjvvQoZZe
zHorimOaChRL2it47iuWxzxSiRMv4c+j70GiWdxXnxe4UoECQQDzJB/0U58W7RZy
6enGVj2kWF732CoWFZWzi1FicudrBFoy63QwcowpoCazKtvZGMNlPWnC7x/6o8Gc
uSe0ga2xAkEA8C7PipPm1/1fTRQvj1o/dDmZp243044ZNyxjg+/OPN0oWCbXIGxy
WvmZbXriOWoSALJTjExEgraHEgnXssuk7QJBALl5ICsYMu6hMxO73gnfNayNgPxd
WFV6Z7ULnKyV7HSVYF0hgYOHjeYe9gaMtiJYoo0zGN+L3AAtNP9huqkWlzECQE1a
licIeVlo1e+qJ6Mgqr0Q7Aa7falZ448ccbSFYEPD6oFxiOl9Y9se9iYHZKKfIcst
o7DUw1/hz2Ck4N5JrgUCQQCyKveNvjzkkd8HjYs0SwM0fPjK16//5qDZ2UiDGnOe
uEzxBDAr518Z8VFbR41in3W4Y3yCDgQlLlcETrS+zYcL
-----END RSA PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkHlOQoBTzWRiGs5V6NpP3idY6Wk08a5qhdR6wy5bdOKb2jLQiY/J16JYi0Qvx/byYzCNb3W91y3FutACDfzwQ/BC/e/8uBsCR+yz1Lxj+PL6lHvqMKrM3rG4hstT5QjvHO9PzoxZyVYLzBfO2EeC3Ip3G+2kryOTIKT+l/K4w3QIDAQAB
+72
View File
@@ -0,0 +1,72 @@
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the author be held liable for any damages
# arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
#
# Copyright (c) 2011 William Grant <me@williamgrant.id.au>
import os.path
import unittest
import dkim
def read_test_data(filename):
"""Get the content of the given test data file.
The files live in dkim/tests/data.
"""
path = os.path.join(os.path.dirname(__file__), 'data', filename)
return open(path).read()
class TestFold(unittest.TestCase):
def test_short_line(self):
self.assertEqual(
"foo", dkim.fold("foo"))
def DISABLED_test_long_line(self):
# The function is terribly broken, not passing even this simple
# test.
self.assertEqual(
"foo"*24 + "\r\n foo", dkim.fold("foo" * 25))
class TestSignAndVerify(unittest.TestCase):
"""End-to-end signature and verification tests."""
def setUp(self):
self.message = read_test_data("test.message")
self.key = read_test_data("test.private")
def dnsfunc(self, domain):
self.assertEqual('test._domainkey.example.com.', domain)
return read_test_data("test.txt")
def test_verifies(self):
# A message verifies after being signed.
sig = dkim.sign(self.message, "test", "example.com", self.key)
res = dkim.verify(sig + self.message, dnsfunc=self.dnsfunc)
self.assertTrue(res)
def test_altered_body_fails(self):
# An altered body fails verification.
sig = dkim.sign(self.message, "test", "example.com", self.key)
res = dkim.verify(sig + self.message + "foo", dnsfunc=self.dnsfunc)
self.assertFalse(res)
if __name__ == '__main__':
unittest.main()