Apply performance patch from bug#901591
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
2012-02-03 Version 0.5.1
|
||||||
|
- Apply performance patch from <https://launchpad.net/bugs/901591>
|
||||||
|
|
||||||
2011-10-26 Version 0.5
|
2011-10-26 Version 0.5
|
||||||
- Add test case and fix for <https://launchpad.net/bugs/644046>
|
- Add test case and fix for <https://launchpad.net/bugs/644046>
|
||||||
- Add test case and fix for <https://launchpad.net/bugs/737311>
|
- Add test case and fix for <https://launchpad.net/bugs/737311>
|
||||||
|
|||||||
+2
-4
@@ -450,8 +450,7 @@ class DKIM(object):
|
|||||||
self.logger.debug("sign headers: %r" % self.signed_headers)
|
self.logger.debug("sign headers: %r" % self.signed_headers)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sig2 = RSASSA_PKCS1_v1_5_sign(
|
sig2 = RSASSA_PKCS1_v1_5_sign(h, pk)
|
||||||
h, pk['privateExponent'], pk['modulus'])
|
|
||||||
except DigestTooLargeError:
|
except DigestTooLargeError:
|
||||||
raise ParameterError("digest too large for modulus")
|
raise ParameterError("digest too large for modulus")
|
||||||
sig_value += base64.b64encode(bytes(sig2))
|
sig_value += base64.b64encode(bytes(sig2))
|
||||||
@@ -545,8 +544,7 @@ class DKIM(object):
|
|||||||
try:
|
try:
|
||||||
self.signature_fields = sig
|
self.signature_fields = sig
|
||||||
signature = base64.b64decode(re.sub(br"\s+", b"", sig[b'b']))
|
signature = base64.b64decode(re.sub(br"\s+", b"", sig[b'b']))
|
||||||
return RSASSA_PKCS1_v1_5_verify(
|
return RSASSA_PKCS1_v1_5_verify(h, signature, pk)
|
||||||
h, signature, pk['publicExponent'], pk['modulus'])
|
|
||||||
except (TypeError,DigestTooLargeError) as e:
|
except (TypeError,DigestTooLargeError) as e:
|
||||||
raise KeyFormatError("digest too large for modulus: %s"%e)
|
raise KeyFormatError("digest too large for modulus: %s"%e)
|
||||||
|
|
||||||
|
|||||||
+34
-15
@@ -213,41 +213,60 @@ def int2str(n, length=-1):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def perform_rsa(message, exponent, modulus, mlen):
|
def rsa_decrypt(message, pk, mlen):
|
||||||
"""Perform RSA signing or verification.
|
"""Perform RSA decryption/signing
|
||||||
|
|
||||||
@param message: byte string to operate on
|
@param message: byte string to operate on
|
||||||
@param exponent: public or private key exponent
|
@param pk: private key data
|
||||||
@param modulus: key modulus
|
|
||||||
@param mlen: desired output length
|
@param mlen: desired output length
|
||||||
@return: byte string result of the operation
|
@return: byte string result of the operation
|
||||||
"""
|
"""
|
||||||
return int2str(pow(str2int(message), exponent, modulus), mlen)
|
c = str2int(message)
|
||||||
|
|
||||||
|
m1 = pow(c, pk['exponent1'], pk['prime1'])
|
||||||
|
m2 = pow(c, pk['exponent2'], pk['prime2'])
|
||||||
|
|
||||||
|
if m1 < m2:
|
||||||
|
h = pk['coefficient'] * (m1 + pk['prime1'] - m2) % pk['prime1']
|
||||||
|
else:
|
||||||
|
h = pk['coefficient'] * (m1 - m2) % pk['prime1']
|
||||||
|
|
||||||
|
return int2str(m2 + h * pk['prime2'], mlen)
|
||||||
|
|
||||||
|
|
||||||
def RSASSA_PKCS1_v1_5_sign(hash, private_exponent, modulus):
|
def rsa_encrypt(message, pk, mlen):
|
||||||
|
"""Perform RSA encryption/verification
|
||||||
|
|
||||||
|
@param message: byte string to operate on
|
||||||
|
@param pk: public key data
|
||||||
|
@param mlen: desired output length
|
||||||
|
@return: byte string result of the operation
|
||||||
|
"""
|
||||||
|
m = str2int(message)
|
||||||
|
return int2str(pow(m, pk['publicExponent'], pk['modulus']), mlen)
|
||||||
|
|
||||||
|
|
||||||
|
def RSASSA_PKCS1_v1_5_sign(hash, private_key):
|
||||||
"""Sign a digest with RFC3447 RSASSA-PKCS1-v1_5.
|
"""Sign a digest with RFC3447 RSASSA-PKCS1-v1_5.
|
||||||
|
|
||||||
@param hash: hash object to sign
|
@param hash: hash object to sign
|
||||||
@param private_exponent: private key exponent
|
@param private_key: private key data
|
||||||
@param modulus: key modulus
|
|
||||||
@return: signed digest byte string
|
@return: signed digest byte string
|
||||||
"""
|
"""
|
||||||
modlen = len(int2str(modulus))
|
modlen = len(int2str(private_key['modulus']))
|
||||||
encoded_digest = EMSA_PKCS1_v1_5_encode(hash, modlen)
|
encoded_digest = EMSA_PKCS1_v1_5_encode(hash, modlen)
|
||||||
return perform_rsa(encoded_digest, private_exponent, modulus, modlen)
|
return rsa_decrypt(encoded_digest, private_key, modlen)
|
||||||
|
|
||||||
|
|
||||||
def RSASSA_PKCS1_v1_5_verify(hash, signature, public_exponent, modulus):
|
def RSASSA_PKCS1_v1_5_verify(hash, signature, public_key):
|
||||||
"""Verify a digest signed with RFC3447 RSASSA-PKCS1-v1_5.
|
"""Verify a digest signed with RFC3447 RSASSA-PKCS1-v1_5.
|
||||||
|
|
||||||
@param hash: hash object to check
|
@param hash: hash object to check
|
||||||
@param signature: signed digest byte string
|
@param signature: signed digest byte string
|
||||||
@param public_exponent: public key exponent
|
@param public_key: public key data
|
||||||
@param modulus: key modulus
|
|
||||||
@return: True if the signature is valid, False otherwise
|
@return: True if the signature is valid, False otherwise
|
||||||
"""
|
"""
|
||||||
modlen = len(int2str(modulus))
|
modlen = len(int2str(public_key['modulus']))
|
||||||
encoded_digest = EMSA_PKCS1_v1_5_encode(hash, modlen)
|
encoded_digest = EMSA_PKCS1_v1_5_encode(hash, modlen)
|
||||||
signed_digest = perform_rsa(signature, public_exponent, modulus, modlen)
|
signed_digest = rsa_encrypt(signature, public_key, modlen)
|
||||||
return encoded_digest == signed_digest
|
return encoded_digest == signed_digest
|
||||||
|
|||||||
+37
-31
@@ -27,7 +27,6 @@ from dkim.crypto import (
|
|||||||
int2str,
|
int2str,
|
||||||
parse_pem_private_key,
|
parse_pem_private_key,
|
||||||
parse_public_key,
|
parse_public_key,
|
||||||
perform_rsa,
|
|
||||||
RSASSA_PKCS1_v1_5_sign,
|
RSASSA_PKCS1_v1_5_sign,
|
||||||
RSASSA_PKCS1_v1_5_verify,
|
RSASSA_PKCS1_v1_5_verify,
|
||||||
str2int,
|
str2int,
|
||||||
@@ -50,6 +49,37 @@ TEST_KEY_PRIVATE_EXPONENT = int(
|
|||||||
'489900956461640273471526152019568303807247290486052565153701534491987040'
|
'489900956461640273471526152019568303807247290486052565153701534491987040'
|
||||||
'131529720476525111651818771481293273124837542067061293644354088836358900'
|
'131529720476525111651818771481293273124837542067061293644354088836358900'
|
||||||
'29771161475005043329')
|
'29771161475005043329')
|
||||||
|
TEST_KEY_PRIME1 = int(
|
||||||
|
'127343333492908149956322715568115237787784712176275919666517073343689103'
|
||||||
|
'280591709737233188193431204382936008602497360201661766158158969883295914'
|
||||||
|
'16266272177')
|
||||||
|
TEST_KEY_PRIME2 = int(
|
||||||
|
'125793967926229270607412639516115399484604596465353856808629588968254772'
|
||||||
|
'302339293254103556785310783521521266982500068526354237606773478050287350'
|
||||||
|
'33316975853')
|
||||||
|
TEST_KEY_EXPONENT1 = int(
|
||||||
|
'971401692373919639404678505179789291960987093676634885925231250693661495'
|
||||||
|
'080125935714710587508461815572290443270923375888685273287584323569222368'
|
||||||
|
'5450962737')
|
||||||
|
TEST_KEY_EXPONENT2 = int(
|
||||||
|
'405135004809332318340885085107137607293826268763328174261828392259785080'
|
||||||
|
'028911220030572618988900118679333717167345003034279703551607153395397272'
|
||||||
|
'3014807045')
|
||||||
|
TEST_KEY_COEFFICIENT = int(
|
||||||
|
'933140693852464192207530806898449261372116224159220632563973880414444021'
|
||||||
|
'989007318611849609226428922185905596238131661588470844906391982906126973'
|
||||||
|
'1282880267')
|
||||||
|
TEST_PK = {
|
||||||
|
'version': 0,
|
||||||
|
'modulus': TEST_KEY_MODULUS,
|
||||||
|
'publicExponent': TEST_KEY_PUBLIC_EXPONENT,
|
||||||
|
'privateExponent': TEST_KEY_PRIVATE_EXPONENT,
|
||||||
|
'prime1': TEST_KEY_PRIME1,
|
||||||
|
'prime2': TEST_KEY_PRIME2,
|
||||||
|
'exponent1': TEST_KEY_EXPONENT1,
|
||||||
|
'exponent2': TEST_KEY_EXPONENT2,
|
||||||
|
'coefficient': TEST_KEY_COEFFICIENT,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TestStrIntConversion(unittest.TestCase):
|
class TestStrIntConversion(unittest.TestCase):
|
||||||
@@ -71,9 +101,7 @@ class TestParseKeys(unittest.TestCase):
|
|||||||
|
|
||||||
def test_parse_pem_private_key(self):
|
def test_parse_pem_private_key(self):
|
||||||
key = parse_pem_private_key(read_test_data('test.private'))
|
key = parse_pem_private_key(read_test_data('test.private'))
|
||||||
self.assertEqual(key['modulus'], TEST_KEY_MODULUS)
|
self.assertEqual(key, TEST_PK)
|
||||||
self.assertEqual(key['publicExponent'], TEST_KEY_PUBLIC_EXPONENT)
|
|
||||||
self.assertEqual(key['privateExponent'], TEST_KEY_PRIVATE_EXPONENT)
|
|
||||||
|
|
||||||
def test_parse_public_key(self):
|
def test_parse_public_key(self):
|
||||||
data = read_test_data('test.txt')
|
data = read_test_data('test.txt')
|
||||||
@@ -109,27 +137,6 @@ class TestEMSA_PKCS1_v1_5(unittest.TestCase):
|
|||||||
EMSA_PKCS1_v1_5_encode, hash, 45)
|
EMSA_PKCS1_v1_5_encode, hash, 45)
|
||||||
|
|
||||||
|
|
||||||
class TestRSA(unittest.TestCase):
|
|
||||||
|
|
||||||
message = binascii.unhexlify(b'0004fb')
|
|
||||||
modulus = 186101
|
|
||||||
modlen = 3
|
|
||||||
public_exponent = 907
|
|
||||||
private_exponent = 2851
|
|
||||||
|
|
||||||
def test_perform(self):
|
|
||||||
signed = perform_rsa(
|
|
||||||
self.message, self.private_exponent, self.modulus, self.modlen)
|
|
||||||
self.assertEqual(binascii.unhexlify(b'01f140'), signed)
|
|
||||||
|
|
||||||
def test_sign_and_verify(self):
|
|
||||||
signed = perform_rsa(
|
|
||||||
self.message, self.private_exponent, self.modulus, self.modlen)
|
|
||||||
unsigned = perform_rsa(
|
|
||||||
signed, self.public_exponent, self.modulus, self.modlen)
|
|
||||||
self.assertEqual(self.message, unsigned)
|
|
||||||
|
|
||||||
|
|
||||||
class TestRSASSA(unittest.TestCase):
|
class TestRSASSA(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -144,19 +151,18 @@ class TestRSASSA(unittest.TestCase):
|
|||||||
b'39d2d6ab8b215b19be0e69ef490885004a474eb26d747a219693e8c')
|
b'39d2d6ab8b215b19be0e69ef490885004a474eb26d747a219693e8c')
|
||||||
|
|
||||||
def test_sign_and_verify(self):
|
def test_sign_and_verify(self):
|
||||||
signature = RSASSA_PKCS1_v1_5_sign(
|
signature = RSASSA_PKCS1_v1_5_sign(self.hash, TEST_PK)
|
||||||
self.hash, TEST_KEY_PRIVATE_EXPONENT, TEST_KEY_MODULUS)
|
|
||||||
self.assertEqual(self.test_signature, signature)
|
self.assertEqual(self.test_signature, signature)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
RSASSA_PKCS1_v1_5_verify(
|
RSASSA_PKCS1_v1_5_verify(
|
||||||
self.hash, signature, TEST_KEY_PUBLIC_EXPONENT,
|
self.hash, signature, TEST_PK))
|
||||||
TEST_KEY_MODULUS))
|
|
||||||
|
|
||||||
def test_invalid_signature(self):
|
def test_invalid_signature(self):
|
||||||
|
invalid_key = TEST_PK.copy()
|
||||||
|
invalid_key['modulus'] += 1
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
RSASSA_PKCS1_v1_5_verify(
|
RSASSA_PKCS1_v1_5_verify(
|
||||||
self.hash, self.test_signature, TEST_KEY_PUBLIC_EXPONENT,
|
self.hash, self.test_signature, invalid_key))
|
||||||
TEST_KEY_MODULUS + 1))
|
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
|
|||||||
Reference in New Issue
Block a user