Roy Kokkelkoren | 0659aac | 2015-10-25 15:12:11 | [diff] [blame] | 1 | # Copyright 2011 Sybren A. Stüvel <[email protected]> |
| 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 | # |
Sybren A. Stüvel | 3934ab4 | 2016-02-05 15:01:20 | [diff] [blame] | 7 | # https://www.apache.org/licenses/LICENSE-2.0 |
Roy Kokkelkoren | 0659aac | 2015-10-25 15:12:11 | [diff] [blame] | 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 | |
Sybren A. Stüvel | f0627be | 2016-03-17 14:52:23 | [diff] [blame] | 15 | """Unittest for saving and loading keys.""" |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 16 | |
| 17 | import base64 |
Sybren A. Stüvel | f68c52a | 2016-01-18 14:39:50 | [diff] [blame] | 18 | import os.path |
Sybren A. Stüvel | 4bc9733 | 2016-01-22 14:41:40 | [diff] [blame] | 19 | import pickle |
Michael Manganiello | 0c90633 | 2017-01-05 12:51:12 | [diff] [blame] | 20 | import unittest |
| 21 | import warnings |
Sybren A. Stüvel | ded036c | 2019-08-04 13:02:20 | [diff] [blame] | 22 | from unittest import mock |
Sybren A. Stüvel | f68c52a | 2016-01-18 14:39:50 | [diff] [blame] | 23 | |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 24 | import rsa.key |
| 25 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 26 | B64PRIV_DER = b'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt' |
Sybren A. Stüvel | e798a6e | 2016-01-18 14:39:00 | [diff] [blame] | 27 | PRIVATE_DER = base64.standard_b64decode(B64PRIV_DER) |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 28 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 29 | B64PUB_DER = b'MAwCBQDeKYlRAgMBAAE=' |
Sybren A. Stüvel | e798a6e | 2016-01-18 14:39:00 | [diff] [blame] | 30 | PUBLIC_DER = base64.standard_b64decode(B64PUB_DER) |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 31 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 32 | PRIVATE_PEM = b'''\ |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 33 | -----BEGIN CONFUSING STUFF----- |
| 34 | Cruft before the key |
| 35 | |
| 36 | -----BEGIN RSA PRIVATE KEY----- |
Sybren A. Stüvel | 70bc1a5 | 2011-07-30 18:13:09 | [diff] [blame] | 37 | Comment: something blah |
| 38 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 39 | ''' + B64PRIV_DER + b''' |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 40 | -----END RSA PRIVATE KEY----- |
| 41 | |
| 42 | Stuff after the key |
| 43 | -----END CONFUSING STUFF----- |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 44 | ''' |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 45 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 46 | CLEAN_PRIVATE_PEM = b'''\ |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 47 | -----BEGIN RSA PRIVATE KEY----- |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 48 | ''' + B64PRIV_DER + b''' |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 49 | -----END RSA PRIVATE KEY----- |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 50 | ''' |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 51 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 52 | PUBLIC_PEM = b'''\ |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 53 | -----BEGIN CONFUSING STUFF----- |
| 54 | Cruft before the key |
| 55 | |
| 56 | -----BEGIN RSA PUBLIC KEY----- |
Sybren A. Stüvel | 70bc1a5 | 2011-07-30 18:13:09 | [diff] [blame] | 57 | Comment: something blah |
| 58 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 59 | ''' + B64PUB_DER + b''' |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 60 | -----END RSA PUBLIC KEY----- |
| 61 | |
| 62 | Stuff after the key |
| 63 | -----END CONFUSING STUFF----- |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 64 | ''' |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 65 | |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 66 | CLEAN_PUBLIC_PEM = b'''\ |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 67 | -----BEGIN RSA PUBLIC KEY----- |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 68 | ''' + B64PUB_DER + b''' |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 69 | -----END RSA PUBLIC KEY----- |
adamantike | 9f57740 | 2016-05-08 18:36:57 | [diff] [blame] | 70 | ''' |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 71 | |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 72 | |
Sybren A. Stüvel | ed1c81d | 2016-01-14 11:23:32 | [diff] [blame] | 73 | class DerTest(unittest.TestCase): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 74 | """Test saving and loading DER keys.""" |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 75 | |
| 76 | def test_load_private_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 77 | """Test loading private DER keys.""" |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 78 | |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 79 | key = rsa.key.PrivateKey.load_pkcs1(PRIVATE_DER, 'DER') |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 80 | expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) |
| 81 | |
| 82 | self.assertEqual(expected, key) |
Michael Manganiello | 0c90633 | 2017-01-05 12:51:12 | [diff] [blame] | 83 | self.assertEqual(key.exp1, 55063) |
| 84 | self.assertEqual(key.exp2, 10095) |
| 85 | self.assertEqual(key.coef, 50797) |
| 86 | |
| 87 | @mock.patch('pyasn1.codec.der.decoder.decode') |
| 88 | def test_load_malformed_private_key(self, der_decode): |
| 89 | """Test loading malformed private DER keys.""" |
| 90 | |
| 91 | # Decode returns an invalid exp2 value. |
| 92 | der_decode.return_value = ( |
| 93 | [0, 3727264081, 65537, 3349121513, 65063, 57287, 55063, 0, 50797], |
| 94 | 0, |
| 95 | ) |
| 96 | |
| 97 | with warnings.catch_warnings(record=True) as w: |
| 98 | # Always print warnings |
| 99 | warnings.simplefilter('always') |
| 100 | |
| 101 | # Load 3 keys |
| 102 | for _ in range(3): |
| 103 | key = rsa.key.PrivateKey.load_pkcs1(PRIVATE_DER, 'DER') |
| 104 | |
| 105 | # Check that 3 warnings were generated. |
| 106 | self.assertEqual(3, len(w)) |
| 107 | |
| 108 | for warning in w: |
| 109 | self.assertTrue(issubclass(warning.category, UserWarning)) |
| 110 | self.assertIn('malformed', str(warning.message)) |
| 111 | |
| 112 | # Check that we are creating the key with correct values |
| 113 | self.assertEqual(key.exp1, 55063) |
| 114 | self.assertEqual(key.exp2, 10095) |
| 115 | self.assertEqual(key.coef, 50797) |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 116 | |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 117 | def test_save_private_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 118 | """Test saving private DER keys.""" |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 119 | |
| 120 | key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 121 | der = key.save_pkcs1('DER') |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 122 | |
Sybren A. Stüvel | f0627be | 2016-03-17 14:52:23 | [diff] [blame] | 123 | self.assertIsInstance(der, bytes) |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 124 | self.assertEqual(PRIVATE_DER, der) |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 125 | |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 126 | def test_load_public_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 127 | """Test loading public DER keys.""" |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 128 | |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 129 | key = rsa.key.PublicKey.load_pkcs1(PUBLIC_DER, 'DER') |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 130 | expected = rsa.key.PublicKey(3727264081, 65537) |
| 131 | |
| 132 | self.assertEqual(expected, key) |
| 133 | |
| 134 | def test_save_public_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 135 | """Test saving public DER keys.""" |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 136 | |
| 137 | key = rsa.key.PublicKey(3727264081, 65537) |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 138 | der = key.save_pkcs1('DER') |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 139 | |
Sybren A. Stüvel | f0627be | 2016-03-17 14:52:23 | [diff] [blame] | 140 | self.assertIsInstance(der, bytes) |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 141 | self.assertEqual(PUBLIC_DER, der) |
| 142 | |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 143 | |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 144 | class PemTest(unittest.TestCase): |
| 145 | """Test saving and loading PEM keys.""" |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 146 | |
| 147 | def test_load_private_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 148 | """Test loading private PEM files.""" |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 149 | |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 150 | key = rsa.key.PrivateKey.load_pkcs1(PRIVATE_PEM, 'PEM') |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 151 | expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) |
| 152 | |
| 153 | self.assertEqual(expected, key) |
Michael Manganiello | 0c90633 | 2017-01-05 12:51:12 | [diff] [blame] | 154 | self.assertEqual(key.exp1, 55063) |
| 155 | self.assertEqual(key.exp2, 10095) |
| 156 | self.assertEqual(key.coef, 50797) |
Sybren A. Stüvel | fa34679 | 2011-07-19 21:53:59 | [diff] [blame] | 157 | |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 158 | def test_save_private_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 159 | """Test saving private PEM files.""" |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 160 | |
| 161 | key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 162 | pem = key.save_pkcs1('PEM') |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 163 | |
Sybren A. Stüvel | f0627be | 2016-03-17 14:52:23 | [diff] [blame] | 164 | self.assertIsInstance(pem, bytes) |
Sybren A. Stüvel | f6a1073 | 2011-07-19 23:11:34 | [diff] [blame] | 165 | self.assertEqual(CLEAN_PRIVATE_PEM, pem) |
| 166 | |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 167 | def test_load_public_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 168 | """Test loading public PEM files.""" |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 169 | |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 170 | key = rsa.key.PublicKey.load_pkcs1(PUBLIC_PEM, 'PEM') |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 171 | expected = rsa.key.PublicKey(3727264081, 65537) |
| 172 | |
| 173 | self.assertEqual(expected, key) |
| 174 | |
| 175 | def test_save_public_key(self): |
Sybren A. Stüvel | d3d1034 | 2016-01-22 10:36:06 | [diff] [blame] | 176 | """Test saving public PEM files.""" |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 177 | |
| 178 | key = rsa.key.PublicKey(3727264081, 65537) |
Sybren A. Stüvel | aa5a7fd | 2011-07-24 17:06:32 | [diff] [blame] | 179 | pem = key.save_pkcs1('PEM') |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 180 | |
Sybren A. Stüvel | f0627be | 2016-03-17 14:52:23 | [diff] [blame] | 181 | self.assertIsInstance(pem, bytes) |
Sybren A. Stüvel | 74023dc | 2011-07-24 16:29:17 | [diff] [blame] | 182 | self.assertEqual(CLEAN_PUBLIC_PEM, pem) |
| 183 | |
Sybren A. Stüvel | f68c52a | 2016-01-18 14:39:50 | [diff] [blame] | 184 | def test_load_from_disk(self): |
| 185 | """Test loading a PEM file from disk.""" |
| 186 | |
| 187 | fname = os.path.join(os.path.dirname(__file__), 'private.pem') |
| 188 | with open(fname, mode='rb') as privatefile: |
| 189 | keydata = privatefile.read() |
| 190 | privkey = rsa.key.PrivateKey.load_pkcs1(keydata) |
| 191 | |
| 192 | self.assertEqual(15945948582725241569, privkey.p) |
| 193 | self.assertEqual(14617195220284816877, privkey.q) |
Sybren A. Stüvel | 4bc9733 | 2016-01-22 14:41:40 | [diff] [blame] | 194 | |
| 195 | |
| 196 | class PickleTest(unittest.TestCase): |
| 197 | """Test saving and loading keys by pickling.""" |
| 198 | |
| 199 | def test_private_key(self): |
| 200 | pk = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) |
| 201 | |
| 202 | pickled = pickle.dumps(pk) |
| 203 | unpickled = pickle.loads(pickled) |
| 204 | self.assertEqual(pk, unpickled) |
| 205 | |
Bu Sun Kim | eb6ddb6 | 2021-02-19 01:05:54 | [diff] [blame^] | 206 | for attr in rsa.key.AbstractKey.__slots__: |
| 207 | self.assertTrue(hasattr(unpickled, attr)) |
| 208 | |
Sybren A. Stüvel | 4bc9733 | 2016-01-22 14:41:40 | [diff] [blame] | 209 | def test_public_key(self): |
| 210 | pk = rsa.key.PublicKey(3727264081, 65537) |
| 211 | |
| 212 | pickled = pickle.dumps(pk) |
| 213 | unpickled = pickle.loads(pickled) |
| 214 | |
| 215 | self.assertEqual(pk, unpickled) |
Bu Sun Kim | eb6ddb6 | 2021-02-19 01:05:54 | [diff] [blame^] | 216 | for attr in rsa.key.AbstractKey.__slots__: |
| 217 | self.assertTrue(hasattr(unpickled, attr)) |