test_load_save_keys.py 6.2 KB

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