Extract crypto stuff to dkim.crypto.

This commit is contained in:
William Grant
2011-03-09 23:27:04 +11:00
parent b6d3502f9e
commit 6f715a1a01
2 changed files with 114 additions and 84 deletions
+4 -84
View File
@@ -5,15 +5,10 @@ import time
import dns.resolver
from dkim.asn1 import (
asn1_build,
asn1_parse,
BIT_STRING,
INTEGER,
SEQUENCE,
OBJECT_IDENTIFIER,
OCTET_STRING,
NULL,
from dkim.crypto import (
EMSA_PKCS1_v1_5_encode,
parse_private_key,
parse_public_key,
)
__all__ = [
@@ -87,22 +82,6 @@ def _remove(s, t):
assert i >= 0
return s[:i] + s[i+len(t):]
def EMSA_PKCS1_v1_5_encode(digest, modlen, hashid):
dinfo = asn1_build(
(SEQUENCE, [
(SEQUENCE, [
(OBJECT_IDENTIFIER, hashid),
(NULL, None),
]),
(OCTET_STRING, digest),
]),
)
if len(dinfo)+3 > modlen:
raise ParameterError("Hash too large for modulus")
return "\x00\x01"+"\xff"*(modlen-len(dinfo)-3)+"\x00"+dinfo
def hash_headers(hasher, canonicalize_headers, headers, include_headers,
sigheaders, sig):
sign_headers = []
@@ -126,33 +105,6 @@ def hash_headers(hasher, canonicalize_headers, headers, include_headers,
hasher.update(x[1])
def parse_public_key(data):
x = asn1_parse(ASN1_Object, data)
# Not sure why the [1:] is necessary to skip a byte.
pkd = asn1_parse(ASN1_RSAPublicKey, x[0][1][1:])
pk = {
'modulus': pkd[0][0],
'publicExponent': pkd[0][1],
}
return pk
def parse_private_key(data):
pka = asn1_parse(ASN1_RSAPrivateKey, data)
pk = {
'version': pka[0][0],
'modulus': pka[0][1],
'publicExponent': pka[0][2],
'privateExponent': pka[0][3],
'prime1': pka[0][4],
'prime2': pka[0][5],
'exponent1': pka[0][6],
'exponent2': pka[0][7],
'coefficient': pka[0][8],
}
return pk
def validate_signature_fields(sig, debuglog=None):
mandatory_fields = ('v', 'a', 'b', 'bh', 'd', 'h', 's')
for field in mandatory_fields:
@@ -200,38 +152,6 @@ def validate_signature_fields(sig, debuglog=None):
return False
return True
ASN1_Object = [
(SEQUENCE, [
(SEQUENCE, [
(OBJECT_IDENTIFIER,),
(NULL,),
]),
(BIT_STRING,),
])
]
ASN1_RSAPublicKey = [
(SEQUENCE, [
(INTEGER,),
(INTEGER,),
])
]
ASN1_RSAPrivateKey = [
(SEQUENCE, [
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
])
]
# These values come from RFC 3447, section 9.2 Notes, page 43.
HASHID_SHA1 = "\x2b\x0e\x03\x02\x1a"
HASHID_SHA256 = "\x60\x86\x48\x01\x65\x03\x04\x02\x01"
+110
View File
@@ -0,0 +1,110 @@
# 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) 2008 Greg Hewgill http://hewgill.com
# Copyright (c) 2011 William Grant <me@williamgrant.id.au>
__all__ = [
'EMSA_PKCS1_v1_5_encode',
'parse_private_key',
'parse_public_key',
]
from dkim.asn1 import (
asn1_build,
asn1_parse,
BIT_STRING,
INTEGER,
SEQUENCE,
OBJECT_IDENTIFIER,
OCTET_STRING,
NULL,
)
ASN1_Object = [
(SEQUENCE, [
(SEQUENCE, [
(OBJECT_IDENTIFIER,),
(NULL,),
]),
(BIT_STRING,),
])
]
ASN1_RSAPublicKey = [
(SEQUENCE, [
(INTEGER,),
(INTEGER,),
])
]
ASN1_RSAPrivateKey = [
(SEQUENCE, [
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
(INTEGER,),
])
]
def parse_public_key(data):
x = asn1_parse(ASN1_Object, data)
# Not sure why the [1:] is necessary to skip a byte.
pkd = asn1_parse(ASN1_RSAPublicKey, x[0][1][1:])
pk = {
'modulus': pkd[0][0],
'publicExponent': pkd[0][1],
}
return pk
def parse_private_key(data):
pka = asn1_parse(ASN1_RSAPrivateKey, data)
pk = {
'version': pka[0][0],
'modulus': pka[0][1],
'publicExponent': pka[0][2],
'privateExponent': pka[0][3],
'prime1': pka[0][4],
'prime2': pka[0][5],
'exponent1': pka[0][6],
'exponent2': pka[0][7],
'coefficient': pka[0][8],
}
return pk
def EMSA_PKCS1_v1_5_encode(digest, modlen, hashid):
dinfo = asn1_build(
(SEQUENCE, [
(SEQUENCE, [
(OBJECT_IDENTIFIER, hashid),
(NULL, None),
]),
(OCTET_STRING, digest),
]),
)
if len(dinfo)+3 > modlen:
raise Exception("Hash too large for modulus") # XXX: DKIMException
return "\x00\x01"+"\xff"*(modlen-len(dinfo)-3)+"\x00"+dinfo