[CalendarServer-changes] [9832] CalendarServer/branches/users/cdaboo/ischedule-dkim
source_changes at macosforge.org
source_changes at macosforge.org
Fri Sep 21 13:13:56 PDT 2012
Revision: 9832
http://trac.calendarserver.org//changeset/9832
Author: cdaboo at apple.com
Date: 2012-09-21 13:13:55 -0700 (Fri, 21 Sep 2012)
Log Message:
-----------
Switch to PyCrypto.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py
CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py
Modified: CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py
===================================================================
--- CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py 2012-09-21 17:16:16 UTC (rev 9831)
+++ CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py 2012-09-21 20:13:55 UTC (rev 9832)
@@ -15,8 +15,9 @@
# limitations under the License.
##
+from Crypto.PublicKey import RSA
from StringIO import StringIO
-from subprocess import PIPE
+from twext.web2.client.http import ClientRequest
from twext.web2.http_headers import Headers
from twext.web2.stream import MemoryStream
from twisted.internet import reactor
@@ -24,45 +25,34 @@
from twisted.python.usage import Options
from twistedcaldav.scheduling.ischedule.dkim import RSA256, DKIMRequest, \
PublicKeyLookup, DKIMVerifier, DKIMVerificationError
-import subprocess
import sys
-from twext.web2.client.http import ClientRequest
-import rsa
def _doKeyGeneration(options):
- child = subprocess.Popen(
- args=["openssl", "genrsa", str(options["key-size"]), ],
- stdout=PIPE,
- )
- output, status = child.communicate()
- if status:
- print "Failed to generate private key"
- sys.exit(1)
- output = output.strip()
+
+ key = RSA.generate(options["key-size"])
+ output = key.exportKey()
+ lineBreak = False
if options["key"]:
open(options["key"], "w").write(output)
else:
print output
+ lineBreak = True
- child = subprocess.Popen(
- args=["openssl", "rsa", "-pubout", ],
- stdout=PIPE,
- stdin=PIPE,
- )
- output, status = child.communicate(output)
- if status:
- print "Failed to generate public key"
- sys.exit(1)
- output = output.strip()
+ output = key.publickey().exportKey()
if options["pub-key"]:
open(options["pub-key"], "w").write(output)
else:
+ if lineBreak:
+ print
print output
+ lineBreak = True
if options["txt"]:
output = "".join(output.splitlines()[1:-1])
txt = "v=DKIM1; p=%s" % (output,)
+ if lineBreak:
+ print
print txt
@@ -96,8 +86,13 @@
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()
@@ -122,6 +117,8 @@
lookup = None
dkim = DKIMVerifier(request, lookup)
+ if options["fake-time"]:
+ dkim.time = 100
try:
yield dkim.verify()
@@ -181,7 +178,7 @@
"""
Do the key lookup using the actual lookup method.
"""
- return rsa.PublicKey.load_pkcs1(open(self.pubkeyfile).read())
+ return RSA.importKey(open(self.pubkeyfile).read())
@@ -209,6 +206,8 @@
--pub-key FILE Public key file to create [stdout]
--key-size SIZE Key size [1024]
--txt Also generate the public key TXT record
+ --fake-time Use fake t=, x= values when signing and also
+ ignore expiration on verification
# Request
--request FILE An HTTP request to sign
@@ -225,8 +224,14 @@
q= lookup
Description:
- This utility is for testing DKIM signed HTTP request.
+ This utility is for testing DKIM signed HTTP requests. Key operations are:
+ --key-gen: generate a private/public RSA key.
+
+ --request: sign an HTTP request.
+
+ --verify: verify a signed HTTP request.
+
"""
@@ -241,6 +246,7 @@
['verbose', 'v', "Verbose logging."],
['key-gen', 'g', "Generate private/public key files"],
['txt', 't', "Also generate the public key TXT record"],
+ ['fake-time', 'f', "Fake time values for signing/verification"],
]
optParameters = [
Modified: CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py
===================================================================
--- CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py 2012-09-21 17:16:16 UTC (rev 9831)
+++ CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py 2012-09-21 20:13:55 UTC (rev 9832)
@@ -27,12 +27,15 @@
from twistedcaldav.simpleresource import SimpleResource, SimpleDataResource
from twistedcaldav.scheduling.ischedule.utils import lookupDataViaTXT
+from Crypto.Hash import SHA, SHA256
+from Crypto.PublicKey import RSA
+from Crypto.Signature import PKCS1_v1_5
+
import base64
import binascii
import collections
import hashlib
import os
-import rsa
import textwrap
import time
import uuid
@@ -92,7 +95,7 @@
log.error(msg)
raise ConfigurationError(msg)
try:
- rsa.PrivateKey.load_pkcs1(key_data)
+ RSA.importKey(key_data)
except:
msg = "DKIM: Invalid private key file: %s" % (config.Scheduling.iSchedule.DKIM.PrivateKeyFile,)
log.error(msg)
@@ -106,7 +109,7 @@
log.error(msg)
raise ConfigurationError(msg)
try:
- rsa.PublicKey.load_pkcs1(key_data)
+ RSA.importKey(key_data)
except:
msg = "DKIM: Invalid public key file: %s" % (config.Scheduling.iSchedule.DKIM.PublicKeyFile,)
log.error(msg)
@@ -170,11 +173,22 @@
"""
return {
RSA1 : "SHA-1",
- RSA256: "SHA-256"
+ RSA256: "SHA-256",
}[algorithm]
@staticmethod
+ def hash_func(algorithm):
+ """
+ Return RSA hash name for DKIM algorithm.
+ """
+ return {
+ RSA1 : SHA,
+ RSA256: SHA256,
+ }[algorithm]
+
+
+ @staticmethod
def extractTags(data):
"""
Split a DKIM tag list into a dict, removing unneeded whitespace.
@@ -299,6 +313,7 @@
self.hash_method = DKIMUtils.hashlib_method(self.algorithm)
self.hash_name = DKIMUtils.hash_name(self.algorithm)
+ self.hash_func = DKIMUtils.hash_func(self.algorithm)
self.keyMethods = []
if useDNSKey:
@@ -404,8 +419,10 @@
def generateSignature(self, headers):
# Sign the hash
if self.key_file not in self.keys:
- self.keys[self.key_file] = rsa.PrivateKey.load_pkcs1(open(self.key_file).read())
- return base64.b64encode(rsa.sign(headers, self.keys[self.key_file], self.hash_name))
+ self.keys[self.key_file] = RSA.importKey(open(self.key_file).read())
+ h = self.hash_func.new(headers)
+ signer = PKCS1_v1_5.new(self.keys[self.key_file])
+ return base64.b64encode(signer.sign(h))
@@ -447,7 +464,9 @@
PublicKeyLookup_DNSTXT,
) if key_lookup is None else key_lookup
+ self.time = int(time.time())
+
@inlineCallbacks
def verify(self):
"""
@@ -468,8 +487,11 @@
# Do header verification
try:
- rsa.verify(headers, base64.b64decode(self.dkim_tags["b"]), pubkey)
- except rsa.VerificationError:
+ h = self.hash_func.new(headers)
+ verifier = PKCS1_v1_5.new(pubkey)
+ if not verifier.verify(h, base64.b64decode(self.dkim_tags["b"])):
+ raise ValueError()
+ except ValueError:
msg = "Could not verify signature"
_debug_msg = """
DKIM-Signature:%s
@@ -563,7 +585,7 @@
# Check expiration
if "x" in self.dkim_tags:
- diff_time = int(time.time()) - int(self.dkim_tags["x"])
+ diff_time = self.time - int(self.dkim_tags["x"])
if diff_time > 0:
msg = "Signature expired: %d seconds" % (diff_time,)
log.debug("DKIM: " + msg)
@@ -593,6 +615,7 @@
# Some useful bits
self.hash_method = DKIMUtils.hashlib_method(self.dkim_tags["a"])
+ self.hash_func = DKIMUtils.hash_func(self.dkim_tags["a"])
self.key_methods = self.dkim_tags["q"].split(":")
@@ -734,7 +757,7 @@
""" % ("\n".join(textwrap.wrap(pkey["p"], 64)),)
try:
- key = rsa.PublicKey.load_pkcs1(key_data)
+ key = RSA.importKey(key_data)
key._original_data = key_data
return key
except:
@@ -882,7 +905,7 @@
# Make sure we can parse a valid public key
try:
- rsa.PublicKey.load_pkcs1(key_data)
+ RSA.importKey(key_data)
except:
log.error("DKIM: Invalid public key file: %s" % (pubkeyfile,))
raise
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120921/6c4b1606/attachment-0001.html>
More information about the calendarserver-changes
mailing list