Correct crypto exception handling.
This commit is contained in:
+17
-1
@@ -25,10 +25,12 @@ import time
|
|||||||
import dns.resolver
|
import dns.resolver
|
||||||
|
|
||||||
from dkim.crypto import (
|
from dkim.crypto import (
|
||||||
|
DigestTooLargeError,
|
||||||
parse_private_key,
|
parse_private_key,
|
||||||
parse_public_key,
|
parse_public_key,
|
||||||
RSASSA_PKCS1_v1_5_sign,
|
RSASSA_PKCS1_v1_5_sign,
|
||||||
RSASSA_PKCS1_v1_5_verify,
|
RSASSA_PKCS1_v1_5_verify,
|
||||||
|
UnparsableKeyError,
|
||||||
)
|
)
|
||||||
from dkim.util import (
|
from dkim.util import (
|
||||||
InvalidTagValueList,
|
InvalidTagValueList,
|
||||||
@@ -273,7 +275,11 @@ def sign(message, selector, domain, privkey, identity=None, canonicalize=(Simple
|
|||||||
raise KeyFormatError(str(e))
|
raise KeyFormatError(str(e))
|
||||||
if debuglog is not None:
|
if debuglog is not None:
|
||||||
print >>debuglog, " ".join("%02x" % ord(x) for x in pkdata)
|
print >>debuglog, " ".join("%02x" % ord(x) for x in pkdata)
|
||||||
|
try:
|
||||||
pk = parse_private_key(pkdata)
|
pk = parse_private_key(pkdata)
|
||||||
|
except UnparsableKeyError, e:
|
||||||
|
raise KeyFormatError(str(e))
|
||||||
|
|
||||||
if identity is not None and not identity.endswith(domain):
|
if identity is not None and not identity.endswith(domain):
|
||||||
raise ParameterError("identity must end with domain")
|
raise ParameterError("identity must end with domain")
|
||||||
|
|
||||||
@@ -321,8 +327,11 @@ def sign(message, selector, domain, privkey, identity=None, canonicalize=(Simple
|
|||||||
if debuglog is not None:
|
if debuglog is not None:
|
||||||
print >>debuglog, "sign digest:", " ".join("%02x" % ord(x) for x in d)
|
print >>debuglog, "sign digest:", " ".join("%02x" % ord(x) for x in d)
|
||||||
|
|
||||||
|
try:
|
||||||
sig2 = RSASSA_PKCS1_v1_5_sign(
|
sig2 = RSASSA_PKCS1_v1_5_sign(
|
||||||
d, HASHID_SHA256, pk['privateExponent'], pk['modulus'])
|
d, HASHID_SHA256, pk['privateExponent'], pk['modulus'])
|
||||||
|
except DigestTooLargeError:
|
||||||
|
raise ParameterError("digest too large for modulus")
|
||||||
sig += base64.b64encode(sig2)
|
sig += base64.b64encode(sig2)
|
||||||
|
|
||||||
return sig + "\r\n"
|
return sig + "\r\n"
|
||||||
@@ -414,7 +423,12 @@ def verify(message, debuglog=None, dnsfunc=dnstxt):
|
|||||||
pub = parse_tag_value(s)
|
pub = parse_tag_value(s)
|
||||||
except InvalidTagValueList:
|
except InvalidTagValueList:
|
||||||
return False
|
return False
|
||||||
|
try:
|
||||||
pk = parse_public_key(base64.b64decode(pub['p']))
|
pk = parse_public_key(base64.b64decode(pub['p']))
|
||||||
|
except UnparsableKeyError, e:
|
||||||
|
if debuglog is not None:
|
||||||
|
print >>debuglog, "could not parse public key: %s" % e
|
||||||
|
return False
|
||||||
|
|
||||||
include_headers = re.split(r"\s*:\s*", sig['h'])
|
include_headers = re.split(r"\s*:\s*", sig['h'])
|
||||||
h = hasher()
|
h = hasher()
|
||||||
@@ -427,5 +441,7 @@ def verify(message, debuglog=None, dnsfunc=dnstxt):
|
|||||||
try:
|
try:
|
||||||
return RSASSA_PKCS1_v1_5_verify(
|
return RSASSA_PKCS1_v1_5_verify(
|
||||||
d, hashid, signature, pk['publicExponent'], pk['modulus'])
|
d, hashid, signature, pk['publicExponent'], pk['modulus'])
|
||||||
except ParameterError:
|
except DigestTooLargeError:
|
||||||
|
if debuglog is not None:
|
||||||
|
print >>debuglog, "digest too large for modulus"
|
||||||
return False
|
return False
|
||||||
|
|||||||
+17
-3
@@ -18,13 +18,16 @@
|
|||||||
# Copyright (c) 2011 William Grant <me@williamgrant.id.au>
|
# Copyright (c) 2011 William Grant <me@williamgrant.id.au>
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'DigestTooLargeError',
|
||||||
'parse_private_key',
|
'parse_private_key',
|
||||||
'parse_public_key',
|
'parse_public_key',
|
||||||
'RSASSA_PKCS1_v1_5_sign',
|
'RSASSA_PKCS1_v1_5_sign',
|
||||||
'RSASSA_PKCS1_v1_5_verify',
|
'RSASSA_PKCS1_v1_5_verify',
|
||||||
|
'UnparsableKeyError',
|
||||||
]
|
]
|
||||||
|
|
||||||
from dkim.asn1 import (
|
from dkim.asn1 import (
|
||||||
|
ASN1FormatError,
|
||||||
asn1_build,
|
asn1_build,
|
||||||
asn1_parse,
|
asn1_parse,
|
||||||
BIT_STRING,
|
BIT_STRING,
|
||||||
@@ -68,11 +71,16 @@ ASN1_RSAPrivateKey = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class DigestTooLarge(Exception):
|
class DigestTooLargeError(Exception):
|
||||||
"""The digest is too large to fit within the requested length."""
|
"""The digest is too large to fit within the requested length."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UnparsableKeyError(Exception):
|
||||||
|
"""The data could not be parsed as a key."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def parse_public_key(data):
|
def parse_public_key(data):
|
||||||
"""Parse an RSA public key.
|
"""Parse an RSA public key.
|
||||||
|
|
||||||
@@ -80,9 +88,12 @@ def parse_public_key(data):
|
|||||||
containing an RFC3447 RSAPublicKey.
|
containing an RFC3447 RSAPublicKey.
|
||||||
@return: RSA public key
|
@return: RSA public key
|
||||||
"""
|
"""
|
||||||
x = asn1_parse(ASN1_Object, data)
|
try:
|
||||||
# Not sure why the [1:] is necessary to skip a byte.
|
# Not sure why the [1:] is necessary to skip a byte.
|
||||||
|
x = asn1_parse(ASN1_Object, data)
|
||||||
pkd = asn1_parse(ASN1_RSAPublicKey, x[0][1][1:])
|
pkd = asn1_parse(ASN1_RSAPublicKey, x[0][1][1:])
|
||||||
|
except ASN1FormatError, e:
|
||||||
|
raise UnparsableKeyError(str(e))
|
||||||
pk = {
|
pk = {
|
||||||
'modulus': pkd[0][0],
|
'modulus': pkd[0][0],
|
||||||
'publicExponent': pkd[0][1],
|
'publicExponent': pkd[0][1],
|
||||||
@@ -96,7 +107,10 @@ def parse_private_key(data):
|
|||||||
@param data: DER-encoded RFC3447 RSAPrivateKey.
|
@param data: DER-encoded RFC3447 RSAPrivateKey.
|
||||||
@return: RSA private key
|
@return: RSA private key
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
pka = asn1_parse(ASN1_RSAPrivateKey, data)
|
pka = asn1_parse(ASN1_RSAPrivateKey, data)
|
||||||
|
except ASN1FormatError, e:
|
||||||
|
raise UnparsableKeyError(str(e))
|
||||||
pk = {
|
pk = {
|
||||||
'version': pka[0][0],
|
'version': pka[0][0],
|
||||||
'modulus': pka[0][1],
|
'modulus': pka[0][1],
|
||||||
@@ -128,7 +142,7 @@ def EMSA_PKCS1_v1_5_encode(digest, mlen, hashid):
|
|||||||
(OCTET_STRING, digest),
|
(OCTET_STRING, digest),
|
||||||
]))
|
]))
|
||||||
if len(dinfo)+3 > mlen:
|
if len(dinfo)+3 > mlen:
|
||||||
raise DigestTooLarge()
|
raise DigestTooLargeError()
|
||||||
return "\x00\x01"+"\xff"*(mlen-len(dinfo)-3)+"\x00"+dinfo
|
return "\x00\x01"+"\xff"*(mlen-len(dinfo)-3)+"\x00"+dinfo
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user