OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 # |
| 3 # SelfTest/Cipher/test_pkcs1_oaep.py: Self-test for PKCS#1 OAEP 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 |
| 23 from __future__ import nested_scopes |
| 24 |
| 25 __revision__ = "$Id$" |
| 26 |
| 27 import unittest |
| 28 |
| 29 from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex |
| 30 |
| 31 from Crypto.Util.py3compat import * |
| 32 from Crypto.PublicKey import RSA |
| 33 from Crypto.Cipher import PKCS1_OAEP as PKCS |
| 34 from Crypto.Hash import MD2,MD5,SHA as SHA1,SHA256,RIPEMD |
| 35 from Crypto import Random |
| 36 |
| 37 def rws(t): |
| 38 """Remove white spaces, tabs, and new lines from a string""" |
| 39 for c in ['\n', '\t', ' ']: |
| 40 t = t.replace(c,'') |
| 41 return t |
| 42 |
| 43 def t2b(t): |
| 44 """Convert a text string with bytes in hex form to a byte string""" |
| 45 clean = rws(t) |
| 46 if len(clean)%2 == 1: |
| 47 raise ValueError("Even number of characters expected") |
| 48 return a2b_hex(clean) |
| 49 |
| 50 class PKCS1_OAEP_Tests(unittest.TestCase): |
| 51 |
| 52 def setUp(self): |
| 53 self.rng = Random.new().read |
| 54 self.key1024 = RSA.generate(1024, self.rng) |
| 55 |
| 56 # List of tuples with test data for PKCS#1 OAEP |
| 57 # Each tuple is made up by: |
| 58 # Item #0: dictionary with RSA key component |
| 59 # Item #1: plaintext |
| 60 # Item #2: ciphertext |
| 61 # Item #3: random data (=seed) |
| 62 # Item #4: hash object |
| 63 |
| 64 _testData = ( |
| 65 |
| 66 # |
| 67 # From in oaep-int.txt to be found in |
| 68 # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip |
| 69 # |
| 70 ( |
| 71 # Private key |
| 72 { |
| 73 'n':'''bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 |
| 74 36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f |
| 75 b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48 |
| 76 76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f |
| 77 af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84 |
| 78 ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e |
| 79 e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f |
| 80 e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb''', |
| 81 # Public key |
| 82 'e':'11', |
| 83 # In the test vector, only p and q were given... |
| 84 # d is computed offline as e^{-1} mod (p-1)(q-1) |
| 85 'd':'''a5dafc5341faf289c4b988db30c1cdf83f31251e0 |
| 86 668b42784813801579641b29410b3c7998d6bc465745e5c3 |
| 87 92669d6870da2c082a939e37fdcb82ec93edac97ff3ad595 |
| 88 0accfbc111c76f1a9529444e56aaf68c56c092cd38dc3bef |
| 89 5d20a939926ed4f74a13eddfbe1a1cecc4894af9428c2b7b |
| 90 8883fe4463a4bc85b1cb3c1''' |
| 91 } |
| 92 , |
| 93 # Plaintext |
| 94 '''d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49''', |
| 95 # Ciphertext |
| 96 '''12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 |
| 97 39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7 |
| 98 63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 |
| 99 53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb |
| 100 6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0 |
| 101 24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 |
| 102 da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d |
| 103 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55''', |
| 104 # Random |
| 105 '''aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 |
| 106 f0 6c b5 8f''', |
| 107 # Hash |
| 108 SHA1, |
| 109 ), |
| 110 |
| 111 # |
| 112 # From in oaep-vect.txt to be found in Example 1.1 |
| 113 # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip |
| 114 # |
| 115 ( |
| 116 # Private key |
| 117 { |
| 118 'n':'''a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 |
| 119 91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab |
| 120 c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 |
| 121 12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 |
| 122 f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 |
| 123 c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 |
| 124 8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 |
| 125 76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb''', |
| 126 'e':'''01 00 01''', |
| 127 'd':'''53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c |
| 128 55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd |
| 129 8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b |
| 130 15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 |
| 131 fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 |
| 132 2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf |
| 133 b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de |
| 134 f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 ''' |
| 135 } |
| 136 , |
| 137 # Plaintext |
| 138 '''66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 |
| 139 97 d5 0d ba 79 b9 87 00 4a fe fe 34''', |
| 140 # Ciphertext |
| 141 '''35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f |
| 142 7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb |
| 143 21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01 |
| 144 03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f |
| 145 a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22 |
| 146 d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26 |
| 147 d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c |
| 148 40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a''', |
| 149 # Random |
| 150 '''18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 |
| 151 dd a0 a5 ef''', |
| 152 SHA1 |
| 153 ), |
| 154 |
| 155 # |
| 156 # From in oaep-vect.txt to be found in Example 2.1 |
| 157 # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip |
| 158 # |
| 159 ( |
| 160 # Private key |
| 161 { |
| 162 'n':'''01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5 |
| 163 e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e |
| 164 49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba |
| 165 7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d |
| 166 0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d |
| 167 de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05 |
| 168 5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66 |
| 169 32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f |
| 170 45''', |
| 171 'e':'''01 00 01''', |
| 172 'd':'''08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa |
| 173 4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93 |
| 174 c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47 |
| 175 39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc |
| 176 d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0 |
| 177 8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59 |
| 178 41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25 |
| 179 25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39''' |
| 180 }, |
| 181 # Plaintext |
| 182 '''8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6 |
| 183 52 b5 8c f1 d9 2f ec 57 0b ee e7''', |
| 184 # Ciphertext |
| 185 '''01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99 |
| 186 2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a |
| 187 5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a |
| 188 ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34 |
| 189 56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d |
| 190 56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a |
| 191 bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f |
| 192 ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72 |
| 193 0e''', |
| 194 # Random |
| 195 '''8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94 |
| 196 e7 1b 17 82''', |
| 197 SHA1 |
| 198 ), |
| 199 |
| 200 # |
| 201 # From in oaep-vect.txt to be found in Example 10.1 |
| 202 # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip |
| 203 # |
| 204 ( |
| 205 # Private key |
| 206 { |
| 207 'n':'''ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d |
| 208 db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8 |
| 209 df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4 |
| 210 02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5 |
| 211 40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d |
| 212 4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f |
| 213 a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1 |
| 214 2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0 |
| 215 33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a |
| 216 53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00 |
| 217 c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8 |
| 218 4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef |
| 219 a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76 |
| 220 57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88 |
| 221 d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc |
| 222 36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb''', |
| 223 'e':'''01 00 01''', |
| 224 'd':'''05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85 |
| 225 25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59 |
| 226 6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0 |
| 227 d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d |
| 228 19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80 |
| 229 4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be |
| 230 be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19 |
| 231 34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10 |
| 232 2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2 |
| 233 4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64 |
| 234 fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1 |
| 235 3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43 |
| 236 0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87 |
| 237 6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01 |
| 238 84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e |
| 239 97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79''' |
| 240 }, |
| 241 # Plaintext |
| 242 '''8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70 |
| 243 b0 89 53 b0 6b 4e b2 05 bc 16 94 ee''', |
| 244 # Ciphertext |
| 245 '''53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15 |
| 246 52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19 |
| 247 ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee |
| 248 e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14 |
| 249 4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a |
| 250 8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc |
| 251 c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb |
| 252 ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87 |
| 253 74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec |
| 254 6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1 |
| 255 fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62 |
| 256 93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05 |
| 257 ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55 |
| 258 ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64 |
| 259 73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54 |
| 260 bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc''', |
| 261 # Random |
| 262 '''47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0 |
| 263 aa 63 bd 33''', |
| 264 SHA1 |
| 265 ), |
| 266 ) |
| 267 |
| 268 def testEncrypt1(self): |
| 269 # Verify encryption using all test vectors |
| 270 for test in self._testData: |
| 271 # Build the key |
| 272 comps = [ long(rws(test[0][x]),16) for x in ('n','e') ] |
| 273 key = RSA.construct(comps) |
| 274 # RNG that takes its random numbers from a pool given |
| 275 # at initialization |
| 276 class randGen: |
| 277 def __init__(self, data): |
| 278 self.data = data |
| 279 self.idx = 0 |
| 280 def __call__(self, N): |
| 281 r = self.data[self.idx:N] |
| 282 self.idx += N |
| 283 return r |
| 284 # The real test |
| 285 key._randfunc = randGen(t2b(test[3])) |
| 286 cipher = PKCS.new(key, test[4]) |
| 287 ct = cipher.encrypt(t2b(test[1])) |
| 288 self.assertEqual(ct, t2b(test[2])) |
| 289 |
| 290 def testEncrypt2(self): |
| 291 # Verify that encryption fails if plaintext is too long |
| 292 pt = '\x00'*(128-2*20-2+1) |
| 293 cipher = PKCS.new(self.key1024) |
| 294 self.assertRaises(ValueError, cipher.encrypt, pt) |
| 295 |
| 296 def testDecrypt1(self): |
| 297 # Verify decryption using all test vectors |
| 298 for test in self._testData: |
| 299 # Build the key |
| 300 comps = [ long(rws(test[0][x]),16) for x in ('n','e','d'
) ] |
| 301 key = RSA.construct(comps) |
| 302 # The real test |
| 303 cipher = PKCS.new(key, test[4]) |
| 304 pt = cipher.decrypt(t2b(test[2])) |
| 305 self.assertEqual(pt, t2b(test[1])) |
| 306 |
| 307 def testDecrypt2(self): |
| 308 # Simplest possible negative tests |
| 309 for ct_size in (127,128,129): |
| 310 cipher = PKCS.new(self.key1024) |
| 311 self.assertRaises(ValueError, cipher.decrypt, bchr(0x00)*ct_
size) |
| 312 |
| 313 def testEncryptDecrypt1(self): |
| 314 # Encrypt/Decrypt messages of length [0..128-2*20-2] |
| 315 for pt_len in xrange(0,128-2*20-2): |
| 316 pt = self.rng(pt_len) |
| 317 ct = PKCS.encrypt(pt, self.key1024) |
| 318 pt2 = PKCS.decrypt(ct, self.key1024) |
| 319 self.assertEqual(pt,pt2) |
| 320 |
| 321 def testEncryptDecrypt1(self): |
| 322 # Helper function to monitor what's requested from RNG |
| 323 global asked |
| 324 def localRng(N): |
| 325 global asked |
| 326 asked += N |
| 327 return self.rng(N) |
| 328 # Verify that OAEP is friendly to all hashes |
| 329 for hashmod in (MD2,MD5,SHA1,SHA256,RIPEMD): |
| 330 # Verify that encrypt() asks for as many random bytes |
| 331 # as the hash output size |
| 332 asked = 0 |
| 333 pt = self.rng(40) |
| 334 self.key1024._randfunc = localRng |
| 335 cipher = PKCS.new(self.key1024, hashmod) |
| 336 ct = cipher.encrypt(pt) |
| 337 self.assertEqual(cipher.decrypt(ct), pt) |
| 338 self.failUnless(asked > hashmod.digest_size) |
| 339 |
| 340 def testEncryptDecrypt2(self): |
| 341 # Verify that OAEP supports labels |
| 342 pt = self.rng(35) |
| 343 xlabel = self.rng(22) |
| 344 cipher = PKCS.new(self.key1024, label=xlabel) |
| 345 ct = cipher.encrypt(pt) |
| 346 self.assertEqual(cipher.decrypt(ct), pt) |
| 347 |
| 348 def testEncryptDecrypt3(self): |
| 349 # Verify that encrypt() uses the custom MGF |
| 350 global mgfcalls |
| 351 # Helper function to monitor what's requested from MGF |
| 352 def newMGF(seed,maskLen): |
| 353 global mgfcalls |
| 354 mgfcalls += 1 |
| 355 return bchr(0x00)*maskLen |
| 356 mgfcalls = 0 |
| 357 pt = self.rng(32) |
| 358 cipher = PKCS.new(self.key1024, mgfunc=newMGF) |
| 359 ct = cipher.encrypt(pt) |
| 360 self.assertEqual(mgfcalls, 2) |
| 361 self.assertEqual(cipher.decrypt(ct), pt) |
| 362 |
| 363 def get_tests(config={}): |
| 364 tests = [] |
| 365 tests += list_test_cases(PKCS1_OAEP_Tests) |
| 366 return tests |
| 367 |
| 368 if __name__ == '__main__': |
| 369 suite = lambda: unittest.TestSuite(get_tests()) |
| 370 unittest.main(defaultTest='suite') |
| 371 |
| 372 # vim:set ts=4 sw=4 sts=4 expandtab: |
OLD | NEW |