test_pkcs1_15.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. # -*- coding: utf-8 -*-
  2. #
  3. # SelfTest/Cipher/test_pkcs1_15.py: Self-test for PKCS#1 v1.5 encryption
  4. #
  5. # ===================================================================
  6. # The contents of this file are dedicated to the public domain. To
  7. # the extent that dedication to the public domain is not available,
  8. # everyone is granted a worldwide, perpetual, royalty-free,
  9. # non-exclusive license to exercise all rights associated with the
  10. # contents of this file for any purpose whatsoever.
  11. # No rights are reserved.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  17. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  18. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. # ===================================================================
  22. from __future__ import print_function
  23. import unittest
  24. from Cryptodome.PublicKey import RSA
  25. from Cryptodome.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
  26. from Cryptodome import Random
  27. from Cryptodome.Cipher import PKCS1_v1_5 as PKCS
  28. from Cryptodome.Util.py3compat import b
  29. from Cryptodome.Util.number import bytes_to_long, long_to_bytes
  30. def rws(t):
  31. """Remove white spaces, tabs, and new lines from a string"""
  32. for c in ['\n', '\t', ' ']:
  33. t = t.replace(c,'')
  34. return t
  35. def t2b(t):
  36. """Convert a text string with bytes in hex form to a byte string"""
  37. clean = b(rws(t))
  38. if len(clean)%2 == 1:
  39. raise ValueError("Even number of characters expected")
  40. return a2b_hex(clean)
  41. class PKCS1_15_Tests(unittest.TestCase):
  42. def setUp(self):
  43. self.rng = Random.new().read
  44. self.key1024 = RSA.generate(1024, self.rng)
  45. # List of tuples with test data for PKCS#1 v1.5.
  46. # Each tuple is made up by:
  47. # Item #0: dictionary with RSA key component, or key to import
  48. # Item #1: plaintext
  49. # Item #2: ciphertext
  50. # Item #3: random data
  51. _testData = (
  52. #
  53. # Generated with openssl 0.9.8o
  54. #
  55. (
  56. # Private key
  57. '''-----BEGIN RSA PRIVATE KEY-----
  58. MIICXAIBAAKBgQDAiAnvIAOvqVwJTaYzsKnefZftgtXGE2hPJppGsWl78yz9jeXY
  59. W/FxX/gTPURArNhdnhP6n3p2ZaDIBrO2zizbgIXs0IsljTTcr4vnI8fMXzyNUOjA
  60. zP3nzMqZDZK6757XQAobOssMkBFqRWwilT/3DsBhRpl3iMUhF+wvpTSHewIDAQAB
  61. AoGAC4HV/inOrpgTvSab8Wj0riyZgQOZ3U3ZpSlsfR8ra9Ib9Uee3jCYnKscu6Gk
  62. y6zI/cdt8EPJ4PuwAWSNJzbpbVaDvUq25OD+CX8/uRT08yBS4J8TzBitZJTD4lS7
  63. atdTnKT0Wmwk+u8tDbhvMKwnUHdJLcuIsycts9rwJVapUtkCQQDvDpx2JMun0YKG
  64. uUttjmL8oJ3U0m3ZvMdVwBecA0eebZb1l2J5PvI3EJD97eKe91Nsw8T3lwpoN40k
  65. IocSVDklAkEAzi1HLHE6EzVPOe5+Y0kGvrIYRRhncOb72vCvBZvD6wLZpQgqo6c4
  66. d3XHFBBQWA6xcvQb5w+VVEJZzw64y25sHwJBAMYReRl6SzL0qA0wIYrYWrOt8JeQ
  67. 8mthulcWHXmqTgC6FEXP9Es5GD7/fuKl4wqLKZgIbH4nqvvGay7xXLCXD/ECQH9a
  68. 1JYNMtRen5unSAbIOxRcKkWz92F0LKpm9ZW/S9vFHO+mBcClMGoKJHiuQxLBsLbT
  69. NtEZfSJZAeS2sUtn3/0CQDb2M2zNBTF8LlM0nxmh0k9VGm5TVIyBEMcipmvOgqIs
  70. HKukWBcq9f/UOmS0oEhai/6g+Uf7VHJdWaeO5LzuvwU=
  71. -----END RSA PRIVATE KEY-----''',
  72. # Plaintext
  73. '''THIS IS PLAINTEXT\x0A''',
  74. # Ciphertext
  75. '''3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36
  76. 8f 8f d9 e3 13 1c 7f c8 b3 f9 c1 08 e4 eb 79 9c
  77. 91 89 1f 96 3b 94 77 61 99 a4 b1 ee 5d e6 17 c9
  78. 5d 0a b5 63 52 0a eb 00 45 38 2a fb b0 71 3d 11
  79. f7 a1 9e a7 69 b3 af 61 c0 bb 04 5b 5d 4b 27 44
  80. 1f 5b 97 89 ba 6a 08 95 ee 4f a2 eb 56 64 e5 0f
  81. da 7c f9 9a 61 61 06 62 ed a0 bc 5f aa 6c 31 78
  82. 70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75''',
  83. # Random data
  84. '''eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d
  85. 61 6c af 67 b8 4e 17 56 80 66 36 04 64 34 26 8a
  86. 47 dd 44 b3 1a b2 17 60 f4 91 2e e2 b5 95 64 cc
  87. f9 da c8 70 94 54 86 4c ef 5b 08 7d 18 c4 ab 8d
  88. 04 06 33 8f ca 15 5f 52 60 8a a1 0c f5 08 b5 4c
  89. bb 99 b8 94 25 04 9c e6 01 75 e6 f9 63 7a 65 61
  90. 13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5'''
  91. ),
  92. )
  93. def testEncrypt1(self):
  94. for test in self._testData:
  95. # Build the key
  96. key = RSA.importKey(test[0])
  97. # RNG that takes its random numbers from a pool given
  98. # at initialization
  99. class randGen:
  100. def __init__(self, data):
  101. self.data = data
  102. self.idx = 0
  103. def __call__(self, N):
  104. r = self.data[self.idx:self.idx+N]
  105. self.idx += N
  106. return r
  107. # The real test
  108. cipher = PKCS.new(key, randfunc=randGen(t2b(test[3])))
  109. ct = cipher.encrypt(b(test[1]))
  110. self.assertEqual(ct, t2b(test[2]))
  111. def testEncrypt2(self):
  112. # Verify that encryption fail if plaintext is too long
  113. pt = '\x00'*(128-11+1)
  114. cipher = PKCS.new(self.key1024)
  115. self.assertRaises(ValueError, cipher.encrypt, pt)
  116. def testVerify1(self):
  117. for test in self._testData:
  118. # Build the key
  119. key = RSA.importKey(test[0])
  120. # The real test
  121. cipher = PKCS.new(key)
  122. pt = cipher.decrypt(t2b(test[2]), "---")
  123. self.assertEqual(pt, b(test[1]))
  124. def testVerify2(self):
  125. # Verify that decryption fails if ciphertext is not as long as
  126. # RSA modulus
  127. cipher = PKCS.new(self.key1024)
  128. self.assertRaises(ValueError, cipher.decrypt, '\x00'*127, "---")
  129. self.assertRaises(ValueError, cipher.decrypt, '\x00'*129, "---")
  130. # Verify that decryption fails if there are less then 8 non-zero padding
  131. # bytes
  132. pt = b('\x00\x02' + '\xFF'*7 + '\x00' + '\x45'*118)
  133. pt_int = bytes_to_long(pt)
  134. ct_int = self.key1024._encrypt(pt_int)
  135. ct = long_to_bytes(ct_int, 128)
  136. self.assertEqual("---", cipher.decrypt(ct, "---"))
  137. def testEncryptVerify1(self):
  138. # Encrypt/Verify messages of length [0..RSAlen-11]
  139. # and therefore padding [8..117]
  140. for pt_len in range(0,128-11+1):
  141. pt = self.rng(pt_len)
  142. cipher = PKCS.new(self.key1024)
  143. ct = cipher.encrypt(pt)
  144. pt2 = cipher.decrypt(ct, "---")
  145. self.assertEqual(pt,pt2)
  146. def testByteArray(self):
  147. pt = b"XER"
  148. cipher = PKCS.new(self.key1024)
  149. ct = cipher.encrypt(bytearray(pt))
  150. pt2 = cipher.decrypt(bytearray(ct), "---")
  151. self.assertEqual(pt, pt2)
  152. def testMemoryview(self):
  153. pt = b"XER"
  154. cipher = PKCS.new(self.key1024)
  155. ct = cipher.encrypt(memoryview(bytearray(pt)))
  156. pt2 = cipher.decrypt(memoryview(bytearray(ct)), "---")
  157. self.assertEqual(pt, pt2)
  158. import sys
  159. if sys.version[:3] == "2.6":
  160. del testMemoryview
  161. def get_tests(config={}):
  162. tests = []
  163. tests += list_test_cases(PKCS1_15_Tests)
  164. return tests
  165. if __name__ == '__main__':
  166. suite = lambda: unittest.TestSuite(get_tests())
  167. unittest.main(defaultTest='suite')
  168. # vim:set ts=4 sw=4 sts=4 expandtab: