From 519e7aea6de4e8f03b62c6e1dba724aca738882e Mon Sep 17 00:00:00 2001 From: Helder Eijs Date: Mon, 25 Dec 2023 14:49:23 +0100 Subject: [PATCH] Avoid changing signature of RSA._decrypt() method if possible --- lib/Crypto/Cipher/PKCS1_OAEP.py | 2 +- lib/Crypto/Cipher/PKCS1_v1_5.py | 2 +- lib/Crypto/PublicKey/RSA.py | 7 ++++++- lib/Crypto/SelfTest/PublicKey/test_RSA.py | 8 ++++++-- lib/Crypto/SelfTest/PublicKey/test_import_RSA.py | 4 ++-- lib/Crypto/Signature/pkcs1_15.py | 2 +- lib/Crypto/Signature/pss.py | 2 +- 7 files changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/Crypto/Cipher/PKCS1_OAEP.py b/lib/Crypto/Cipher/PKCS1_OAEP.py index 8b0f89fc..a4a9132e 100644 --- a/lib/Crypto/Cipher/PKCS1_OAEP.py +++ b/lib/Crypto/Cipher/PKCS1_OAEP.py @@ -168,7 +168,7 @@ def decrypt(self, ciphertext): # Step 2a (O2SIP) ct_int = bytes_to_long(ciphertext) # Step 2b (RSADP) and step 2c (I2OSP) - em = self._key._decrypt(ct_int) + em = self._key._decrypt_to_bytes(ct_int) # Step 3a lHash = self._hashObj.new(self._label).digest() # Step 3b diff --git a/lib/Crypto/Cipher/PKCS1_v1_5.py b/lib/Crypto/Cipher/PKCS1_v1_5.py index db5e7315..a08ed650 100644 --- a/lib/Crypto/Cipher/PKCS1_v1_5.py +++ b/lib/Crypto/Cipher/PKCS1_v1_5.py @@ -177,7 +177,7 @@ def decrypt(self, ciphertext, sentinel, expected_pt_len=0): ct_int = bytes_to_long(ciphertext) # Step 2b (RSADP) and Step 2c (I2OSP) - em = self._key._decrypt(ct_int) + em = self._key._decrypt_to_bytes(ct_int) # Step 3 (not constant time when the sentinel is not a byte string) output = bytes(bytearray(k)) diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py index 9f4a0d35..fd8f8547 100644 --- a/lib/Crypto/PublicKey/RSA.py +++ b/lib/Crypto/PublicKey/RSA.py @@ -181,7 +181,7 @@ def _encrypt(self, plaintext): raise ValueError("Plaintext too large") return int(pow(Integer(plaintext), self._e, self._n)) - def _decrypt(self, ciphertext): + def _decrypt_to_bytes(self, ciphertext): if not 0 <= ciphertext < self._n: raise ValueError("Ciphertext too large") if not self.has_private(): @@ -206,6 +206,11 @@ def _decrypt(self, ciphertext): self._n) return result + def _decrypt(self, ciphertext): + """Legacy private method""" + + return bytes_to_long(self._decrypt_to_bytes(ciphertext)) + def has_private(self): """Whether this is an RSA private key""" diff --git a/lib/Crypto/SelfTest/PublicKey/test_RSA.py b/lib/Crypto/SelfTest/PublicKey/test_RSA.py index f85e9dcd..45ca70e6 100644 --- a/lib/Crypto/SelfTest/PublicKey/test_RSA.py +++ b/lib/Crypto/SelfTest/PublicKey/test_RSA.py @@ -214,9 +214,11 @@ def test_raw_rsa_boundary(self): rsa_obj = self.rsa.generate(1024) self.assertRaises(ValueError, rsa_obj._decrypt, rsa_obj.n) + self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, rsa_obj.n) self.assertRaises(ValueError, rsa_obj._encrypt, rsa_obj.n) self.assertRaises(ValueError, rsa_obj._decrypt, -1) + self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, -1) self.assertRaises(ValueError, rsa_obj._encrypt, -1) def test_size(self): @@ -265,6 +267,8 @@ def _check_public_key(self, rsaObj): # Public keys should not be able to sign or decrypt self.assertRaises(TypeError, rsaObj._decrypt, bytes_to_long(ciphertext)) + self.assertRaises(TypeError, rsaObj._decrypt_to_bytes, + bytes_to_long(ciphertext)) # Check __eq__ and __ne__ self.assertEqual(rsaObj.public_key() == rsaObj.public_key(),True) # assert_ @@ -279,7 +283,7 @@ def _exercise_primitive(self, rsaObj): ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) # Test decryption - plaintext = bytes_to_long(rsaObj._decrypt(ciphertext)) + plaintext = rsaObj._decrypt(ciphertext) # Test encryption (2 arguments) new_ciphertext2 = rsaObj._encrypt(plaintext) @@ -304,7 +308,7 @@ def _check_decryption(self, rsaObj): ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) # Test plain decryption - new_plaintext = bytes_to_long(rsaObj._decrypt(ciphertext)) + new_plaintext = rsaObj._decrypt(ciphertext) self.assertEqual(plaintext, new_plaintext) diff --git a/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py b/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py index 06f7e97d..94999414 100644 --- a/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py +++ b/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py @@ -239,13 +239,13 @@ def testImportKey4bytes(self): def testImportKey5(self): """Verifies that the imported key is still a valid RSA pair""" key = RSA.importKey(self.rsaKeyPEM) - idem = key._encrypt(bytes_to_long(key._decrypt(89))) + idem = key._encrypt(key._decrypt(89)) self.assertEqual(idem, 89) def testImportKey6(self): """Verifies that the imported key is still a valid RSA pair""" key = RSA.importKey(self.rsaKeyDER) - idem = key._encrypt(bytes_to_long(key._decrypt(65))) + idem = key._encrypt(key._decrypt(65)) self.assertEqual(idem, 65) def testImportKey7(self): diff --git a/lib/Crypto/Signature/pkcs1_15.py b/lib/Crypto/Signature/pkcs1_15.py index 90da4ab6..0b02d998 100644 --- a/lib/Crypto/Signature/pkcs1_15.py +++ b/lib/Crypto/Signature/pkcs1_15.py @@ -78,7 +78,7 @@ def sign(self, msg_hash): # Step 2a (OS2IP) em_int = bytes_to_long(em) # Step 2b (RSASP1) and Step 2c (I2OSP) - signature = self._key._decrypt(em_int) + signature = self._key._decrypt_to_bytes(em_int) # Verify no faults occurred if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): raise ValueError("Fault detected in RSA private key operation") diff --git a/lib/Crypto/Signature/pss.py b/lib/Crypto/Signature/pss.py index eeb7082e..f2295df6 100644 --- a/lib/Crypto/Signature/pss.py +++ b/lib/Crypto/Signature/pss.py @@ -108,7 +108,7 @@ def sign(self, msg_hash): # Step 2a (OS2IP) em_int = bytes_to_long(em) # Step 2b (RSASP1) and Step 2c (I2OSP) - signature = self._key._decrypt(em_int) + signature = self._key._decrypt_to_bytes(em_int) # Verify no faults occurred if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n): raise ValueError("Fault detected in RSA private key operation")