test_load_save_keys.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # https://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Unittest for saving and loading keys."""
  15. import base64
  16. import os.path
  17. import pickle
  18. import unittest
  19. import warnings
  20. from unittest import mock
  21. import rsa.key
  22. B64PRIV_DER = b"MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt"
  23. PRIVATE_DER = base64.standard_b64decode(B64PRIV_DER)
  24. B64PUB_DER = b"MAwCBQDeKYlRAgMBAAE="
  25. PUBLIC_DER = base64.standard_b64decode(B64PUB_DER)
  26. PRIVATE_PEM = (
  27. b"""\
  28. -----BEGIN CONFUSING STUFF-----
  29. Cruft before the key
  30. -----BEGIN RSA PRIVATE KEY-----
  31. Comment: something blah
  32. """
  33. + B64PRIV_DER
  34. + b"""
  35. -----END RSA PRIVATE KEY-----
  36. Stuff after the key
  37. -----END CONFUSING STUFF-----
  38. """
  39. )
  40. CLEAN_PRIVATE_PEM = (
  41. b"""\
  42. -----BEGIN RSA PRIVATE KEY-----
  43. """
  44. + B64PRIV_DER
  45. + b"""
  46. -----END RSA PRIVATE KEY-----
  47. """
  48. )
  49. PUBLIC_PEM = (
  50. b"""\
  51. -----BEGIN CONFUSING STUFF-----
  52. Cruft before the key
  53. -----BEGIN RSA PUBLIC KEY-----
  54. Comment: something blah
  55. """
  56. + B64PUB_DER
  57. + b"""
  58. -----END RSA PUBLIC KEY-----
  59. Stuff after the key
  60. -----END CONFUSING STUFF-----
  61. """
  62. )
  63. CLEAN_PUBLIC_PEM = (
  64. b"""\
  65. -----BEGIN RSA PUBLIC KEY-----
  66. """
  67. + B64PUB_DER
  68. + b"""
  69. -----END RSA PUBLIC KEY-----
  70. """
  71. )
  72. class DerTest(unittest.TestCase):
  73. """Test saving and loading DER keys."""
  74. def test_load_private_key(self):
  75. """Test loading private DER keys."""
  76. key = rsa.key.PrivateKey.load_pkcs1(PRIVATE_DER, "DER")
  77. expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
  78. self.assertEqual(expected, key)
  79. self.assertEqual(key.exp1, 55063)
  80. self.assertEqual(key.exp2, 10095)
  81. self.assertEqual(key.coef, 50797)
  82. @mock.patch("pyasn1.codec.der.decoder.decode")
  83. def test_load_malformed_private_key(self, der_decode):
  84. """Test loading malformed private DER keys."""
  85. # Decode returns an invalid exp2 value.
  86. der_decode.return_value = (
  87. [0, 3727264081, 65537, 3349121513, 65063, 57287, 55063, 0, 50797],
  88. 0,
  89. )
  90. with warnings.catch_warnings(record=True) as w:
  91. # Always print warnings
  92. warnings.simplefilter("always")
  93. # Load 3 keys
  94. for _ in range(3):
  95. key = rsa.key.PrivateKey.load_pkcs1(PRIVATE_DER, "DER")
  96. # Check that 3 warnings were generated.
  97. self.assertEqual(3, len(w))
  98. for warning in w:
  99. self.assertTrue(issubclass(warning.category, UserWarning))
  100. self.assertIn("malformed", str(warning.message))
  101. # Check that we are creating the key with correct values
  102. self.assertEqual(key.exp1, 55063)
  103. self.assertEqual(key.exp2, 10095)
  104. self.assertEqual(key.coef, 50797)
  105. def test_save_private_key(self):
  106. """Test saving private DER keys."""
  107. key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
  108. der = key.save_pkcs1("DER")
  109. self.assertIsInstance(der, bytes)
  110. self.assertEqual(PRIVATE_DER, der)
  111. def test_load_public_key(self):
  112. """Test loading public DER keys."""
  113. key = rsa.key.PublicKey.load_pkcs1(PUBLIC_DER, "DER")
  114. expected = rsa.key.PublicKey(3727264081, 65537)
  115. self.assertEqual(expected, key)
  116. def test_save_public_key(self):
  117. """Test saving public DER keys."""
  118. key = rsa.key.PublicKey(3727264081, 65537)
  119. der = key.save_pkcs1("DER")
  120. self.assertIsInstance(der, bytes)
  121. self.assertEqual(PUBLIC_DER, der)
  122. class PemTest(unittest.TestCase):
  123. """Test saving and loading PEM keys."""
  124. def test_load_private_key(self):
  125. """Test loading private PEM files."""
  126. key = rsa.key.PrivateKey.load_pkcs1(PRIVATE_PEM, "PEM")
  127. expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
  128. self.assertEqual(expected, key)
  129. self.assertEqual(key.exp1, 55063)
  130. self.assertEqual(key.exp2, 10095)
  131. self.assertEqual(key.coef, 50797)
  132. def test_save_private_key(self):
  133. """Test saving private PEM files."""
  134. key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
  135. pem = key.save_pkcs1("PEM")
  136. self.assertIsInstance(pem, bytes)
  137. self.assertEqual(CLEAN_PRIVATE_PEM, pem)
  138. def test_load_public_key(self):
  139. """Test loading public PEM files."""
  140. key = rsa.key.PublicKey.load_pkcs1(PUBLIC_PEM, "PEM")
  141. expected = rsa.key.PublicKey(3727264081, 65537)
  142. self.assertEqual(expected, key)
  143. def test_save_public_key(self):
  144. """Test saving public PEM files."""
  145. key = rsa.key.PublicKey(3727264081, 65537)
  146. pem = key.save_pkcs1("PEM")
  147. self.assertIsInstance(pem, bytes)
  148. self.assertEqual(CLEAN_PUBLIC_PEM, pem)
  149. def test_load_from_disk(self):
  150. """Test loading a PEM file from disk."""
  151. from yatest.common import source_path
  152. fname = source_path("contrib/python/rsa/py3/tests/private.pem")
  153. with open(fname, mode="rb") as privatefile:
  154. keydata = privatefile.read()
  155. privkey = rsa.key.PrivateKey.load_pkcs1(keydata)
  156. self.assertEqual(15945948582725241569, privkey.p)
  157. self.assertEqual(14617195220284816877, privkey.q)
  158. class PickleTest(unittest.TestCase):
  159. """Test saving and loading keys by pickling."""
  160. def test_private_key(self):
  161. pk = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
  162. pickled = pickle.dumps(pk)
  163. unpickled = pickle.loads(pickled)
  164. self.assertEqual(pk, unpickled)
  165. for attr in rsa.key.AbstractKey.__slots__:
  166. self.assertTrue(hasattr(unpickled, attr))
  167. def test_public_key(self):
  168. pk = rsa.key.PublicKey(3727264081, 65537)
  169. pickled = pickle.dumps(pk)
  170. unpickled = pickle.loads(pickled)
  171. self.assertEqual(pk, unpickled)
  172. for attr in rsa.key.AbstractKey.__slots__:
  173. self.assertTrue(hasattr(unpickled, attr))