Apply performance patch from bug#901591
This commit is contained in:
+2
-4
@@ -450,8 +450,7 @@ class DKIM(object):
|
||||
self.logger.debug("sign headers: %r" % self.signed_headers)
|
||||
|
||||
try:
|
||||
sig2 = RSASSA_PKCS1_v1_5_sign(
|
||||
h, pk['privateExponent'], pk['modulus'])
|
||||
sig2 = RSASSA_PKCS1_v1_5_sign(h, pk)
|
||||
except DigestTooLargeError:
|
||||
raise ParameterError("digest too large for modulus")
|
||||
sig_value += base64.b64encode(bytes(sig2))
|
||||
@@ -545,8 +544,7 @@ class DKIM(object):
|
||||
try:
|
||||
self.signature_fields = sig
|
||||
signature = base64.b64decode(re.sub(br"\s+", b"", sig[b'b']))
|
||||
return RSASSA_PKCS1_v1_5_verify(
|
||||
h, signature, pk['publicExponent'], pk['modulus'])
|
||||
return RSASSA_PKCS1_v1_5_verify(h, signature, pk)
|
||||
except (TypeError,DigestTooLargeError) as e:
|
||||
raise KeyFormatError("digest too large for modulus: %s"%e)
|
||||
|
||||
|
||||
+34
-15
@@ -213,41 +213,60 @@ def int2str(n, length=-1):
|
||||
return r
|
||||
|
||||
|
||||
def perform_rsa(message, exponent, modulus, mlen):
|
||||
"""Perform RSA signing or verification.
|
||||
def rsa_decrypt(message, pk, mlen):
|
||||
"""Perform RSA decryption/signing
|
||||
|
||||
@param message: byte string to operate on
|
||||
@param exponent: public or private key exponent
|
||||
@param modulus: key modulus
|
||||
@param pk: private key data
|
||||
@param mlen: desired output length
|
||||
@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.
|
||||
|
||||
@param hash: hash object to sign
|
||||
@param private_exponent: private key exponent
|
||||
@param modulus: key modulus
|
||||
@param private_key: private key data
|
||||
@return: signed digest byte string
|
||||
"""
|
||||
modlen = len(int2str(modulus))
|
||||
modlen = len(int2str(private_key['modulus']))
|
||||
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.
|
||||
|
||||
@param hash: hash object to check
|
||||
@param signature: signed digest byte string
|
||||
@param public_exponent: public key exponent
|
||||
@param modulus: key modulus
|
||||
@param public_key: public key data
|
||||
@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)
|
||||
signed_digest = perform_rsa(signature, public_exponent, modulus, modlen)
|
||||
signed_digest = rsa_encrypt(signature, public_key, modlen)
|
||||
return encoded_digest == signed_digest
|
||||
|
||||
+37
-31
@@ -27,7 +27,6 @@ from dkim.crypto import (
|
||||
int2str,
|
||||
parse_pem_private_key,
|
||||
parse_public_key,
|
||||
perform_rsa,
|
||||
RSASSA_PKCS1_v1_5_sign,
|
||||
RSASSA_PKCS1_v1_5_verify,
|
||||
str2int,
|
||||
@@ -50,6 +49,37 @@ TEST_KEY_PRIVATE_EXPONENT = int(
|
||||
'489900956461640273471526152019568303807247290486052565153701534491987040'
|
||||
'131529720476525111651818771481293273124837542067061293644354088836358900'
|
||||
'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):
|
||||
@@ -71,9 +101,7 @@ class TestParseKeys(unittest.TestCase):
|
||||
|
||||
def test_parse_pem_private_key(self):
|
||||
key = parse_pem_private_key(read_test_data('test.private'))
|
||||
self.assertEqual(key['modulus'], TEST_KEY_MODULUS)
|
||||
self.assertEqual(key['publicExponent'], TEST_KEY_PUBLIC_EXPONENT)
|
||||
self.assertEqual(key['privateExponent'], TEST_KEY_PRIVATE_EXPONENT)
|
||||
self.assertEqual(key, TEST_PK)
|
||||
|
||||
def test_parse_public_key(self):
|
||||
data = read_test_data('test.txt')
|
||||
@@ -109,27 +137,6 @@ class TestEMSA_PKCS1_v1_5(unittest.TestCase):
|
||||
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):
|
||||
|
||||
def setUp(self):
|
||||
@@ -144,19 +151,18 @@ class TestRSASSA(unittest.TestCase):
|
||||
b'39d2d6ab8b215b19be0e69ef490885004a474eb26d747a219693e8c')
|
||||
|
||||
def test_sign_and_verify(self):
|
||||
signature = RSASSA_PKCS1_v1_5_sign(
|
||||
self.hash, TEST_KEY_PRIVATE_EXPONENT, TEST_KEY_MODULUS)
|
||||
signature = RSASSA_PKCS1_v1_5_sign(self.hash, TEST_PK)
|
||||
self.assertEqual(self.test_signature, signature)
|
||||
self.assertTrue(
|
||||
RSASSA_PKCS1_v1_5_verify(
|
||||
self.hash, signature, TEST_KEY_PUBLIC_EXPONENT,
|
||||
TEST_KEY_MODULUS))
|
||||
self.hash, signature, TEST_PK))
|
||||
|
||||
def test_invalid_signature(self):
|
||||
invalid_key = TEST_PK.copy()
|
||||
invalid_key['modulus'] += 1
|
||||
self.assertFalse(
|
||||
RSASSA_PKCS1_v1_5_verify(
|
||||
self.hash, self.test_signature, TEST_KEY_PUBLIC_EXPONENT,
|
||||
TEST_KEY_MODULUS + 1))
|
||||
self.hash, self.test_signature, invalid_key))
|
||||
|
||||
|
||||
def test_suite():
|
||||
|
||||
Reference in New Issue
Block a user