1#!/usr/bin/env python3 2 3import sys 4import unittest 5import struct 6import itertools 7import functools 8import contextlib 9import hashlib 10import binascii 11import base64 12import json 13try: 14 from math import gcd 15except ImportError: 16 from fractions import gcd 17 18from eccref import * 19from testcrypt import * 20from ssh import * 21 22assert sys.version_info[:2] >= (3,0), "This is Python 3 code" 23 24try: 25 base64decode = base64.decodebytes 26except AttributeError: 27 base64decode = base64.decodestring 28 29def unhex(s): 30 return binascii.unhexlify(s.replace(" ", "").replace("\n", "")) 31 32def rsa_bare(e, n): 33 rsa = rsa_new() 34 get_rsa_ssh1_pub(ssh_uint32(nbits(n)) + ssh1_mpint(e) + ssh1_mpint(n), 35 rsa, 'exponent_first') 36 return rsa 37 38def find_non_square_mod(p): 39 # Find a non-square mod p, using the Jacobi symbol 40 # calculation function from eccref.py. 41 return next(z for z in itertools.count(2) if jacobi(z, p) == -1) 42 43def fibonacci_scattered(n=10): 44 # Generate a list of Fibonacci numbers with power-of-2 indices 45 # (F_1, F_2, F_4, ...), to be used as test inputs of varying 46 # sizes. Also put F_0 = 0 into the list as a bonus. 47 yield 0 48 a, b, c = 0, 1, 1 49 while True: 50 yield b 51 n -= 1 52 if n <= 0: 53 break 54 a, b, c = (a**2+b**2, b*(a+c), b**2+c**2) 55 56def fibonacci(n=10): 57 # Generate the full Fibonacci sequence starting from F_0 = 0. 58 a, b = 0, 1 59 while True: 60 yield a 61 n -= 1 62 if n <= 0: 63 break 64 a, b = b, a+b 65 66def mp_mask(mp): 67 # Return the value that mp would represent if all its bits 68 # were set. Useful for masking a true mathematical output 69 # value (e.g. from an operation that can over/underflow, like 70 # mp_sub or mp_anything_into) to check it's right within the 71 # ability of that particular mp_int to represent. 72 return ((1 << mp_max_bits(mp))-1) 73 74def adjtuples(iterable, n): 75 # Return all the contiguous n-tuples of an iterable, including 76 # overlapping ones. E.g. if called on [0,1,2,3,4] with n=3 it 77 # would return (0,1,2), (1,2,3), (2,3,4) and then stop. 78 it = iter(iterable) 79 toret = [next(it) for _ in range(n-1)] 80 for element in it: 81 toret.append(element) 82 yield tuple(toret) 83 toret[:1] = [] 84 85def last(iterable): 86 # Return the last element of an iterable, or None if it is empty. 87 it = iter(iterable) 88 toret = None 89 for toret in it: 90 pass 91 return toret 92 93def le_integer(x, nbits): 94 assert nbits % 8 == 0 95 return bytes([0xFF & (x >> (8*n)) for n in range(nbits//8)]) 96 97@contextlib.contextmanager 98def queued_random_data(nbytes, seed): 99 hashsize = 512 // 8 100 data = b''.join( 101 hashlib.sha512("preimage:{:d}:{}".format(i, seed).encode('ascii')) 102 .digest() for i in range((nbytes + hashsize - 1) // hashsize)) 103 data = data[:nbytes] 104 random_queue(data) 105 yield None 106 random_clear() 107 108@contextlib.contextmanager 109def queued_specific_random_data(data): 110 random_queue(data) 111 yield None 112 random_clear() 113 114@contextlib.contextmanager 115def random_prng(seed): 116 random_make_prng('sha256', seed) 117 yield None 118 random_clear() 119 120def hash_str(alg, message): 121 h = ssh_hash_new(alg) 122 ssh_hash_update(h, message) 123 return ssh_hash_final(h) 124 125def hash_str_iter(alg, message_iter): 126 h = ssh_hash_new(alg) 127 for string in message_iter: 128 ssh_hash_update(h, string) 129 return ssh_hash_final(h) 130 131def mac_str(alg, key, message, cipher=None): 132 m = ssh2_mac_new(alg, cipher) 133 ssh2_mac_setkey(m, key) 134 ssh2_mac_start(m) 135 ssh2_mac_update(m, "dummy") 136 # Make sure ssh_mac_start erases previous state 137 ssh2_mac_start(m) 138 ssh2_mac_update(m, message) 139 return ssh2_mac_genresult(m) 140 141def lcm(a, b): 142 return a * b // gcd(a, b) 143 144class MyTestBase(unittest.TestCase): 145 "Intermediate class that adds useful helper methods." 146 def assertEqualBin(self, x, y): 147 # Like assertEqual, but produces more legible error reports 148 # for random-looking binary data. 149 self.assertEqual(binascii.hexlify(x), binascii.hexlify(y)) 150 151class mpint(MyTestBase): 152 def testCreation(self): 153 self.assertEqual(int(mp_new(128)), 0) 154 self.assertEqual(int(mp_from_bytes_be(b'ABCDEFGHIJKLMNOP')), 155 0x4142434445464748494a4b4c4d4e4f50) 156 self.assertEqual(int(mp_from_bytes_le(b'ABCDEFGHIJKLMNOP')), 157 0x504f4e4d4c4b4a494847464544434241) 158 self.assertEqual(int(mp_from_integer(12345)), 12345) 159 decstr = '91596559417721901505460351493238411077414937428167' 160 self.assertEqual(int(mp_from_decimal_pl(decstr)), int(decstr, 10)) 161 self.assertEqual(int(mp_from_decimal(decstr)), int(decstr, 10)) 162 self.assertEqual(int(mp_from_decimal("")), 0) 163 # For hex, test both upper and lower case digits 164 hexstr = 'ea7cb89f409ae845215822e37D32D0C63EC43E1381C2FF8094' 165 self.assertEqual(int(mp_from_hex_pl(hexstr)), int(hexstr, 16)) 166 self.assertEqual(int(mp_from_hex(hexstr)), int(hexstr, 16)) 167 self.assertEqual(int(mp_from_hex("")), 0) 168 p2 = mp_power_2(123) 169 self.assertEqual(int(p2), 1 << 123) 170 p2c = mp_copy(p2) 171 self.assertEqual(int(p2c), 1 << 123) 172 # Check mp_copy really makes a copy, not an alias (ok, that's 173 # testing the testcrypt system more than it's testing the 174 # underlying C functions) 175 mp_set_bit(p2c, 120, 1) 176 self.assertEqual(int(p2c), (1 << 123) + (1 << 120)) 177 self.assertEqual(int(p2), 1 << 123) 178 179 def testBytesAndBits(self): 180 x = mp_new(128) 181 self.assertEqual(mp_get_byte(x, 2), 0) 182 mp_set_bit(x, 2*8+3, 1) 183 self.assertEqual(mp_get_byte(x, 2), 1<<3) 184 self.assertEqual(mp_get_bit(x, 2*8+3), 1) 185 mp_set_bit(x, 2*8+3, 0) 186 self.assertEqual(mp_get_byte(x, 2), 0) 187 self.assertEqual(mp_get_bit(x, 2*8+3), 0) 188 # Currently I expect 128 to be a multiple of any 189 # BIGNUM_INT_BITS value we might be running with, so these 190 # should be exact equality 191 self.assertEqual(mp_max_bytes(x), 128/8) 192 self.assertEqual(mp_max_bits(x), 128) 193 194 nb = lambda hexstr: mp_get_nbits(mp_from_hex(hexstr)) 195 self.assertEqual(nb('00000000000000000000000000000000'), 0) 196 self.assertEqual(nb('00000000000000000000000000000001'), 1) 197 self.assertEqual(nb('00000000000000000000000000000002'), 2) 198 self.assertEqual(nb('00000000000000000000000000000003'), 2) 199 self.assertEqual(nb('00000000000000000000000000000004'), 3) 200 self.assertEqual(nb('000003ffffffffffffffffffffffffff'), 106) 201 self.assertEqual(nb('000003ffffffffff0000000000000000'), 106) 202 self.assertEqual(nb('80000000000000000000000000000000'), 128) 203 self.assertEqual(nb('ffffffffffffffffffffffffffffffff'), 128) 204 205 def testDecAndHex(self): 206 def checkHex(hexstr): 207 n = mp_from_hex(hexstr) 208 i = int(hexstr, 16) 209 self.assertEqual(mp_get_hex(n), 210 "{:x}".format(i).encode('ascii')) 211 self.assertEqual(mp_get_hex_uppercase(n), 212 "{:X}".format(i).encode('ascii')) 213 checkHex("0") 214 checkHex("f") 215 checkHex("00000000000000000000000000000000000000000000000000") 216 checkHex("d5aa1acd5a9a1f6b126ed416015390b8dc5fceee4c86afc8c2") 217 checkHex("ffffffffffffffffffffffffffffffffffffffffffffffffff") 218 219 def checkDec(hexstr): 220 n = mp_from_hex(hexstr) 221 i = int(hexstr, 16) 222 self.assertEqual(mp_get_decimal(n), 223 "{:d}".format(i).encode('ascii')) 224 checkDec("0") 225 checkDec("f") 226 checkDec("00000000000000000000000000000000000000000000000000") 227 checkDec("d5aa1acd5a9a1f6b126ed416015390b8dc5fceee4c86afc8c2") 228 checkDec("ffffffffffffffffffffffffffffffffffffffffffffffffff") 229 checkDec("f" * 512) 230 231 def testComparison(self): 232 inputs = [ 233 "0", "1", "2", "10", "314159265358979", "FFFFFFFFFFFFFFFF", 234 235 # Test over-long versions of some of the same numbers we 236 # had short forms of above 237 "0000000000000000000000000000000000000000000000000000000000000000" 238 "0000000000000000000000000000000000000000000000000000000000000000", 239 240 "0000000000000000000000000000000000000000000000000000000000000000" 241 "0000000000000000000000000000000000000000000000000000000000000001", 242 243 "0000000000000000000000000000000000000000000000000000000000000000" 244 "0000000000000000000000000000000000000000000000000000000000000002", 245 246 "0000000000000000000000000000000000000000000000000000000000000000" 247 "000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF", 248 249 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 250 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 251 ] 252 values = [(mp_from_hex(s), int(s, 16)) for s in inputs] 253 for am, ai in values: 254 for bm, bi in values: 255 self.assertEqual(mp_cmp_eq(am, bm) == 1, ai == bi) 256 self.assertEqual(mp_cmp_hs(am, bm) == 1, ai >= bi) 257 if (bi >> 64) == 0: 258 self.assertEqual(mp_eq_integer(am, bi) == 1, ai == bi) 259 self.assertEqual(mp_hs_integer(am, bi) == 1, ai >= bi) 260 261 # mp_{min,max}{,_into} is a reasonable thing to test 262 # here as well 263 self.assertEqual(int(mp_min(am, bm)), min(ai, bi)) 264 self.assertEqual(int(mp_max(am, bm)), max(ai, bi)) 265 am_small = mp_copy(am if ai<bi else bm) 266 mp_min_into(am_small, am, bm) 267 self.assertEqual(int(am_small), min(ai, bi)) 268 am_big = mp_copy(am if ai>bi else bm) 269 mp_max_into(am_big, am, bm) 270 self.assertEqual(int(am_big), max(ai, bi)) 271 272 # Test mp_{eq,hs}_integer in the case where the integer is as 273 # large as possible and the bignum contains very few words. In 274 # modes where BIGNUM_INT_BITS < 64, this used to go wrong. 275 mp10 = mp_new(4) 276 mp_copy_integer_into(mp10, 10) 277 highbit = 1 << 63 278 self.assertEqual(mp_hs_integer(mp10, highbit | 9), 0) 279 self.assertEqual(mp_hs_integer(mp10, highbit | 10), 0) 280 self.assertEqual(mp_hs_integer(mp10, highbit | 11), 0) 281 self.assertEqual(mp_eq_integer(mp10, highbit | 9), 0) 282 self.assertEqual(mp_eq_integer(mp10, highbit | 10), 0) 283 self.assertEqual(mp_eq_integer(mp10, highbit | 11), 0) 284 285 def testConditionals(self): 286 testnumbers = [(mp_copy(n),n) for n in fibonacci_scattered()] 287 for am, ai in testnumbers: 288 for bm, bi in testnumbers: 289 cm = mp_copy(am) 290 mp_select_into(cm, am, bm, 0) 291 self.assertEqual(int(cm), ai & mp_mask(am)) 292 mp_select_into(cm, am, bm, 1) 293 self.assertEqual(int(cm), bi & mp_mask(am)) 294 295 mp_cond_add_into(cm, am, bm, 0) 296 self.assertEqual(int(cm), ai & mp_mask(am)) 297 mp_cond_add_into(cm, am, bm, 1) 298 self.assertEqual(int(cm), (ai+bi) & mp_mask(am)) 299 300 mp_cond_sub_into(cm, am, bm, 0) 301 self.assertEqual(int(cm), ai & mp_mask(am)) 302 mp_cond_sub_into(cm, am, bm, 1) 303 self.assertEqual(int(cm), (ai-bi) & mp_mask(am)) 304 305 maxbits = max(mp_max_bits(am), mp_max_bits(bm)) 306 cm = mp_new(maxbits) 307 dm = mp_new(maxbits) 308 mp_copy_into(cm, am) 309 mp_copy_into(dm, bm) 310 311 self.assertEqual(int(cm), ai) 312 self.assertEqual(int(dm), bi) 313 mp_cond_swap(cm, dm, 0) 314 self.assertEqual(int(cm), ai) 315 self.assertEqual(int(dm), bi) 316 mp_cond_swap(cm, dm, 1) 317 self.assertEqual(int(cm), bi) 318 self.assertEqual(int(dm), ai) 319 320 if bi != 0: 321 mp_cond_clear(cm, 0) 322 self.assertEqual(int(cm), bi) 323 mp_cond_clear(cm, 1) 324 self.assertEqual(int(cm), 0) 325 326 def testBasicArithmetic(self): 327 testnumbers = list(fibonacci_scattered(5)) 328 testnumbers.extend([1 << (1 << i) for i in range(3,10)]) 329 testnumbers.extend([(1 << (1 << i)) - 1 for i in range(3,10)]) 330 331 testnumbers = [(mp_copy(n),n) for n in testnumbers] 332 333 for am, ai in testnumbers: 334 for bm, bi in testnumbers: 335 self.assertEqual(int(mp_add(am, bm)), ai + bi) 336 self.assertEqual(int(mp_mul(am, bm)), ai * bi) 337 # Cope with underflow in subtraction 338 diff = mp_sub(am, bm) 339 self.assertEqual(int(diff), (ai - bi) & mp_mask(diff)) 340 341 for bits in range(64, 512, 64): 342 cm = mp_new(bits) 343 mp_add_into(cm, am, bm) 344 self.assertEqual(int(cm), (ai + bi) & mp_mask(cm)) 345 mp_mul_into(cm, am, bm) 346 self.assertEqual(int(cm), (ai * bi) & mp_mask(cm)) 347 mp_sub_into(cm, am, bm) 348 self.assertEqual(int(cm), (ai - bi) & mp_mask(cm)) 349 350 # A test cherry-picked from the old bignum test script, 351 # involving two numbers whose product has a single 1 bit miles 352 # in the air and then all 0s until a bunch of cruft at the 353 # bottom, the aim being to test that carry propagation works 354 # all the way up. 355 ai, bi = 0xb4ff6ed2c633847562087ed9354c5c17be212ac83b59c10c316250f50b7889e5b058bf6bfafd12825225ba225ede0cba583ffbd0882de88c9e62677385a6dbdedaf81959a273eb7909ebde21ae5d12e2a584501a6756fe50ccb93b93f0d6ee721b6052a0d88431e62f410d608532868cdf3a6de26886559e94cc2677eea9bd797918b70e2717e95b45918bd1f86530cb9989e68b632c496becff848aa1956cd57ed46676a65ce6dd9783f230c8796909eef5583fcfe4acbf9c8b4ea33a08ec3fd417cf7175f434025d032567a00fc329aee154ca20f799b961fbab8f841cb7351f561a44aea45746ceaf56874dad99b63a7d7af2769d2f185e2d1c656cc6630b5aba98399fa57, 0xb50a77c03ac195225021dc18d930a352f27c0404742f961ca828c972737bad3ada74b1144657ab1d15fe1b8aefde8784ad61783f3c8d4584aa5f22a4eeca619f90563ae351b5da46770df182cf348d8e23b25fda07670c6609118e916a57ce4043608752c91515708327e36f5bb5ebd92cd4cfb39424167a679870202b23593aa524bac541a3ad322c38102a01e9659b06a4335c78d50739a51027954ac2bf03e500f975c2fa4d0ab5dd84cc9334f219d2ae933946583e384ed5dbf6498f214480ca66987b867df0f69d92e4e14071e4b8545212dd5e29ff0248ed751e168d78934da7930bcbe10e9a212128a68de5d749c61f5e424cf8cf6aa329674de0cf49c6f9b4c8b8cc3 356 am = mp_copy(ai) 357 bm = mp_copy(bi) 358 self.assertEqual(int(mp_mul(am, bm)), ai * bi) 359 360 # A regression test for a bug that came up during development 361 # of mpint.c, relating to an intermediate value overflowing 362 # its container. 363 ai, bi = (2**8512 * 2 // 3), (2**4224 * 11 // 15) 364 am = mp_copy(ai) 365 bm = mp_copy(bi) 366 self.assertEqual(int(mp_mul(am, bm)), ai * bi) 367 368 def testAddInteger(self): 369 initial = mp_copy(4444444444444444444444444) 370 371 x = mp_new(mp_max_bits(initial) + 64) 372 373 # mp_{add,sub,copy}_integer_into should be able to cope with 374 # any uintmax_t. Test a number that requires more than 32 bits. 375 mp_add_integer_into(x, initial, 123123123123123) 376 self.assertEqual(int(x), 4444444444567567567567567) 377 mp_sub_integer_into(x, initial, 123123123123123) 378 self.assertEqual(int(x), 4444444444321321321321321) 379 mp_copy_integer_into(x, 123123123123123) 380 self.assertEqual(int(x), 123123123123123) 381 382 # mp_mul_integer_into only takes a uint16_t integer input 383 mp_mul_integer_into(x, initial, 10001) 384 self.assertEqual(int(x), 44448888888888888888888884444) 385 386 def testDivision(self): 387 divisors = [1, 2, 3, 2**16+1, 2**32-1, 2**32+1, 2**128-159, 388 141421356237309504880168872420969807856967187537694807] 389 quotients = [0, 1, 2, 2**64-1, 2**64, 2**64+1, 17320508075688772935] 390 for d in divisors: 391 for q in quotients: 392 remainders = {0, 1, d-1, 2*d//3} 393 for r in sorted(remainders): 394 if r >= d: 395 continue # silly cases with tiny divisors 396 n = q*d + r 397 mq = mp_new(max(nbits(q), 1)) 398 mr = mp_new(max(nbits(r), 1)) 399 mp_divmod_into(n, d, mq, mr) 400 self.assertEqual(int(mq), q) 401 self.assertEqual(int(mr), r) 402 self.assertEqual(int(mp_div(n, d)), q) 403 self.assertEqual(int(mp_mod(n, d)), r) 404 405 # Make sure divmod_into can handle not getting one 406 # of its output pointers (or even both). 407 mp_clear(mq) 408 mp_divmod_into(n, d, mq, None) 409 self.assertEqual(int(mq), q) 410 mp_clear(mr) 411 mp_divmod_into(n, d, None, mr) 412 self.assertEqual(int(mr), r) 413 mp_divmod_into(n, d, None, None) 414 # No tests we can do after that last one - we just 415 # insist that it isn't allowed to have crashed! 416 417 def testNthRoot(self): 418 roots = [1, 13, 1234567654321, 419 57721566490153286060651209008240243104215933593992] 420 tests = [] 421 tests.append((0, 2, 0, 0)) 422 tests.append((0, 3, 0, 0)) 423 for r in roots: 424 for n in 2, 3, 5: 425 tests.append((r**n, n, r, 0)) 426 tests.append((r**n+1, n, r, 1)) 427 tests.append((r**n-1, n, r-1, r**n - (r-1)**n - 1)) 428 for x, n, eroot, eremainder in tests: 429 with self.subTest(x=x): 430 mx = mp_copy(x) 431 remainder = mp_copy(mx) 432 root = mp_nthroot(x, n, remainder) 433 self.assertEqual(int(root), eroot) 434 self.assertEqual(int(remainder), eremainder) 435 self.assertEqual(int(mp_nthroot(2*10**100, 2, None)), 436 141421356237309504880168872420969807856967187537694) 437 self.assertEqual(int(mp_nthroot(3*10**150, 3, None)), 438 144224957030740838232163831078010958839186925349935) 439 440 def testBitwise(self): 441 p = 0x3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e 442 e = 0x2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190 443 x = mp_new(nbits(p)) 444 445 mp_and_into(x, p, e) 446 self.assertEqual(int(x), p & e) 447 448 mp_or_into(x, p, e) 449 self.assertEqual(int(x), p | e) 450 451 mp_xor_into(x, p, e) 452 self.assertEqual(int(x), p ^ e) 453 454 mp_bic_into(x, p, e) 455 self.assertEqual(int(x), p & ~e) 456 457 def testInversion(self): 458 # Test mp_invert_mod_2to. 459 testnumbers = [(mp_copy(n),n) for n in fibonacci_scattered() 460 if n & 1] 461 for power2 in [1, 2, 3, 5, 13, 32, 64, 127, 128, 129]: 462 for am, ai in testnumbers: 463 bm = mp_invert_mod_2to(am, power2) 464 bi = int(bm) 465 self.assertEqual(((ai * bi) & ((1 << power2) - 1)), 1) 466 467 # mp_reduce_mod_2to is a much simpler function, but 468 # this is as good a place as any to test it. 469 rm = mp_copy(am) 470 mp_reduce_mod_2to(rm, power2) 471 self.assertEqual(int(rm), ai & ((1 << power2) - 1)) 472 473 # Test mp_invert proper. 474 moduli = [2, 3, 2**16+1, 2**32-1, 2**32+1, 2**128-159, 475 141421356237309504880168872420969807856967187537694807, 476 2**128-1] 477 for m in moduli: 478 # Prepare a MontyContext for the monty_invert test below 479 # (unless m is even, in which case we can't) 480 mc = monty_new(m) if m & 1 else None 481 482 to_invert = {1, 2, 3, 7, 19, m-1, 5*m//17, (m-1)//2, (m+1)//2} 483 for x in sorted(to_invert): 484 if gcd(x, m) != 1: 485 continue # filter out non-invertible cases 486 inv = int(mp_invert(x, m)) 487 assert x * inv % m == 1 488 489 # Test monty_invert too, while we're here 490 if mc is not None: 491 self.assertEqual( 492 int(monty_invert(mc, monty_import(mc, x))), 493 int(monty_import(mc, inv))) 494 495 def testGCD(self): 496 powerpairs = [(0,0), (1,0), (1,1), (2,1), (2,2), (75,3), (17,23)] 497 for a2, b2 in powerpairs: 498 for a3, b3 in powerpairs: 499 for a5, b5 in powerpairs: 500 a = 2**a2 * 3**a3 * 5**a5 * 17 * 19 * 23 501 b = 2**b2 * 3**b3 * 5**b5 * 65423 502 d = 2**min(a2, b2) * 3**min(a3, b3) * 5**min(a5, b5) 503 504 ma = mp_copy(a) 505 mb = mp_copy(b) 506 507 self.assertEqual(int(mp_gcd(ma, mb)), d) 508 509 md = mp_new(nbits(d)) 510 mA = mp_new(nbits(b)) 511 mB = mp_new(nbits(a)) 512 mp_gcd_into(ma, mb, md, mA, mB) 513 self.assertEqual(int(md), d) 514 A = int(mA) 515 B = int(mB) 516 self.assertEqual(a*A - b*B, d) 517 self.assertTrue(0 <= A < b//d) 518 self.assertTrue(0 <= B < a//d) 519 520 self.assertEqual(mp_coprime(ma, mb), 1 if d==1 else 0) 521 522 # Make sure gcd_into can handle not getting some 523 # of its output pointers. 524 mp_clear(md) 525 mp_gcd_into(ma, mb, md, None, None) 526 self.assertEqual(int(md), d) 527 mp_clear(mA) 528 mp_gcd_into(ma, mb, None, mA, None) 529 self.assertEqual(int(mA), A) 530 mp_clear(mB) 531 mp_gcd_into(ma, mb, None, None, mB) 532 self.assertEqual(int(mB), B) 533 mp_gcd_into(ma, mb, None, None, None) 534 # No tests we can do after that last one - we just 535 # insist that it isn't allowed to have crashed! 536 537 def testMonty(self): 538 moduli = [5, 19, 2**16+1, 2**31-1, 2**128-159, 2**255-19, 539 293828847201107461142630006802421204703, 540 113064788724832491560079164581712332614996441637880086878209969852674997069759] 541 542 for m in moduli: 543 mc = monty_new(m) 544 545 # Import some numbers 546 inputs = [(monty_import(mc, n), n) 547 for n in sorted({0, 1, 2, 3, 2*m//3, m-1})] 548 549 # Check modulus and identity 550 self.assertEqual(int(monty_modulus(mc)), m) 551 self.assertEqual(int(monty_identity(mc)), int(inputs[1][0])) 552 553 # Check that all those numbers export OK 554 for mn, n in inputs: 555 self.assertEqual(int(monty_export(mc, mn)), n) 556 557 for ma, a in inputs: 558 for mb, b in inputs: 559 xprod = int(monty_export(mc, monty_mul(mc, ma, mb))) 560 self.assertEqual(xprod, a*b % m) 561 562 xsum = int(monty_export(mc, monty_add(mc, ma, mb))) 563 self.assertEqual(xsum, (a+b) % m) 564 565 xdiff = int(monty_export(mc, monty_sub(mc, ma, mb))) 566 self.assertEqual(xdiff, (a-b) % m) 567 568 # Test the ordinary mp_mod{add,sub,mul} at the 569 # same time, even though those don't do any 570 # montying at all 571 572 xprod = int(mp_modmul(a, b, m)) 573 self.assertEqual(xprod, a*b % m) 574 575 xsum = int(mp_modadd(a, b, m)) 576 self.assertEqual(xsum, (a+b) % m) 577 578 xdiff = int(mp_modsub(a, b, m)) 579 self.assertEqual(xdiff, (a-b) % m) 580 581 for ma, a in inputs: 582 # Compute a^0, a^1, a^1, a^2, a^3, a^5, ... 583 indices = list(fibonacci()) 584 powers = [int(monty_export(mc, monty_pow(mc, ma, power))) 585 for power in indices] 586 # Check the first two make sense 587 self.assertEqual(powers[0], 1) 588 self.assertEqual(powers[1], a) 589 # Check the others using the Fibonacci identity: 590 # F_n + F_{n+1} = F_{n+2}, so a^{F_n} a^{F_{n+1}} = a^{F_{n+2}} 591 for p0, p1, p2 in adjtuples(powers, 3): 592 self.assertEqual(p2, p0 * p1 % m) 593 594 # Test the ordinary mp_modpow here as well, while 595 # we've got the machinery available 596 for index, power in zip(indices, powers): 597 self.assertEqual(int(mp_modpow(a, index, m)), power) 598 599 # A regression test for a bug I encountered during initial 600 # development of mpint.c, in which an incomplete reduction 601 # happened somewhere in an intermediate value. 602 b, e, m = 0x2B5B93812F253FF91F56B3B4DAD01CA2884B6A80719B0DA4E2159A230C6009EDA97C5C8FD4636B324F9594706EE3AD444831571BA5E17B1B2DFA92DEA8B7E, 0x25, 0xC8FCFD0FD7371F4FE8D0150EFC124E220581569587CCD8E50423FA8D41E0B2A0127E100E92501E5EE3228D12EA422A568C17E0AD2E5C5FCC2AE9159D2B7FB8CB 603 assert(int(mp_modpow(b, e, m)) == pow(b, e, m)) 604 605 # Make sure mp_modpow can handle a base larger than the 606 # modulus, by pre-reducing it 607 assert(int(mp_modpow(1<<877, 907, 999979)) == pow(2, 877*907, 999979)) 608 609 def testModsqrt(self): 610 moduli = [ 611 5, 19, 2**16+1, 2**31-1, 2**128-159, 2**255-19, 612 293828847201107461142630006802421204703, 613 113064788724832491560079164581712332614996441637880086878209969852674997069759, 614 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6FFFFFFFF00000001] 615 for p in moduli: 616 # Count the factors of 2 in the group. (That is, we want 617 # p-1 to be an odd multiple of 2^{factors_of_2}.) 618 factors_of_2 = nbits((p-1) & (1-p)) - 1 619 assert (p & ((2 << factors_of_2)-1)) == ((1 << factors_of_2)+1) 620 621 z = find_non_square_mod(p) 622 623 sc = modsqrt_new(p, z) 624 625 def ptest(x): 626 root, success = mp_modsqrt(sc, x) 627 r = int(root) 628 self.assertTrue(success) 629 self.assertEqual((r * r - x) % p, 0) 630 631 def ntest(x): 632 root, success = mp_modsqrt(sc, x) 633 self.assertFalse(success) 634 635 # Make up some more or less random values mod p to square 636 v1 = pow(3, nbits(p), p) 637 v2 = pow(5, v1, p) 638 test_roots = [0, 1, 2, 3, 4, 3*p//4, v1, v2, v1+1, 12873*v1, v1*v2] 639 known_squares = {r*r % p for r in test_roots} 640 for s in known_squares: 641 ptest(s) 642 if s != 0: 643 ntest(z*s % p) 644 645 # Make sure we've tested a value that is in each of the 646 # subgroups of order (p-1)/2^k but not in the next one 647 # (with the exception of k=0, which just means 'have we 648 # tested a non-square?', which we have in the above loop). 649 # 650 # We do this by starting with a known non-square; then 651 # squaring it (factors_of_2) times will return values 652 # nested deeper and deeper in those subgroups. 653 vbase = z 654 for k in range(factors_of_2): 655 # Adjust vbase by an arbitrary odd power of 656 # z, so that it won't look too much like the previous 657 # value. 658 vbase = vbase * pow(z, (vbase + v1 + v2) | 1, p) % p 659 660 # Move vbase into the next smaller group by squaring 661 # it. 662 vbase = pow(vbase, 2, p) 663 664 ptest(vbase) 665 666 def testShifts(self): 667 x = ((1<<900) // 9949) | 1 668 for i in range(2049): 669 mp = mp_copy(x) 670 671 mp_lshift_fixed_into(mp, mp, i) 672 self.assertEqual(int(mp), (x << i) & mp_mask(mp)) 673 674 mp_copy_into(mp, x) 675 mp_lshift_safe_into(mp, mp, i) 676 self.assertEqual(int(mp), (x << i) & mp_mask(mp)) 677 678 mp_copy_into(mp, x) 679 mp_rshift_fixed_into(mp, mp, i) 680 self.assertEqual(int(mp), x >> i) 681 682 mp_copy_into(mp, x) 683 mp_rshift_safe_into(mp, mp, i) 684 self.assertEqual(int(mp), x >> i) 685 686 self.assertEqual(int(mp_rshift_fixed(x, i)), x >> i) 687 688 self.assertEqual(int(mp_rshift_safe(x, i)), x >> i) 689 690 def testRandom(self): 691 # Test random_bits to ensure it correctly masks the return 692 # value, and uses exactly as many random bytes as we expect it 693 # to. 694 for bits in range(512): 695 bytes_needed = (bits + 7) // 8 696 with queued_random_data(bytes_needed, "random_bits test"): 697 mp = mp_random_bits(bits) 698 self.assertTrue(int(mp) < (1 << bits)) 699 self.assertEqual(random_queue_len(), 0) 700 701 # Test mp_random_in_range to ensure it returns things in the 702 # right range. 703 for rangesize in [2, 3, 19, 35]: 704 for lo in [0, 1, 0x10001, 1<<512]: 705 hi = lo + rangesize 706 bytes_needed = mp_max_bytes(hi) + 16 707 for trial in range(rangesize*3): 708 with queued_random_data( 709 bytes_needed, 710 "random_in_range {:d}".format(trial)): 711 v = int(mp_random_in_range(lo, hi)) 712 self.assertTrue(lo <= v < hi) 713 714class ecc(MyTestBase): 715 def testWeierstrassSimple(self): 716 # Simple tests using a Weierstrass curve I made up myself, 717 # which (unlike the ones used for serious crypto) is small 718 # enough that you can fit all the coordinates for a curve on 719 # to your retina in one go. 720 721 p = 3141592661 722 a, b = -3 % p, 12345 723 rc = WeierstrassCurve(p, a, b) 724 wc = ecc_weierstrass_curve(p, a, b, None) 725 726 def check_point(wp, rp): 727 self.assertTrue(ecc_weierstrass_point_valid(wp)) 728 is_id = ecc_weierstrass_is_identity(wp) 729 x, y = ecc_weierstrass_get_affine(wp) 730 if rp.infinite: 731 self.assertEqual(is_id, 1) 732 else: 733 self.assertEqual(is_id, 0) 734 self.assertEqual(int(x), int(rp.x)) 735 self.assertEqual(int(y), int(rp.y)) 736 737 def make_point(x, y): 738 wp = ecc_weierstrass_point_new(wc, x, y) 739 rp = rc.point(x, y) 740 check_point(wp, rp) 741 return wp, rp 742 743 # Some sample points, including the identity and also a pair 744 # of mutual inverses. 745 wI, rI = ecc_weierstrass_point_new_identity(wc), rc.point() 746 wP, rP = make_point(102, 387427089) 747 wQ, rQ = make_point(1000, 546126574) 748 wmP, rmP = make_point(102, p - 387427089) 749 750 # Check the simple arithmetic functions. 751 check_point(ecc_weierstrass_add(wP, wQ), rP + rQ) 752 check_point(ecc_weierstrass_add(wQ, wP), rP + rQ) 753 check_point(ecc_weierstrass_double(wP), rP + rP) 754 check_point(ecc_weierstrass_double(wQ), rQ + rQ) 755 756 # Check all the special cases with add_general: 757 # Adding two finite unequal non-mutually-inverse points 758 check_point(ecc_weierstrass_add_general(wP, wQ), rP + rQ) 759 # Doubling a finite point 760 check_point(ecc_weierstrass_add_general(wP, wP), rP + rP) 761 check_point(ecc_weierstrass_add_general(wQ, wQ), rQ + rQ) 762 # Adding the identity to a point (both ways round) 763 check_point(ecc_weierstrass_add_general(wI, wP), rP) 764 check_point(ecc_weierstrass_add_general(wI, wQ), rQ) 765 check_point(ecc_weierstrass_add_general(wP, wI), rP) 766 check_point(ecc_weierstrass_add_general(wQ, wI), rQ) 767 # Doubling the identity 768 check_point(ecc_weierstrass_add_general(wI, wI), rI) 769 # Adding a point to its own inverse, giving the identity. 770 check_point(ecc_weierstrass_add_general(wmP, wP), rI) 771 check_point(ecc_weierstrass_add_general(wP, wmP), rI) 772 773 # Verify that point_valid fails if we pass it nonsense. 774 bogus = ecc_weierstrass_point_new(wc, int(rP.x), int(rP.y * 3)) 775 self.assertFalse(ecc_weierstrass_point_valid(bogus)) 776 777 # Re-instantiate the curve with the ability to take square 778 # roots, and check that we can reconstruct P and Q from their 779 # x coordinate and y parity only. 780 wc = ecc_weierstrass_curve(p, a, b, find_non_square_mod(p)) 781 782 x, yp = int(rP.x), (int(rP.y) & 1) 783 check_point(ecc_weierstrass_point_new_from_x(wc, x, yp), rP) 784 check_point(ecc_weierstrass_point_new_from_x(wc, x, yp ^ 1), rmP) 785 x, yp = int(rQ.x), (int(rQ.y) & 1) 786 check_point(ecc_weierstrass_point_new_from_x(wc, x, yp), rQ) 787 788 def testMontgomerySimple(self): 789 p, a, b = 3141592661, 0xabc, 0xde 790 791 rc = MontgomeryCurve(p, a, b) 792 mc = ecc_montgomery_curve(p, a, b) 793 794 rP = rc.cpoint(0x1001) 795 rQ = rc.cpoint(0x20001) 796 rdiff = rP - rQ 797 rsum = rP + rQ 798 799 def make_mpoint(rp): 800 return ecc_montgomery_point_new(mc, int(rp.x)) 801 802 mP = make_mpoint(rP) 803 mQ = make_mpoint(rQ) 804 mdiff = make_mpoint(rdiff) 805 msum = make_mpoint(rsum) 806 807 def check_point(mp, rp): 808 x = ecc_montgomery_get_affine(mp) 809 self.assertEqual(int(x), int(rp.x)) 810 811 check_point(ecc_montgomery_diff_add(mP, mQ, mdiff), rsum) 812 check_point(ecc_montgomery_diff_add(mQ, mP, mdiff), rsum) 813 check_point(ecc_montgomery_diff_add(mP, mQ, msum), rdiff) 814 check_point(ecc_montgomery_diff_add(mQ, mP, msum), rdiff) 815 check_point(ecc_montgomery_double(mP), rP + rP) 816 check_point(ecc_montgomery_double(mQ), rQ + rQ) 817 818 zero = ecc_montgomery_point_new(mc, 0) 819 self.assertEqual(ecc_montgomery_is_identity(zero), False) 820 identity = ecc_montgomery_double(zero) 821 ecc_montgomery_get_affine(identity) 822 self.assertEqual(ecc_montgomery_is_identity(identity), True) 823 824 def testEdwardsSimple(self): 825 p, d, a = 3141592661, 2688750488, 367934288 826 827 rc = TwistedEdwardsCurve(p, d, a) 828 ec = ecc_edwards_curve(p, d, a, None) 829 830 def check_point(ep, rp): 831 x, y = ecc_edwards_get_affine(ep) 832 self.assertEqual(int(x), int(rp.x)) 833 self.assertEqual(int(y), int(rp.y)) 834 835 def make_point(x, y): 836 ep = ecc_edwards_point_new(ec, x, y) 837 rp = rc.point(x, y) 838 check_point(ep, rp) 839 return ep, rp 840 841 # Some sample points, including the identity and also a pair 842 # of mutual inverses. 843 eI, rI = make_point(0, 1) 844 eP, rP = make_point(196270812, 1576162644) 845 eQ, rQ = make_point(1777630975, 2717453445) 846 emP, rmP = make_point(p - 196270812, 1576162644) 847 848 # Check that the ordinary add function handles all the special 849 # cases. 850 851 # Adding two finite unequal non-mutually-inverse points 852 check_point(ecc_edwards_add(eP, eQ), rP + rQ) 853 check_point(ecc_edwards_add(eQ, eP), rP + rQ) 854 # Doubling a finite point 855 check_point(ecc_edwards_add(eP, eP), rP + rP) 856 check_point(ecc_edwards_add(eQ, eQ), rQ + rQ) 857 # Adding the identity to a point (both ways round) 858 check_point(ecc_edwards_add(eI, eP), rP) 859 check_point(ecc_edwards_add(eI, eQ), rQ) 860 check_point(ecc_edwards_add(eP, eI), rP) 861 check_point(ecc_edwards_add(eQ, eI), rQ) 862 # Doubling the identity 863 check_point(ecc_edwards_add(eI, eI), rI) 864 # Adding a point to its own inverse, giving the identity. 865 check_point(ecc_edwards_add(emP, eP), rI) 866 check_point(ecc_edwards_add(eP, emP), rI) 867 868 # Re-instantiate the curve with the ability to take square 869 # roots, and check that we can reconstruct P and Q from their 870 # y coordinate and x parity only. 871 ec = ecc_edwards_curve(p, d, a, find_non_square_mod(p)) 872 873 y, xp = int(rP.y), (int(rP.x) & 1) 874 check_point(ecc_edwards_point_new_from_y(ec, y, xp), rP) 875 check_point(ecc_edwards_point_new_from_y(ec, y, xp ^ 1), rmP) 876 y, xp = int(rQ.y), (int(rQ.x) & 1) 877 check_point(ecc_edwards_point_new_from_y(ec, y, xp), rQ) 878 879 # For testing point multiplication, let's switch to the full-sized 880 # standard curves, because I want to have tested those a bit too. 881 882 def testWeierstrassMultiply(self): 883 wc = ecc_weierstrass_curve(p256.p, int(p256.a), int(p256.b), None) 884 wG = ecc_weierstrass_point_new(wc, int(p256.G.x), int(p256.G.y)) 885 self.assertTrue(ecc_weierstrass_point_valid(wG)) 886 887 ints = set(i % p256.p for i in fibonacci_scattered(10)) 888 ints.remove(0) # the zero multiple isn't expected to work 889 for i in sorted(ints): 890 wGi = ecc_weierstrass_multiply(wG, i) 891 x, y = ecc_weierstrass_get_affine(wGi) 892 rGi = p256.G * i 893 self.assertEqual(int(x), int(rGi.x)) 894 self.assertEqual(int(y), int(rGi.y)) 895 896 def testMontgomeryMultiply(self): 897 mc = ecc_montgomery_curve( 898 curve25519.p, int(curve25519.a), int(curve25519.b)) 899 mG = ecc_montgomery_point_new(mc, int(curve25519.G.x)) 900 901 ints = set(i % p256.p for i in fibonacci_scattered(10)) 902 ints.remove(0) # the zero multiple isn't expected to work 903 for i in sorted(ints): 904 mGi = ecc_montgomery_multiply(mG, i) 905 x = ecc_montgomery_get_affine(mGi) 906 rGi = curve25519.G * i 907 self.assertEqual(int(x), int(rGi.x)) 908 909 def testEdwardsMultiply(self): 910 ec = ecc_edwards_curve(ed25519.p, int(ed25519.d), int(ed25519.a), None) 911 eG = ecc_edwards_point_new(ec, int(ed25519.G.x), int(ed25519.G.y)) 912 913 ints = set(i % ed25519.p for i in fibonacci_scattered(10)) 914 ints.remove(0) # the zero multiple isn't expected to work 915 for i in sorted(ints): 916 eGi = ecc_edwards_multiply(eG, i) 917 x, y = ecc_edwards_get_affine(eGi) 918 rGi = ed25519.G * i 919 self.assertEqual(int(x), int(rGi.x)) 920 self.assertEqual(int(y), int(rGi.y)) 921 922class keygen(MyTestBase): 923 def testPrimeCandidateSource(self): 924 def inspect(pcs): 925 # Returns (pcs->limit, pcs->factor, pcs->addend) as Python integers 926 return tuple(map(int, pcs_inspect(pcs))) 927 928 # Test accumulating modular congruence requirements, by 929 # inspecting the internal values computed during 930 # require_residue. We ensure that the addend satisfies all our 931 # congruences and the factor is the lcm of all the moduli 932 # (hence, the arithmetic progression defined by those 933 # parameters is precisely the set of integers satisfying the 934 # requirements); we also ensure that the limiting values 935 # (addend itself at the low end, and addend + (limit-1) * 936 # factor at the high end) are the maximal subsequence of that 937 # progression that are within the originally specified range. 938 939 def check(pcs, lo, hi, mod_res_pairs): 940 limit, factor, addend = inspect(pcs) 941 942 for mod, res in mod_res_pairs: 943 self.assertEqual(addend % mod, res % mod) 944 945 self.assertEqual(factor, functools.reduce( 946 lcm, [mod for mod, res in mod_res_pairs])) 947 948 self.assertFalse(lo <= addend + (-1) * factor < hi) 949 self.assertTrue (lo <= addend < hi) 950 self.assertTrue (lo <= addend + (limit-1) * factor < hi) 951 self.assertFalse(lo <= addend + limit * factor < hi) 952 953 pcs = pcs_new(64) 954 check(pcs, 2**63, 2**64, [(2, 1)]) 955 pcs_require_residue(pcs, 3, 2) 956 check(pcs, 2**63, 2**64, [(2, 1), (3, 2)]) 957 pcs_require_residue_1(pcs, 7) 958 check(pcs, 2**63, 2**64, [(2, 1), (3, 2), (7, 1)]) 959 pcs_require_residue(pcs, 16, 7) 960 check(pcs, 2**63, 2**64, [(2, 1), (3, 2), (7, 1), (16, 7)]) 961 pcs_require_residue(pcs, 49, 8) 962 check(pcs, 2**63, 2**64, [(2, 1), (3, 2), (7, 1), (16, 7), (49, 8)]) 963 964 # Now test-generate some actual values, and ensure they 965 # satisfy all the congruences, and also avoid one residue mod 966 # 5 that we told them to. Also, give a nontrivial range. 967 pcs = pcs_new_with_firstbits(64, 0xAB, 8) 968 pcs_require_residue(pcs, 0x100, 0xCD) 969 pcs_require_residue_1(pcs, 65537) 970 pcs_avoid_residue_small(pcs, 5, 3) 971 pcs_ready(pcs) 972 with random_prng("test seed"): 973 for i in range(100): 974 n = int(pcs_generate(pcs)) 975 self.assertTrue((0xAB<<56) < n < (0xAC<<56)) 976 self.assertEqual(n % 0x100, 0xCD) 977 self.assertEqual(n % 65537, 1) 978 self.assertNotEqual(n % 5, 3) 979 980 # I'm not actually testing here that the outputs of 981 # pcs_generate are non-multiples of _all_ primes up to 982 # 2^16. But checking this many for 100 turns is enough 983 # to be pretty sure. (If you take the product of 984 # (1-1/p) over all p in the list below, you find that 985 # a given random number has about a 13% chance of 986 # avoiding being a multiple of any of them. So 100 987 # trials without a mistake gives you 0.13^100 < 10^-88 988 # as the probability of it happening by chance. More 989 # likely the code is actually working :-) 990 991 for p in [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61]: 992 self.assertNotEqual(n % p, 0) 993 994 def testPocklePositive(self): 995 def add_small(po, *ps): 996 for p in ps: 997 self.assertEqual(pockle_add_small_prime(po, p), 'POCKLE_OK') 998 def add(po, *args): 999 self.assertEqual(pockle_add_prime(po, *args), 'POCKLE_OK') 1000 1001 # Transcription of the proof that 2^130-5 is prime from 1002 # Theorem 3.1 from http://cr.yp.to/mac/poly1305-20050329.pdf 1003 po = pockle_new() 1004 p1 = (2**130 - 6) // 1517314646 1005 p2 = (p1 - 1) // 222890620702 1006 add_small(po, 37003, 221101) 1007 add(po, p2, [37003, 221101], 2) 1008 add(po, p1, [p2], 2) 1009 add(po, 2**130 - 5, [p1], 2) 1010 1011 # My own proof that 2^255-19 is prime 1012 po = pockle_new() 1013 p1 = 8574133 1014 p2 = 1919519569386763 1015 p3 = 75445702479781427272750846543864801 1016 p4 = (2**255 - 20) // (65147*12) 1017 p = 2**255 - 19 1018 add_small(po, p1) 1019 add(po, p2, [p1], 2) 1020 add(po, p3, [p2], 2) 1021 add(po, p4, [p3], 2) 1022 add(po, p, [p4], 2) 1023 1024 # And the prime used in Ed448, while I'm here 1025 po = pockle_new() 1026 p1 = 379979 1027 p2 = 1764234391 1028 p3 = 97859369123353 1029 p4 = 34741861125639557 1030 p5 = 36131535570665139281 1031 p6 = 167773885276849215533569 1032 p7 = 596242599987116128415063 1033 p = 2**448 - 2**224 - 1 1034 add_small(po, p1, p2) 1035 add(po, p3, [p1], 2) 1036 add(po, p4, [p2], 2) 1037 add(po, p5, [p4], 2) 1038 add(po, p6, [p3], 3) 1039 add(po, p7, [p5], 3) 1040 add(po, p, [p6, p7], 2) 1041 1042 p = 4095744004479977 1043 factors = [2, 79999] # just enough factors to exceed cbrt(p) 1044 po = pockle_new() 1045 for q in factors: 1046 add_small(po, q) 1047 add(po, p, factors, 3) 1048 1049 # The order of the generator in Ed25519 1050 po = pockle_new() 1051 p1a, p1b = 132667, 137849 1052 p2 = 3044861653679985063343 1053 p3 = 198211423230930754013084525763697 1054 p = 2**252 + 0x14def9dea2f79cd65812631a5cf5d3ed 1055 add_small(po, p1a, p1b) 1056 add(po, p2, [p1a, p1b], 2) 1057 add(po, p3, [p2], 2) 1058 add(po, p, [p3], 2) 1059 1060 # And the one in Ed448 1061 po = pockle_new() 1062 p1 = 766223 1063 p2 = 3009341 1064 p3 = 7156907 1065 p4 = 671065561 1066 p5 = 342682509629 1067 p6 = 6730519843040614479184435237013 1068 p = 2**446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d 1069 add_small(po, p1, p2, p3, p4) 1070 add(po, p5, [p1], 2) 1071 add(po, p6, [p3,p4], 2) 1072 add(po, p, [p2,p5,p6], 2) 1073 1074 def testPockleNegative(self): 1075 def add_small(po, p): 1076 self.assertEqual(pockle_add_small_prime(po, p), 'POCKLE_OK') 1077 1078 po = pockle_new() 1079 self.assertEqual(pockle_add_small_prime(po, 0), 1080 'POCKLE_PRIME_SMALLER_THAN_2') 1081 self.assertEqual(pockle_add_small_prime(po, 1), 1082 'POCKLE_PRIME_SMALLER_THAN_2') 1083 self.assertEqual(pockle_add_small_prime(po, 2**61 - 1), 1084 'POCKLE_SMALL_PRIME_NOT_SMALL') 1085 self.assertEqual(pockle_add_small_prime(po, 4), 1086 'POCKLE_SMALL_PRIME_NOT_PRIME') 1087 1088 po = pockle_new() 1089 self.assertEqual(pockle_add_prime(po, 1919519569386763, [8574133], 2), 1090 'POCKLE_FACTOR_NOT_KNOWN_PRIME') 1091 1092 po = pockle_new() 1093 add_small(po, 8574133) 1094 self.assertEqual(pockle_add_prime(po, 1919519569386765, [8574133], 2), 1095 'POCKLE_FACTOR_NOT_A_FACTOR') 1096 1097 p = 4095744004479977 1098 factors = [2, 79997] # not quite enough factors to reach cbrt(p) 1099 po = pockle_new() 1100 for q in factors: 1101 add_small(po, q) 1102 self.assertEqual(pockle_add_prime(po, p, factors, 3), 1103 'POCKLE_PRODUCT_OF_FACTORS_TOO_SMALL') 1104 1105 p = 1999527 * 3999053 1106 factors = [999763] 1107 po = pockle_new() 1108 for q in factors: 1109 add_small(po, q) 1110 self.assertEqual(pockle_add_prime(po, p, factors, 3), 1111 'POCKLE_DISCRIMINANT_IS_SQUARE') 1112 1113 p = 9999929 * 9999931 1114 factors = [257, 2593] 1115 po = pockle_new() 1116 for q in factors: 1117 add_small(po, q) 1118 self.assertEqual(pockle_add_prime(po, p, factors, 3), 1119 'POCKLE_FERMAT_TEST_FAILED') 1120 1121 p = 1713000920401 # a Carmichael number 1122 po = pockle_new() 1123 add_small(po, 561787) 1124 self.assertEqual(pockle_add_prime(po, p, [561787], 2), 1125 'POCKLE_WITNESS_POWER_IS_1') 1126 1127 p = 4294971121 1128 factors = [3, 5, 11, 17] 1129 po = pockle_new() 1130 for q in factors: 1131 add_small(po, q) 1132 self.assertEqual(pockle_add_prime(po, p, factors, 17), 1133 'POCKLE_WITNESS_POWER_NOT_COPRIME') 1134 1135 po = pockle_new() 1136 add_small(po, 2) 1137 self.assertEqual(pockle_add_prime(po, 1, [2], 1), 1138 'POCKLE_PRIME_SMALLER_THAN_2') 1139 1140class crypt(MyTestBase): 1141 def testSSH1Fingerprint(self): 1142 # Example key and reference fingerprint value generated by 1143 # OpenSSH 6.7 ssh-keygen 1144 rsa = rsa_bare(65537, 984185866443261798625575612408956568591522723900235822424492423996716524817102482330189709310179009158443944785704183009867662230534501187034891091310377917105259938712348098594526746211645472854839799025154390701673823298369051411) 1145 fp = rsa_ssh1_fingerprint(rsa) 1146 self.assertEqual( 1147 fp, b"768 96:12:c8:bc:e6:03:75:86:e8:c7:b9:af:d8:0c:15:75") 1148 1149 def testSSH2Fingerprints(self): 1150 # A sensible key blob that we can make sense of. 1151 sensible_blob = base64.decodebytes( 1152 b'AAAAC3NzaC1lZDI1NTE5AAAAICWiV0VAD4lQ7taUN7vZ5Rkc' 1153 b'SLJBW5ubn6ZINwCOzpn3') 1154 self.assertEqual(ssh2_fingerprint_blob(sensible_blob, "sha256"), 1155 b'ssh-ed25519 255 SHA256:' 1156 b'E4VmaHW0sUF7SUgSEOmMJ8WBtt0e/j3zbsKvyqfFnu4') 1157 self.assertEqual(ssh2_fingerprint_blob(sensible_blob, "md5"), 1158 b'ssh-ed25519 255 ' 1159 b'35:73:80:df:a3:2c:1a:f2:2c:a6:5c:84:ce:48:6a:7e') 1160 1161 # A key blob with an unknown algorithm name, so that we can't 1162 # extract the bit count. 1163 silly_blob = ssh_string(b'foo') + ssh_string(b'key data') 1164 self.assertEqual(ssh2_fingerprint_blob(silly_blob, "sha256"), 1165 b'foo SHA256:' 1166 b'mvfJTB4PaRI7hxYaYwn0sH8G6zW1HbLkbWnZE2YIKc4') 1167 self.assertEqual(ssh2_fingerprint_blob(silly_blob, "md5"), 1168 b'foo ' 1169 b'5f:5f:97:94:97:be:01:5c:f6:3f:e3:6e:55:46:ea:52') 1170 1171 # A key blob without even a valid algorithm-name string at the start. 1172 very_silly_blob = b'foo' 1173 self.assertEqual(ssh2_fingerprint_blob(very_silly_blob, "sha256"), 1174 b'SHA256:' 1175 b'LCa0a2j/xo/5m0U8HTBBNBNCLXBkg7+g+YpeiGJm564') 1176 self.assertEqual(ssh2_fingerprint_blob(very_silly_blob, "md5"), 1177 b'ac:bd:18:db:4c:c2:f8:5c:ed:ef:65:4f:cc:c4:a4:d8') 1178 1179 def testAES(self): 1180 # My own test cases, generated by a mostly independent 1181 # reference implementation of AES in Python. ('Mostly' 1182 # independent in that it was written by me.) 1183 1184 def vector(cipher, key, iv, plaintext, ciphertext): 1185 for suffix in "hw", "sw": 1186 c = ssh_cipher_new("{}_{}".format(cipher, suffix)) 1187 if c is None: return # skip test if HW AES not available 1188 ssh_cipher_setkey(c, key) 1189 ssh_cipher_setiv(c, iv) 1190 self.assertEqualBin( 1191 ssh_cipher_encrypt(c, plaintext), ciphertext) 1192 ssh_cipher_setiv(c, iv) 1193 self.assertEqualBin( 1194 ssh_cipher_decrypt(c, ciphertext), plaintext) 1195 1196 # Tests of CBC mode. 1197 1198 key = unhex( 1199 '98483c6eb40b6c31a448c22a66ded3b5e5e8d5119cac8327b655c8b5c4836489') 1200 iv = unhex('38f87b0b9b736160bfc0cbd8447af6ee') 1201 plaintext = unhex(''' 1202 ee16271827b12d828f61d56fddccc38ccaa69601da2b36d3af1a34c51947b71a 1203 362f05e07bf5e7766c24599799b252ad2d5954353c0c6ca668c46779c2659c94 1204 8df04e4179666e335470ff042e213c8bcff57f54842237fbf9f3c7e6111620ac 1205 1c007180edd25f0e337c2a49d890a7173f6b52d61e3d2a21ddc8e41513a0e825 1206 afd5932172270940b01014b5b7fb8495946151520a126518946b44ea32f9b2a9 1207 ''') 1208 1209 vector('aes128_cbc', key[:16], iv, plaintext, unhex(''' 1210 547ee90514cb6406d5bb00855c8092892c58299646edda0b4e7c044247795c8d 1211 3c3eb3d91332e401215d4d528b94a691969d27b7890d1ae42fe3421b91c989d5 1212 113fefa908921a573526259c6b4f8e4d90ea888e1d8b7747457ba3a43b5b79b9 1213 34873ebf21102d14b51836709ee85ed590b7ca618a1e884f5c57c8ea73fe3d0d 1214 6bf8c082dd602732bde28131159ed0b6e9cf67c353ffdd010a5a634815aaa963''')) 1215 1216 vector('aes192_cbc', key[:24], iv, plaintext, unhex(''' 1217 e3dee5122edd3fec5fab95e7db8c784c0cb617103e2a406fba4ae3b4508dd608 1218 4ff5723a670316cc91ed86e413c11b35557c56a6f5a7a2c660fc6ee603d73814 1219 73a287645be0f297cdda97aef6c51faeb2392fec9d33adb65138d60f954babd9 1220 8ee0daab0d1decaa8d1e07007c4a3c7b726948025f9fb72dd7de41f74f2f36b4 1221 23ac6a5b4b6b39682ec74f57d9d300e547f3c3e467b77f5e4009923b2f94c903''')) 1222 1223 vector('aes256_cbc', key[:32], iv, plaintext, unhex(''' 1224 088c6d4d41997bea79c408925255266f6c32c03ea465a5f607c2f076ec98e725 1225 7e0beed79609b3577c16ebdf17d7a63f8865278e72e859e2367de81b3b1fe9ab 1226 8f045e1d008388a3cfc4ff87daffedbb47807260489ad48566dbe73256ce9dd4 1227 ae1689770a883b29695928f5983f33e8d7aec4668f64722e943b0b671c365709 1228 dfa86c648d5fb00544ff11bd29121baf822d867e32da942ba3a0d26299bcee13''')) 1229 1230 # Tests of SDCTR mode, one with a random IV and one with an IV 1231 # about to wrap round. More vigorous tests of IV carry and 1232 # wraparound behaviour are in the testAESSDCTR method. 1233 1234 sdctrIVs = [ 1235 unhex('38f87b0b9b736160bfc0cbd8447af6ee'), 1236 unhex('fffffffffffffffffffffffffffffffe'), 1237 ] 1238 1239 vector('aes128_ctr', key[:16], sdctrIVs[0], plaintext[:64], unhex(''' 1240 d0061d7b6e8c4ef4fe5614b95683383f46cdd2766e66b6fb0b0f0b3a24520b2d 1241 15d869b06cbf685ede064bcf8fb5fb6726cfd68de7016696a126e9e84420af38''')) 1242 vector('aes128_ctr', key[:16], sdctrIVs[1], plaintext[:64], unhex(''' 1243 49ac67164fd9ce8701caddbbc9a2b06ac6524d4aa0fdac95253971974b8f3bc2 1244 bb8d7c970f6bcd79b25218cc95582edf7711aae2384f6cf91d8d07c9d9b370bc''')) 1245 1246 vector('aes192_ctr', key[:24], sdctrIVs[0], plaintext[:64], unhex(''' 1247 0baa86acbe8580845f0671b7ebad4856ca11b74e5108f515e34e54fa90f87a9a 1248 c6eee26686253c19156f9be64957f0dbc4f8ecd7cabb1f4e0afefe33888faeec''')) 1249 vector('aes192_ctr', key[:24], sdctrIVs[1], plaintext[:64], unhex(''' 1250 2da1791250100dc0d1461afe1bbfad8fa0320253ba5d7905d837386ba0a3a41f 1251 01965c770fcfe01cf307b5316afb3981e0e4aa59a6e755f0a5784d9accdc52be''')) 1252 1253 vector('aes256_ctr', key[:32], sdctrIVs[0], plaintext[:64], unhex(''' 1254 49c7b284222d408544c770137b6ef17ef770c47e24f61fa66e7e46cae4888882 1255 f980a0f2446956bf47d2aed55ebd2e0694bfc46527ed1fd33efe708fec2f8b1f''')) 1256 vector('aes256_ctr', key[:32], sdctrIVs[1], plaintext[:64], unhex(''' 1257 f1d013c3913ccb4fc0091e25d165804480fb0a1d5c741bf012bba144afda6db2 1258 c512f3942018574bd7a8fdd88285a73d25ef81e621aebffb6e9b8ecc8e2549d4''')) 1259 1260 def testAESSDCTR(self): 1261 # A thorough test of the IV-incrementing component of SDCTR 1262 # mode. We set up an AES-SDCTR cipher object with the given 1263 # input IV; we encrypt two all-zero blocks, expecting the 1264 # return values to be the AES-ECB encryptions of the input IV 1265 # and the incremented version. Then we decrypt each of them by 1266 # feeding them to an AES-CBC cipher object with its IV set to 1267 # zero. 1268 1269 def increment(keylen, suffix, iv): 1270 key = b'\xab' * (keylen//8) 1271 sdctr = ssh_cipher_new("aes{}_ctr_{}".format(keylen, suffix)) 1272 if sdctr is None: return # skip test if HW AES not available 1273 ssh_cipher_setkey(sdctr, key) 1274 cbc = ssh_cipher_new("aes{}_cbc_{}".format(keylen, suffix)) 1275 ssh_cipher_setkey(cbc, key) 1276 1277 ssh_cipher_setiv(sdctr, iv) 1278 ec0 = ssh_cipher_encrypt(sdctr, b'\x00' * 16) 1279 ec1 = ssh_cipher_encrypt(sdctr, b'\x00' * 16) 1280 ssh_cipher_setiv(cbc, b'\x00' * 16) 1281 dc0 = ssh_cipher_decrypt(cbc, ec0) 1282 ssh_cipher_setiv(cbc, b'\x00' * 16) 1283 dc1 = ssh_cipher_decrypt(cbc, ec1) 1284 self.assertEqualBin(iv, dc0) 1285 return dc1 1286 1287 def test(keylen, suffix, ivInteger): 1288 mask = (1 << 128) - 1 1289 ivInteger &= mask 1290 ivBinary = unhex("{:032x}".format(ivInteger)) 1291 ivIntegerInc = (ivInteger + 1) & mask 1292 ivBinaryInc = unhex("{:032x}".format((ivIntegerInc))) 1293 actualResult = increment(keylen, suffix, ivBinary) 1294 if actualResult is not None: 1295 self.assertEqualBin(actualResult, ivBinaryInc) 1296 1297 # Check every input IV you can make by gluing together 32-bit 1298 # pieces of the form 0, 1 or -1. This should test all the 1299 # places where carry propagation within the 128-bit integer 1300 # can go wrong. 1301 # 1302 # We also test this at all three AES key lengths, in case the 1303 # core cipher routines are written separately for each one. 1304 1305 for suffix in "hw", "sw": 1306 for keylen in [128, 192, 256]: 1307 hexTestValues = ["00000000", "00000001", "ffffffff"] 1308 for ivHexBytes in itertools.product(*([hexTestValues] * 4)): 1309 ivInteger = int("".join(ivHexBytes), 16) 1310 test(keylen, suffix, ivInteger) 1311 1312 def testAESParallelism(self): 1313 # Since at least one of our implementations of AES works in 1314 # parallel, here's a test that CBC decryption works the same 1315 # way no matter how the input data is divided up. 1316 1317 # A pile of conveniently available random-looking test data. 1318 test_ciphertext = ssh2_mpint(last(fibonacci_scattered(14))) 1319 test_ciphertext += b"x" * (15 & -len(test_ciphertext)) # pad to a block 1320 1321 # Test key and IV. 1322 test_key = b"foobarbazquxquuxFooBarBazQuxQuux" 1323 test_iv = b"FOOBARBAZQUXQUUX" 1324 1325 for keylen in [128, 192, 256]: 1326 decryptions = [] 1327 1328 for suffix in "hw", "sw": 1329 c = ssh_cipher_new("aes{:d}_cbc_{}".format(keylen, suffix)) 1330 if c is None: continue 1331 ssh_cipher_setkey(c, test_key[:keylen//8]) 1332 for chunklen in range(16, 16*12, 16): 1333 ssh_cipher_setiv(c, test_iv) 1334 decryption = b"" 1335 for pos in range(0, len(test_ciphertext), chunklen): 1336 chunk = test_ciphertext[pos:pos+chunklen] 1337 decryption += ssh_cipher_decrypt(c, chunk) 1338 decryptions.append(decryption) 1339 1340 for d in decryptions: 1341 self.assertEqualBin(d, decryptions[0]) 1342 1343 def testCRC32(self): 1344 # Check the effect of every possible single-byte input to 1345 # crc32_update. In the traditional implementation with a 1346 # 256-word lookup table, this exercises every table entry; in 1347 # _any_ implementation which iterates over the input one byte 1348 # at a time, it should be a similarly exhaustive test. (But if 1349 # a more optimised implementation absorbed _more_ than 8 bits 1350 # at a time, then perhaps this test wouldn't be enough...) 1351 1352 # It would be nice if there was a functools.iterate() which 1353 # would apply a function n times. Failing that, making shift1 1354 # accept and ignore a second argument allows me to iterate it 1355 # 8 times using functools.reduce. 1356 shift1 = lambda x, dummy=None: (x >> 1) ^ (0xEDB88320 * (x & 1)) 1357 shift8 = lambda x: functools.reduce(shift1, [None]*8, x) 1358 1359 # A small selection of choices for the other input to 1360 # crc32_update, just to check linearity. 1361 test_prior_values = [0, 0xFFFFFFFF, 0x45CC1F6A, 0xA0C4ADCF, 0xD482CDF1] 1362 1363 for prior in test_prior_values: 1364 prior_shifted = shift8(prior) 1365 for i in range(256): 1366 exp = shift8(i) ^ prior_shifted 1367 self.assertEqual(crc32_update(prior, struct.pack("B", i)), exp) 1368 1369 # Check linearity of the _reference_ implementation, while 1370 # we're at it! 1371 self.assertEqual(shift8(i ^ prior), exp) 1372 1373 def testCRCDA(self): 1374 def pattern(badblk, otherblks, pat): 1375 # Arrange copies of the bad block in a pattern 1376 # corresponding to the given bit string. 1377 retstr = b"" 1378 while pat != 0: 1379 retstr += (badblk if pat & 1 else next(otherblks)) 1380 pat >>= 1 1381 return retstr 1382 1383 def testCases(pat): 1384 badblock = b'muhahaha' # the block we'll maliciously repeat 1385 1386 # Various choices of the other blocks, including all the 1387 # same, all different, and all different but only in the 1388 # byte at one end. 1389 for otherblocks in [ 1390 itertools.repeat(b'GoodData'), 1391 (struct.pack('>Q', i) for i in itertools.count()), 1392 (struct.pack('<Q', i) for i in itertools.count())]: 1393 yield pattern(badblock, otherblocks, pat) 1394 1395 def positiveTest(pat): 1396 for data in testCases(pat): 1397 self.assertTrue(crcda_detect(data, "")) 1398 self.assertTrue(crcda_detect(data[8:], data[:8])) 1399 1400 def negativeTest(pat): 1401 for data in testCases(pat): 1402 self.assertFalse(crcda_detect(data, "")) 1403 self.assertFalse(crcda_detect(data[8:], data[:8])) 1404 1405 # Tests of successful attack detection, derived by taking 1406 # multiples of the CRC polynomial itself. 1407 # 1408 # (The CRC32 polynomial is usually written as 0xEDB88320. 1409 # That's in bit-reversed form, but then, that's the form we 1410 # need anyway for these patterns. But it's also missing the 1411 # leading term - really, 0xEDB88320 is the value you get by 1412 # reducing X^32 modulo the real poly, i.e. the value you put 1413 # back in to the CRC to compensate for an X^32 that's just 1414 # been shifted out. If you put that bit back on - at the 1415 # bottom, because of the bit-reversal - you get the less 1416 # familiar-looking 0x1db710641.) 1417 positiveTest(0x1db710641) # the CRC polynomial P itself 1418 positiveTest(0x26d930ac3) # (X+1) * P 1419 positiveTest(0xbdbdf21cf) # (X^3+X^2+X+1) * P 1420 positiveTest(0x3a66a39b653f6889d) 1421 positiveTest(0x170db3167dd9f782b9765214c03e71a18f685b7f3) 1422 positiveTest(0x1751997d000000000000000000000000000000001) 1423 positiveTest(0x800000000000000000000000000000000f128a2d1) 1424 1425 # Tests of non-detection. 1426 negativeTest(0x1db711a41) 1427 negativeTest(0x3a66a39b453f6889d) 1428 negativeTest(0x170db3167dd9f782b9765214c03e71b18f685b7f3) 1429 negativeTest(0x1751997d000000000000000000000001000000001) 1430 negativeTest(0x800000000000002000000000000000000f128a2d1) 1431 1432 def testAuxEncryptFns(self): 1433 # Test helper functions such as aes256_encrypt_pubkey. The 1434 # test cases are all just things I made up at random, and the 1435 # expected outputs are generated by running PuTTY's own code; 1436 # this doesn't independently check them against any other 1437 # implementation, but it at least means we're protected 1438 # against code reorganisations changing the behaviour from 1439 # what it was before. 1440 1441 p = b'three AES blocks, or six DES, of arbitrary input' 1442 1443 k = b'thirty-two-byte aes-256 test key' 1444 iv = b'\0' * 16 1445 c = unhex('7b112d00c0fc95bc13fcdacfd43281bf' 1446 'de9389db1bbcfde79d59a303d41fd2eb' 1447 '0955c9477ae4ee3a4d6c1fbe474c0ef6') 1448 self.assertEqualBin(aes256_encrypt_pubkey(k, iv, p), c) 1449 self.assertEqualBin(aes256_decrypt_pubkey(k, iv, c), p) 1450 1451 # same k as in the previous case 1452 iv = unhex('0102030405060708090a0b0c0d0e0f10') 1453 c = unhex('9e9c8a91b739677b834397bdd8e70c05' 1454 'c3e2cf6cce68d376d798a59848621c6d' 1455 '42b9e7101260a438daadd7b742875a36') 1456 self.assertEqualBin(aes256_encrypt_pubkey(k, iv, p), c) 1457 self.assertEqualBin(aes256_decrypt_pubkey(k, iv, c), p) 1458 1459 k = b'3des with keys distinct.' 1460 iv = b'randomIV' 1461 c = unhex('be81ff840d885869a54d63b03d7cd8db' 1462 'd39ab875e5f7b9da1081f8434cb33c47' 1463 'dee5bcd530a3f6c13a9fc73e321a843a') 1464 self.assertEqualBin(des3_encrypt_pubkey_ossh(k, iv, p), c) 1465 self.assertEqualBin(des3_decrypt_pubkey_ossh(k, iv, c), p) 1466 1467 k = b'3des, 2keys only' 1468 c = unhex('0b845650d73f615cf16ee3ed20535b5c' 1469 'd2a8866ee628547bbdad916e2b4b9f19' 1470 '67c15bde33c5b03ff7f403b4f8cf2364') 1471 self.assertEqualBin(des3_encrypt_pubkey(k, p), c) 1472 self.assertEqualBin(des3_decrypt_pubkey(k, c), p) 1473 1474 k = b'7 bytes' 1475 c = unhex('5cac9999cffc980a1d1184d84b71c8cb' 1476 '313d12a1d25a7831179aeb11edaca5ad' 1477 '9482b224105a61c27137587620edcba8') 1478 self.assertEqualBin(des_encrypt_xdmauth(k, p), c) 1479 self.assertEqualBin(des_decrypt_xdmauth(k, c), p) 1480 1481 def testSSHCiphers(self): 1482 # Test all the SSH ciphers we support, on the same principle 1483 # as testAuxCryptFns that we should have test cases to verify 1484 # that things still work the same today as they did yesterday. 1485 1486 p = b'64 bytes of test input data, enough to check any cipher mode xyz' 1487 k = b'sixty-four bytes of test key data, enough to key any cipher pqrs' 1488 iv = b'16 bytes of IV w' 1489 1490 ciphers = [ 1491 ("3des_ctr", 24, 8, False, unhex('83c17a29250d3d4fa81250fc0362c54e40456936445b77709a30fccf8b983d57129a969c59070d7c2977f3d25dd7d71163687c7b3cd2edb0d07514e6c77479f5')), 1492 ("3des_ssh2", 24, 8, True, unhex('d5f1cc25b8fbc62decc74b432344de674f7249b2e38871f764411eaae17a1097396bd97b66a1e4d49f08c219acaef2a483198ce837f75cc1ef67b37c2432da3e')), 1493 ("3des_ssh1", 24, 8, False, unhex('d5f1cc25b8fbc62de63590b9b92344adf6dd72753273ff0fb32d4dbc6af858529129f34242f3d557eed3a5c84204eb4f868474294964cf70df5d8f45dfccfc45')), 1494 ("des_cbc", 8, 8, True, unhex('051524e77fb40e109d9fffeceacf0f28c940e2f8415ddccc117020bdd2612af5036490b12085d0e46129919b8e499f51cb82a4b341d7a1a1ea3e65201ef248f6')), 1495 ("aes256_ctr", 32, 16, False, unhex('b87b35e819f60f0f398a37b05d7bcf0b04ad4ebe570bd08e8bfa8606bafb0db2cfcd82baf2ccceae5de1a3c1ae08a8b8fdd884fdc5092031ea8ce53333e62976')), 1496 ("aes256_ctr_hw", 32, 16, False, unhex('b87b35e819f60f0f398a37b05d7bcf0b04ad4ebe570bd08e8bfa8606bafb0db2cfcd82baf2ccceae5de1a3c1ae08a8b8fdd884fdc5092031ea8ce53333e62976')), 1497 ("aes256_ctr_sw", 32, 16, False, unhex('b87b35e819f60f0f398a37b05d7bcf0b04ad4ebe570bd08e8bfa8606bafb0db2cfcd82baf2ccceae5de1a3c1ae08a8b8fdd884fdc5092031ea8ce53333e62976')), 1498 ("aes256_cbc", 32, 16, True, unhex('381cbb2fbcc48118d0094540242bd990dd6af5b9a9890edd013d5cad2d904f34b9261c623a452f32ea60e5402919a77165df12862742f1059f8c4a862f0827c5')), 1499 ("aes256_cbc_hw", 32, 16, True, unhex('381cbb2fbcc48118d0094540242bd990dd6af5b9a9890edd013d5cad2d904f34b9261c623a452f32ea60e5402919a77165df12862742f1059f8c4a862f0827c5')), 1500 ("aes256_cbc_sw", 32, 16, True, unhex('381cbb2fbcc48118d0094540242bd990dd6af5b9a9890edd013d5cad2d904f34b9261c623a452f32ea60e5402919a77165df12862742f1059f8c4a862f0827c5')), 1501 ("aes192_ctr", 24, 16, False, unhex('06bcfa7ccf075d723e12b724695a571a0fad67c56287ea609c410ac12749c51bb96e27fa7e1c7ea3b14792bbbb8856efb0617ebec24a8e4a87340d820cf347b8')), 1502 ("aes192_ctr_hw", 24, 16, False, unhex('06bcfa7ccf075d723e12b724695a571a0fad67c56287ea609c410ac12749c51bb96e27fa7e1c7ea3b14792bbbb8856efb0617ebec24a8e4a87340d820cf347b8')), 1503 ("aes192_ctr_sw", 24, 16, False, unhex('06bcfa7ccf075d723e12b724695a571a0fad67c56287ea609c410ac12749c51bb96e27fa7e1c7ea3b14792bbbb8856efb0617ebec24a8e4a87340d820cf347b8')), 1504 ("aes192_cbc", 24, 16, True, unhex('ac97f8698170f9c05341214bd7624d5d2efef8311596163dc597d9fe6c868971bd7557389974612cbf49ea4e7cc6cc302d4cc90519478dd88a4f09b530c141f3')), 1505 ("aes192_cbc_hw", 24, 16, True, unhex('ac97f8698170f9c05341214bd7624d5d2efef8311596163dc597d9fe6c868971bd7557389974612cbf49ea4e7cc6cc302d4cc90519478dd88a4f09b530c141f3')), 1506 ("aes192_cbc_sw", 24, 16, True, unhex('ac97f8698170f9c05341214bd7624d5d2efef8311596163dc597d9fe6c868971bd7557389974612cbf49ea4e7cc6cc302d4cc90519478dd88a4f09b530c141f3')), 1507 ("aes128_ctr", 16, 16, False, unhex('0ad4ddfd2360ec59d77dcb9a981f92109437c68c5e7f02f92017d9f424f89ab7850473ac0e19274125e740f252c84ad1f6ad138b6020a03bdaba2f3a7378ce1e')), 1508 ("aes128_ctr_hw", 16, 16, False, unhex('0ad4ddfd2360ec59d77dcb9a981f92109437c68c5e7f02f92017d9f424f89ab7850473ac0e19274125e740f252c84ad1f6ad138b6020a03bdaba2f3a7378ce1e')), 1509 ("aes128_ctr_sw", 16, 16, False, unhex('0ad4ddfd2360ec59d77dcb9a981f92109437c68c5e7f02f92017d9f424f89ab7850473ac0e19274125e740f252c84ad1f6ad138b6020a03bdaba2f3a7378ce1e')), 1510 ("aes128_cbc", 16, 16, True, unhex('36de36917fb7955a711c8b0bf149b29120a77524f393ae3490f4ce5b1d5ca2a0d7064ce3c38e267807438d12c0e40cd0d84134647f9f4a5b11804a0cc5070e62')), 1511 ("aes128_cbc_hw", 16, 16, True, unhex('36de36917fb7955a711c8b0bf149b29120a77524f393ae3490f4ce5b1d5ca2a0d7064ce3c38e267807438d12c0e40cd0d84134647f9f4a5b11804a0cc5070e62')), 1512 ("aes128_cbc_sw", 16, 16, True, unhex('36de36917fb7955a711c8b0bf149b29120a77524f393ae3490f4ce5b1d5ca2a0d7064ce3c38e267807438d12c0e40cd0d84134647f9f4a5b11804a0cc5070e62')), 1513 ("blowfish_ctr", 32, 8, False, unhex('079daf0f859363ccf72e975764d709232ec48adc74f88ccd1f342683f0bfa89ca0e8dbfccc8d4d99005d6b61e9cc4e6eaa2fd2a8163271b94bf08ef212129f01')), 1514 ("blowfish_ssh2", 16, 8, True, unhex('e986b7b01f17dfe80ee34cac81fa029b771ec0f859ae21ae3ec3df1674bc4ceb54a184c6c56c17dd2863c3e9c068e76fd9aef5673465995f0d648b0bb848017f')), 1515 ("blowfish_ssh1", 32, 8, True, unhex('d44092a9035d895acf564ba0365d19570fbb4f125d5a4fd2a1812ee6c8a1911a51bb181fbf7d1a261253cab71ee19346eb477b3e7ecf1d95dd941e635c1a4fbf')), 1516 ("arcfour256", 32, None, False, unhex('db68db4cd9bbc1d302cce5919ff3181659272f5d38753e464b3122fc69518793fe15dd0fbdd9cd742bd86c5e8a3ae126c17ecc420bd2d5204f1a24874d00fda3')), 1517 ("arcfour128", 16, None, False, unhex('fd4af54c5642cb29629e50a15d22e4944e21ffba77d0543b27590eafffe3886686d1aefae0484afc9e67edc0e67eb176bbb5340af1919ea39adfe866d066dd05')), 1518 ] 1519 1520 for alg, keylen, ivlen, simple_cbc, c in ciphers: 1521 cipher = ssh_cipher_new(alg) 1522 if cipher is None: 1523 continue # hardware-accelerated cipher not available 1524 1525 ssh_cipher_setkey(cipher, k[:keylen]) 1526 if ivlen is not None: 1527 ssh_cipher_setiv(cipher, iv[:ivlen]) 1528 self.assertEqualBin(ssh_cipher_encrypt(cipher, p), c) 1529 1530 ssh_cipher_setkey(cipher, k[:keylen]) 1531 if ivlen is not None: 1532 ssh_cipher_setiv(cipher, iv[:ivlen]) 1533 self.assertEqualBin(ssh_cipher_decrypt(cipher, c), p) 1534 1535 if simple_cbc: 1536 # CBC ciphers (other than the three-layered CBC used 1537 # by SSH-1 3DES) have more specific semantics for 1538 # their IV than 'some kind of starting state for the 1539 # cipher mode': the IV is specifically supposed to 1540 # represent the previous block of ciphertext. So we 1541 # can check that, by supplying the IV _as_ a 1542 # ciphertext block via a call to decrypt(), and seeing 1543 # if that causes our test ciphertext to decrypt the 1544 # same way as when we provided the same IV via 1545 # setiv(). 1546 ssh_cipher_setkey(cipher, k[:keylen]) 1547 ssh_cipher_decrypt(cipher, iv[:ivlen]) 1548 self.assertEqualBin(ssh_cipher_decrypt(cipher, c), p) 1549 1550 def testRSAKex(self): 1551 # Round-trip test of the RSA key exchange functions, plus a 1552 # hardcoded plain/ciphertext pair to guard against the 1553 # behaviour accidentally changing. 1554 def blobs(n, e, d, p, q, iqmp): 1555 # For RSA kex, the public blob is formatted exactly like 1556 # any other SSH-2 RSA public key. But there's no private 1557 # key blob format defined by the protocol, so for the 1558 # purposes of making a test RSA private key, we borrow the 1559 # function we already had that decodes one out of the wire 1560 # format used in the SSH-1 agent protocol. 1561 pubblob = ssh_string(b"ssh-rsa") + ssh2_mpint(e) + ssh2_mpint(n) 1562 privblob = (ssh_uint32(nbits(n)) + ssh1_mpint(n) + ssh1_mpint(e) + 1563 ssh1_mpint(d) + ssh1_mpint(iqmp) + 1564 ssh1_mpint(q) + ssh1_mpint(p)) 1565 return pubblob, privblob 1566 1567 # Parameters for a test key. 1568 p = 0xf49e4d21c1ec3d1c20dc8656cc29aadb2644a12c98ed6c81a6161839d20d398d 1569 q = 0xa5f0bc464bf23c4c83cf17a2f396b15136fbe205c07cb3bb3bdb7ed357d1cd13 1570 n = p*q 1571 e = 37 1572 d = int(mp_invert(e, (p-1)*(q-1))) 1573 iqmp = int(mp_invert(q, p)) 1574 assert iqmp * q % p == 1 1575 assert d * e % (p-1) == 1 1576 assert d * e % (q-1) == 1 1577 1578 pubblob, privblob = blobs(n, e, d, p, q, iqmp) 1579 1580 pubkey = ssh_rsakex_newkey(pubblob) 1581 privkey = get_rsa_ssh1_priv_agent(privblob) 1582 1583 plain = 0x123456789abcdef 1584 hashalg = 'md5' 1585 with queued_random_data(64, "rsakex encrypt test"): 1586 cipher = ssh_rsakex_encrypt(pubkey, hashalg, ssh2_mpint(plain)) 1587 decoded = ssh_rsakex_decrypt(privkey, hashalg, cipher) 1588 self.assertEqual(int(decoded), plain) 1589 self.assertEqualBin(cipher, unhex( 1590 '34277d1060dc0a434d98b4239de9cec59902a4a7d17a763587cdf8c25d57f51a' 1591 '7964541892e7511798e61dd78429358f4d6a887a50d2c5ebccf0e04f48fc665c' 1592 )) 1593 1594 def testMontgomeryKexLowOrderPoints(self): 1595 # List of all the bad input values for Curve25519 which can 1596 # end up generating a zero output key. You can find the first 1597 # five (the ones in canonical representation, i.e. in 1598 # [0,2^255-19)) by running 1599 # find_montgomery_power2_order_x_values(curve25519.p, curve25519.a) 1600 # and then encoding the results little-endian. 1601 bad_keys_25519 = [ 1602 "0000000000000000000000000000000000000000000000000000000000000000", 1603 "0100000000000000000000000000000000000000000000000000000000000000", 1604 "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", 1605 "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", 1606 "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", 1607 1608 # Input values less than 2^255 are reduced mod p, so those 1609 # of the above values which are still in that range when 1610 # you add 2^255-19 to them should also be caught. 1611 "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", 1612 "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", 1613 1614 # Input values are reduced mod 2^255 before reducing mod 1615 # p. So setting the high-order bit of any of the above 7 1616 # values should also lead to rejection, because it will be 1617 # stripped off and then the value will be recognised as 1618 # one of the above. 1619 "0000000000000000000000000000000000000000000000000000000000000080", 1620 "0100000000000000000000000000000000000000000000000000000000000080", 1621 "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7", 1622 "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880", 1623 "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1624 "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1625 "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1626 ] 1627 1628 # Same for Curve448, found by the analogous eccref function call 1629 # find_montgomery_power2_order_x_values(curve448.p, curve448.a) 1630 bad_keys_448 = [ 1631 # The first three are the bad values in canonical 1632 # representationm. In Curve448 these are just 0, 1 and -1. 1633 '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 1634 '0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 1635 'fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1636 1637 # As with Curve25519, we must also include values in 1638 # non-canonical representation that reduce to one of the 1639 # above mod p. 1640 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1641 '00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' 1642 1643 # But that's all, because Curve448 fits neatly into a 1644 # whole number of bytes, so there's no secondary reduction 1645 # mod a power of 2. 1646 ] 1647 1648 with random_prng("doesn't matter"): 1649 ecdh25519 = ssh_ecdhkex_newkey('curve25519') 1650 ecdh448 = ssh_ecdhkex_newkey('curve448') 1651 for pub in bad_keys_25519: 1652 key = ssh_ecdhkex_getkey(ecdh25519, unhex(pub)) 1653 self.assertEqual(key, None) 1654 for pub in bad_keys_448: 1655 key = ssh_ecdhkex_getkey(ecdh448, unhex(pub)) 1656 self.assertEqual(key, None) 1657 1658 def testPRNG(self): 1659 hashalg = 'sha256' 1660 seed = b"hello, world" 1661 entropy = b'1234567890' * 100 1662 1663 # Replicate the generation of some random numbers. to ensure 1664 # they really are the hashes of what they're supposed to be. 1665 pr = prng_new(hashalg) 1666 prng_seed_begin(pr) 1667 prng_seed_update(pr, seed) 1668 prng_seed_finish(pr) 1669 data1 = prng_read(pr, 128) 1670 data2 = prng_read(pr, 127) # a short read shouldn't confuse things 1671 prng_add_entropy(pr, 0, entropy) # forces a reseed 1672 data3 = prng_read(pr, 128) 1673 1674 le128 = lambda x: le_integer(x, 128) 1675 1676 key1 = hash_str(hashalg, b'R' + seed) 1677 expected_data1 = b''.join( 1678 hash_str(hashalg, key1 + b'G' + le128(counter)) 1679 for counter in range(4)) 1680 # After prng_read finishes, we expect the PRNG to have 1681 # automatically reseeded itself, so that if its internal state 1682 # is revealed then the previous output can't be reconstructed. 1683 key2 = hash_str(hashalg, key1 + b'R') 1684 expected_data2 = b''.join( 1685 hash_str(hashalg, key2 + b'G' + le128(counter)) 1686 for counter in range(4,8)) 1687 # There will have been another reseed after the second 1688 # prng_read, and then another due to the entropy. 1689 key3 = hash_str(hashalg, key2 + b'R') 1690 key4 = hash_str(hashalg, key3 + b'R' + hash_str(hashalg, entropy)) 1691 expected_data3 = b''.join( 1692 hash_str(hashalg, key4 + b'G' + le128(counter)) 1693 for counter in range(8,12)) 1694 1695 self.assertEqualBin(data1, expected_data1) 1696 self.assertEqualBin(data2, expected_data2[:127]) 1697 self.assertEqualBin(data3, expected_data3) 1698 1699 def testHashPadding(self): 1700 # A consistency test for hashes that use MD5/SHA-1/SHA-2 style 1701 # padding of the message into a whole number of fixed-size 1702 # blocks. We test-hash a message of every length up to twice 1703 # the block length, to make sure there's no off-by-1 error in 1704 # the code that decides how much padding to put on. 1705 1706 # Source: generated using Python hashlib as an independent 1707 # implementation. The function below will do it, called with 1708 # parameters such as (hashlib.sha256,128). 1709 # 1710 # def gen_testcase(hashclass, maxlen): 1711 # return hashclass(b''.join(hashclass(text[:i]).digest() 1712 # for i in range(maxlen))).hexdigest() 1713 1714 text = """ 1715Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do 1716eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad 1717minim veniam, quis nostrud exercitation ullamco laboris nisi ut 1718aliquip ex ea commodo consequat. Duis aute irure dolor in 1719reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla 1720pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 1721culpa qui officia deserunt mollit anim id est laborum. 1722 """.replace('\n', ' ').strip() 1723 1724 def test(hashname, maxlen, expected): 1725 assert len(text) >= maxlen 1726 buf = b''.join(hash_str(hashname, text[:i]) 1727 for i in range(maxlen)) 1728 self.assertEqualBin(hash_str(hashname, buf), unhex(expected)) 1729 1730 test('md5', 128, '8169d766cc3b8df182b3ce756ae19a15') 1731 test('sha1', 128, '3691759577deb3b70f427763a9c15acb9dfc0259') 1732 test('sha256', 128, 'ec539c4d678412c86c13ee4eb9452232' 1733 '35d4eed3368d876fdf10c9df27396640') 1734 test('sha512', 256, 1735 'cb725b4b4ec0ac1174d69427b4d97848b7db4fc01181f99a8049a4d721862578' 1736 'f91e026778bb2d389a9dd88153405189e6ba438b213c5387284103d2267fd055' 1737 ) 1738 1739 def testDSA(self): 1740 p = 0xe93618c54716992ffd54e79df6e1b0edd517f7bbe4a49d64631eb3efe8105f676e8146248cfb4f05720862533210f0c2ab0f9dd61dbc0e5195200c4ebd95364b 1741 q = 0xf3533bcece2e164ca7c5ce64bc1e395e9a15bbdd 1742 g = 0x5ac9d0401c27d7abfbc5c17cdc1dc43323cd0ef18b79e1909bdace6d17af675a10d37dde8bd8b70e72a8666592216ccb00614629c27e870e4fbf393b812a9f05 1743 y = 0xac3ddeb22d65a5a2ded4a28418b2a748d8e5e544ba5e818c137d7b042ef356b0ef6d66cfca0b3ab5affa2969522e7b07bee60562fa4869829a5afce0ad0c4cd0 1744 x = 0x664f8250b7f1a5093047fe0c7fe4b58e46b73295 1745 pubblob = ssh_string(b"ssh-dss") + b"".join(map(ssh2_mpint, [p,q,g,y])) 1746 privblob = ssh2_mpint(x) 1747 pubkey = ssh_key_new_pub('dsa', pubblob) 1748 privkey = ssh_key_new_priv('dsa', pubblob, privblob) 1749 1750 sig = ssh_key_sign(privkey, b"hello, world", 0) 1751 self.assertTrue(ssh_key_verify(pubkey, sig, b"hello, world")) 1752 self.assertFalse(ssh_key_verify(pubkey, sig, b"hello, again")) 1753 1754 badsig0 = unhex('{:040x}{:040x}'.format(1, 0)) 1755 badsigq = unhex('{:040x}{:040x}'.format(1, q)) 1756 self.assertFalse(ssh_key_verify(pubkey, badsig0, "hello, world")) 1757 self.assertFalse(ssh_key_verify(pubkey, badsigq, "hello, world")) 1758 self.assertFalse(ssh_key_verify(pubkey, badsig0, "hello, again")) 1759 self.assertFalse(ssh_key_verify(pubkey, badsigq, "hello, again")) 1760 1761 def testBLAKE2b(self): 1762 # The standard test vectors for BLAKE2b (in the separate class 1763 # below) don't satisfy me because they only test one hash 1764 # size. These additional tests exercise BLAKE2b's configurable 1765 # output length. The expected results are derived from the 1766 # BLAKE2 reference implementation. 1767 1768 def b2_with_len(data, length): 1769 h = blake2b_new_general(length) 1770 h.update(data) 1771 return h.digest()[:length] 1772 1773 self.assertEqualBin(b2_with_len(b'hello', 1), unhex("29")) 1774 self.assertEqualBin(b2_with_len(b'hello', 2), unhex("accd")) 1775 self.assertEqualBin(b2_with_len(b'hello', 3), unhex("980032")) 1776 self.assertEqualBin(b2_with_len(b'hello', 5), unhex("9baecc38f2")) 1777 self.assertEqualBin(b2_with_len(b'hello', 8), unhex( 1778 "a7b6eda801e5347d")) 1779 self.assertEqualBin(b2_with_len(b'hello', 13), unhex( 1780 "6eedb122c6707328a66aa34a07")) 1781 self.assertEqualBin(b2_with_len(b'hello', 21), unhex( 1782 "c7f0f74a227116547b3d2788e927ee2a76c87d8797")) 1783 self.assertEqualBin(b2_with_len(b'hello', 34), unhex( 1784 "2f5fcdf2b870fa254051dd448193a1fb6e92be122efca539ba2aeac0bc6c77d0" 1785 "dadc")) 1786 self.assertEqualBin(b2_with_len(b'hello', 55), unhex( 1787 "daafcf2bd6fccf976cbc234b71cd9f4f7d56fe0eb33a40018707089a215c44a8" 1788 "4b272d0329ae6d85a0f8acc7e964dc2facb715ba472bb6")) 1789 1790 def testArgon2LongHash(self): 1791 # Unit-test the Argon2 long hash function H', which starts off 1792 # the same as BLAKE2b, but comes with its own method of 1793 # extending the output length past 64 bytes. 1794 # 1795 # I generated these test values using a test program linked 1796 # against the reference implementation's libargon2.a and 1797 # calling its blake2b_long function. 1798 preimage = b'hello, world' 1799 1800 self.assertEqualBin(argon2_long_hash(1, preimage), unhex("8b")) 1801 self.assertEqualBin(argon2_long_hash(2, preimage), unhex("1ff9")) 1802 self.assertEqualBin(argon2_long_hash(63, preimage), unhex( 1803 "e2c997721f1d64aa8c25e588fb8ab19646ce6d5c2a431fa560fcb813e55dd481" 1804 "322d2630d95ca6b1b63317b13d6b111e5816170c80c3ca7d5b4bf894096de4")) 1805 self.assertEqualBin(argon2_long_hash(64, preimage), unhex( 1806 "0c7ba7ee6d510b4bb5c9b69ac91e25e0b11aa30dd6234b8e61b0fe1537c037b8" 1807 "8ed5aa59a277e8cc07095c81aff26d08967e4dfdabd32db8b6af6ceb78cf8c47")) 1808 self.assertEqualBin(argon2_long_hash(65, preimage), unhex( 1809 "680941abbd8fc80f28c38d623e90903f08709bf76575e2775d4ce01c31b192c8" 1810 "73038d9a31af8991c8b1ad4f2b1991f4d15f73ab0f4f3add415c297a12eb9ddb" 1811 "76")) 1812 self.assertEqualBin(argon2_long_hash(95, preimage), unhex( 1813 "4be28c51850fed70d9403e1406b6ba68a83d98cf222a4ee162beef60fd3384df" 1814 "eba3fce9d95f646982eb384ac943ce5263cb03428fd8d261cc41ffdb7ba328fe" 1815 "098526f2b49593f9e7f38188598ce4693b59f4dd32db30c1be9a9d35784fa0")) 1816 self.assertEqualBin(argon2_long_hash(96, preimage), unhex( 1817 "20295ea01e822cca113f668f33e5e481ed5879bfd7de6359ea42d497da97be52" 1818 "2cdd518d34ae32c44cabd45249b4e697626b0b14b6a33a2bd138be0a4bceeaf4" 1819 "9528f93acef01b093ee84d8d871d1ee6cf7c10e83ad0619631aed19345166f03")) 1820 self.assertEqualBin(argon2_long_hash(97, preimage), unhex( 1821 "d24b31f3ac0baad168d524efc4bafee55fef743fd60b14e28b860d7523e319c7" 1822 "520e2d5457cc3d06dc1044530afdf6990fa12e38d5802eb642f8e77fcfee2c0b" 1823 "1f84a28877f2f2f049ed9299e1e0230f98af3a161185970aad21f0ea0f5184cf" 1824 "90")) 1825 self.assertEqualBin(argon2_long_hash(127, preimage), unhex( 1826 "5d1e8380450dbc985418ed1f3700b925ae0719e4486e29131c81bca7083ac6b8" 1827 "f535c3398488e34d3dc1390de44097f1eee498f10ebe85b579e99a7672023b01" 1828 "ca5c20e63c595b640e00d80f113a52e3773719889b266ab4c65269c11fb212e4" 1829 "75f2b769bb26321bb60ecc0d490821e5056d7dfc9def3cd065d3ba90360764")) 1830 self.assertEqualBin(argon2_long_hash(128, preimage), unhex( 1831 "be15b316f3483c4d0d00f71a65b974894a2025f441b79b9fe461bc740cb0b039" 1832 "c4fe914f61c05a612d63ebc50a662b2d59b1996091e5e3474340544ea46a46cb" 1833 "25c41ff700fafcd96c4f12ddc698cd2426558f960696837ea8170fd2fe284b54" 1834 "8f585f97919ef14f2b3cbb351eb98872add7ba6d08c1401232df6cc878fbeb22")) 1835 self.assertEqualBin(argon2_long_hash(129, preimage), unhex( 1836 "83da464c278dcb12c29b6685fee6d32f0b461337c155369ad0d56b58b0aa5f80" 1837 "9aa7b56bd41b664c8d768957f8f0e40999fb0178eb53cf83f31d725bf92881bc" 1838 "900774bce4cdf56b6386ad3de6891d11a0ccd4564a3431fc4c24105a02d0a6a2" 1839 "434712b9a7471f3223c72a6e64912200d0a3d149a19d06fe9dc8ec09d7ed5a48" 1840 "bb")) 1841 self.assertEqualBin(argon2_long_hash(511, preimage), unhex( 1842 "30c0c0d0467e7665368db0b40a2324a61fb569d35172de2df53a9739a8d18e60" 1843 "b4f25d521c8855604be3e24ea56302566074323d94c0bd3a33d08f185d8ba5ac" 1844 "a2bc3fb2e4c4e5ffec5778daea67c6b5913c9cac16f2e5c7b7818e757fa747b3" 1845 "69e586d616010a752762f69c604238ed8738430366fbdb7493454fa02391a76b" 1846 "30f241695b9fa8d3a3116227c6bb6f72d325cf104ab153d15f928b22767d467d" 1847 "4bf7e16176aaa7315954b7872061933c12d548f1f93a8abb9d73791661bee521" 1848 "b2ae51be373a229dfef32787234c1be5846d133563002b9a029178716ad41e70" 1849 "1539d3fad300c77607c5217701e3e485d72c980f3f71d525c8148375a2f8d22c" 1850 "a211ba165330a90b7e0e6baa6073833925c23bdd388ee904f38463c7e6b85475" 1851 "09b810aae5c9ffc5dd902c2ffe049c338e3ae2c6416d3b874d6a9d384089564c" 1852 "0d8e4dce9b6e47e1d5ec9087bf526cc9fa35aab1893a0588d31b77fea37e0799" 1853 "468deacde47629d2960a3519b3bcd4e22364a9cccd3b128cba21cac27f140d53" 1854 "f79c11e4157e4cb48272eecdf62f52084a27e5b0933bbe66ded17e2df6f8d398" 1855 "f6c479c3c716457820ad177b8bd9334cb594e03d09fcc4f82d4385e141eacd7d" 1856 "9ad1e1c4cb42788af70bac0509f0a891e662960955490abf2763373803e8c89c" 1857 "df632579cb9c647634b30df214a3d67b92fd55d283c42c63b470a48a78cd5b")) 1858 self.assertEqualBin(argon2_long_hash(512, preimage), unhex( 1859 "79a6974e29a9a6c069e0156774d35c5014a409f5ffc60013725367a7208d4929" 1860 "7d228637751768a31a59e27aa89372f1bcc095a6fa331198a5bd5ad053ba2ebb" 1861 "cbcc501ea55cf142e8d95209228c9ab60cd104d5077472f2a9ecaa071aed6ee9" 1862 "5de29e188b7399d5b6b7ed897b2bc4dd1ea745eb9974e39ca6fb983380cc537a" 1863 "c04dfe6caefe85faf206b1613092ebadf791eaa8a5b814c9a79a73a5733b0505" 1864 "a47163c10a0f7309df6663896df6079a7c88c6879bb591a40abd398c6deda792" 1865 "1cc3986435b1c840a768b2fa507446f2f77a406b1b2f739f7795db24789c8927" 1866 "24b4c84b7005445123154f8cd2ba63a7ede672af5d197f846700732025c9931d" 1867 "1c67c5493417ca394a8f68ba532645815cf7b5102af134ecb4fd9e326f53779a" 1868 "3039dbef6a0880db9e38b6b61d2f9ead969e4224c2d9c69b5897e5eeb7032e83" 1869 "334e192ff50017056ccb84d4cc8eee3ab248d2614643d0174fe18c72186dd967" 1870 "92d8545645ddf4a9b2c7a91c9a71857a399449d7154077a8e9580f1a2d20227d" 1871 "671b455ccb897cba0491e50892120d7877f7776d653cfdb176fa3f64a9e6f848" 1872 "cd681c487b488775aaf698294eec813b2cca90d68d63b5d886d61c1a8e922aaa" 1873 "330fd658ede56e34bcd288048e845eba7b8e2e7cc22ba6c91b523e48017aa878" 1874 "8ce4f91d0e6d6c6706762fb0cc7f465cee3916684fb21e337cfe1b583e0b1e92")) 1875 self.assertEqualBin(argon2_long_hash(513, preimage), unhex( 1876 "32243cfbd7eca582d60b3b8ea3ba3d93783537689c7cbcd1d1cbde46200b8c86" 1877 "617fc00e8a9ae991a1e2f91c67e07d5f0a777d982c1461d0c5474e4e164b053c" 1878 "2808559e2b8a5ac4a46a5fcbc825b1d5302c7b0611940194eb494d45ce7113a2" 1879 "3424b51c199c6a5100ab159ff323eda5feffee4da4155a028a81da9d44e4286b" 1880 "ac3dab4ffce43a80b6ce97a47ea0ac51ee16e8b4d3b68942afdc20e1c21747c4" 1881 "94859c3d3883e7dc19ea416a393a3507683d9d03e6a3a91f8f1cb8a7d5d9892e" 1882 "80c8fb0222527a73a1f59b9dd41770982f2af177a6e96093064534803edd0713" 1883 "71ede53024cedc291d768325bb4e4def9af1b5569c349b64816496c37a8787b5" 1884 "4fbe248372ebadb5ce20e03eaa935dc55ff4b8cbe5d6d844c7b71d4656fef22c" 1885 "5a49f13d75a7a8368a2dbc1e78d732b879bfc5c9467eda2bf4918f0c59037ae3" 1886 "dee7880a171409dd1a4e143c814e60301ac77237f261fa7519a04e68000530f9" 1887 "708ed9fda5609d655560a9491f80f5875ad5725e3120686b73319c6a727932e3" 1888 "20a2174422523498c38fea47aeb20d135ff9fd93c6fa6db0005e0001685d7577" 1889 "33a82a4dc9dd6556b938f7b8dafd0d670846780b9931b815063708189b17877b" 1890 "825533bcc250fb576a28be4caa107e6a3a6f7b0c60fb51b0def27008b7e272ac" 1891 "95d610bfa912339799a2e537ce543d7862dddbe31bb224fda4ae283571847a28" 1892 "54")) 1893 self.assertEqualBin(argon2_long_hash(1024, preimage), unhex( 1894 "951252f6fa152124f381266a358d9b78b88e469d08d5fc78e4ea32253c7fc26c" 1895 "3ff1c93529ab4ee6fcf00acf29bbaba934a4014ce2625e0806601c55e6ce70d7" 1896 "121fd82f0904f335c5c7ba07dc6e6adf7582c92f7f255072203ea85844b4fe54" 1897 "817476a20bb742710ffc42750361be94332d0fc721b192309acfa70da43db6ae" 1898 "1d0f0bbe8a3250966a4532b36728162073c9eb3e119ea4c1c187c775dbb25a5d" 1899 "d883e3f65706a5fca897cdc4a8aa7b68ba3f57940c72f3a3396c417e758ba071" 1900 "95be4afba325237c0e2738a74d96fd1350fb623cb2ad40ea8b1e070cf398b98c" 1901 "2865ea40225b81f031f2b405409ca01dc5d9903d3d8e1d6381fbe7ccfc8f3dab" 1902 "eadafd7c976c0ba84a936f78ff7df0f112c089ba88f82bed7f9a6e31a91e5fee" 1903 "f675755454b948de22695660b243b9eca3bcc89608f83d2baa1d73dd6b8bd4f9" 1904 "b995ed9cb0f1edc6e98a49ed841b506c1bf59b43f4b3457a376bbff116c1a4f6" 1905 "07cc62381fc5c19953c68f300c1b51198d40784d812d25810ba404862f04b680" 1906 "6039a074f612ad8b84e0941ba23c915c3e7162c225fbecffdb7dc1ab559b2b54" 1907 "32fe8a498c32e918d8e7e33254ff75077f648827705e987f4d90fba971e78e1a" 1908 "6896b4d775c7359dc950f1e964fa04621aacf3c0988969490f4c72c54caf79e8" 1909 "481053cc0a27ffcd3580aabf9ef1268d498d8a18bd70e9b8402e011753bb7dc7" 1910 "e856c00d988fca924ee7cf61979c38cda8a872e4cc4fbdc90c23a0ded71eb944" 1911 "bb816ab22d9a4380e3e9d1cec818165c2fba6c5d51dcbf452c0cb1779a384937" 1912 "64d695370e13a301eca7be68d4112d2177381514efbb36fe08fc5bc2970301b8" 1913 "06f8e5a57a780e894d5276e2025bb775b6d1861e33c54ab6e3eb72947fbe6f91" 1914 "8174ce24eb4682efbb3c4f01233dc7ce9ef44792e9e876bb03e6751b3d559047" 1915 "d045127d976aa042fc55c690c9048e200065e7b7de19d9353aa9ac9b3e7611f0" 1916 "d1c42d069a300455ca1f7420a352bace89215e705106927510c11b3b1c1486d9" 1917 "f3ab006d2de2ee2c94574f760ce8c246bca229f98c66f06042b14f1fff9a16c0" 1918 "1550237e16d108ce5597299b1eb406a9ee505a29a6e0fa526b3e6beafd336aea" 1919 "138b2f31971586f67c5ffffbd6826d1c75666038c43d0bdff4edfc294e064a49" 1920 "2eed43e2dc78d00abc4e85edcd9563b8251b66f57b0f4b6d17f5a3f35c87c488" 1921 "dbeeb84fd720286197c2dec8290eccf3a313747de285b9cd3548e90cf81b3838" 1922 "3ffcc8c2a7f582feb369d05cb96b9b224d05902b3e39e5b96536032e9dddeb9b" 1923 "9d4f40a9c8f544ca37cf8d39d7c8c6a33880e9184ed017bd642db9590759bd10" 1924 "7362048ede5c0257feecc4984584592c566f37fba8469c064015339fb4f03023" 1925 "56ece37fd3655aae2bfc989b9b4c1384efc3503c8866db901802cb36eda9fb00")) 1926 1927 def testArgon2(self): 1928 # A few tests of my own of Argon2, derived from the reference 1929 # implementation. 1930 pwd = b"password" 1931 salt = b"salt of at least 16 bytes" 1932 secret = b"secret" 1933 assoc = b"associated data" 1934 1935 # Smallest memory (8Kbyte) and parallelism (1) parameters the 1936 # reference implementation will accept, but lots of passes 1937 self.assertEqualBin( 1938 argon2('i', 8, 16, 1, 24, pwd, salt, secret, assoc), unhex( 1939 "314da280240a3ca1eedd1f1db417a76eb0741e7df64b8cdf")) 1940 self.assertEqualBin( 1941 argon2('d', 8, 16, 1, 24, pwd, salt, secret, assoc), unhex( 1942 "9cc961cf43e0f86c2d4e202b816dc5bc5b2177e68faa0b08")) 1943 self.assertEqualBin( 1944 argon2('id', 8, 16, 1, 24, pwd, salt, secret, assoc), unhex( 1945 "6cd6c490c582fa597721d772d4e3de166987792491b48c51")) 1946 1947 # Test a memory cost value that isn't a power of 2. This 1948 # checks a wraparound case during the conversion of J1 to a 1949 # block index, and is a regression test for a bug that nearly 1950 # got past me during original development. 1951 self.assertEqualBin( 1952 argon2('i', 104, 16, 2, 24, pwd, salt, secret, assoc), unhex( 1953 "a561963623f1073c9aa8caecdb600c73ffc6de677ba8d97c")) 1954 self.assertEqualBin( 1955 argon2('d', 104, 16, 2, 24, pwd, salt, secret, assoc), unhex( 1956 "a9014db7f1d468fb25b88fa7fc0deac0f2e7f27e25d2cf6e")) 1957 self.assertEqualBin( 1958 argon2('id', 104, 16, 2, 24, pwd, salt, secret, assoc), unhex( 1959 "64f3212b1e7725ffcf9ae2d1753d63e763bcd6970061a435")) 1960 1961 # Larger parameters that should exercise the pseudorandom 1962 # block indexing reasonably thoroughly. Also generate plenty 1963 # of output data. 1964 self.assertEqualBin( 1965 argon2('i', 1024, 5, 16, 77, pwd, salt, secret, assoc), unhex( 1966 "b008a685ff57730fad0e6f3ef3b9189282c0d9b05303675f43b5f3054724" 1967 "733fcbe8e2639cc2c930535b31b723339041bcd703bf2483455acf86c0e6" 1968 "9ed88c545ad40f1f2068855e4d61e99407")) 1969 self.assertEqualBin( 1970 argon2('d', 1024, 5, 16, 111, pwd, salt, secret, assoc), unhex( 1971 "399ffbcd720c47745b9deb391ed0de7d5e0ffe53aef9f8ef7a7918cfa212" 1972 "53df8cc577affbd5e0c0f8bf6d93c11b2f63973f8fc8f89dccd832fc587e" 1973 "5d61717be6e88ca33eef5d1e168c028bae632a2a723c6c83f8e755f39171" 1974 "5eda1c77c8e2fe06fbdd4e56d35262587e7df73cd7")) 1975 self.assertEqualBin( 1976 argon2('id', 1024, 5, 16, 123, pwd, salt, secret, assoc), unhex( 1977 "6636807289cb9b9c032f48dcc31ffed1de4ca6c1b97e1ce768d690486341" 1978 "2ac84b39d568a81dd01d9ee3ceec6cc23441d95e6abeb4a2024f1f540d56" 1979 "9b799277c4037ddc7195ba783c9158a901adc7d4a5df8357b34a3869e5d6" 1980 "aeae2a21201eef5e347de22c922192e8f46274b0c9d33e965155a91e7686" 1981 "9d530e")) 1982 1983 def testRSAVerify(self): 1984 def blobs(n, e, d, p, q, iqmp): 1985 pubblob = ssh_string(b"ssh-rsa") + ssh2_mpint(e) + ssh2_mpint(n) 1986 privblob = (ssh2_mpint(d) + ssh2_mpint(p) + 1987 ssh2_mpint(q) + ssh2_mpint(iqmp)) 1988 return pubblob, privblob 1989 1990 def failure_test(*args): 1991 pubblob, privblob = blobs(*args) 1992 key = ssh_key_new_priv('rsa', pubblob, privblob) 1993 self.assertEqual(key, None) 1994 1995 def success_test(*args): 1996 pubblob, privblob = blobs(*args) 1997 key = ssh_key_new_priv('rsa', pubblob, privblob) 1998 self.assertNotEqual(key, None) 1999 2000 # Parameters for a (trivially small) test key. 2001 n = 0xb5d545a2f6423eabd55ffede53e21628d5d4491541482e10676d9d6f2783b9a5 2002 e = 0x25 2003 d = 0x6733db6a546ac99fcc21ba2b28b0c077156e8a705976205a955c6d9cef98f419 2004 p = 0xe30ebd7348bf10dca72b36f2724dafa7 2005 q = 0xcd02c87a7f7c08c4e9dc80c9b9bad5d3 2006 iqmp = 0x60a129b30db9227910efe1608976c513 2007 2008 # Check the test key makes sense unmodified. 2009 success_test(n, e, d, p, q, iqmp) 2010 2011 # Try modifying the values one by one to ensure they are 2012 # rejected, except iqmp, which sshrsa.c regenerates anyway so 2013 # it won't matter at all. 2014 failure_test(n+1, e, d, p, q, iqmp) 2015 failure_test(n, e+1, d, p, q, iqmp) 2016 failure_test(n, e, d+1, p, q, iqmp) 2017 failure_test(n, e, d, p+1, q, iqmp) 2018 failure_test(n, e, d, p, q+1, iqmp) 2019 success_test(n, e, d, p, q, iqmp+1) 2020 2021 # The key should also be accepted with p,q reversed. (Again, 2022 # iqmp gets regenerated, so it won't matter if that's wrong.) 2023 success_test(n, e, d, q, p, iqmp) 2024 2025 # Replace each of p and q with 0, and with 1. These should 2026 # still fail validation (obviously), but the point is that the 2027 # validator should also avoid trying to divide by zero in the 2028 # process. 2029 failure_test(n, e, d, 0, q, iqmp) 2030 failure_test(n, e, d, p, 0, iqmp) 2031 failure_test(n, e, d, 1, q, iqmp) 2032 failure_test(n, e, d, p, 1, iqmp) 2033 2034 def testKeyMethods(self): 2035 # Exercise all the methods of the ssh_key trait on all key 2036 # types, and ensure that they're consistent with each other. 2037 # No particular test is done on the rightness of the 2038 # signatures by any objective standard, only that the output 2039 # from our signing method can be verified by the corresponding 2040 # verification method. 2041 # 2042 # However, we do include the expected signature text in each 2043 # case, which checks determinism in the sense of being 2044 # independent of any random numbers, and also in the sense of 2045 # tomorrow's change to the code not having accidentally 2046 # changed the behaviour. 2047 2048 test_message = b"Message to be signed by crypt.testKeyMethods\n" 2049 2050 test_keys = [ 2051 ('ed25519', 'AAAAC3NzaC1lZDI1NTE5AAAAIM7jupzef6CD0ps2JYxJp9IlwY49oorOseV5z5JFDFKn', 'AAAAIAf4/WRtypofgdNF2vbZOUFE1h4hvjw4tkGJZyOzI7c3', 255, b'0xf4d6e7f6f4479c23f0764ef43cea1711dbfe02aa2b5a32ff925c7c1fbf0f0db,0x27520c4592cf79e5b1ce8aa23d8ec125d2a7498c25369bd283a07fde9cbae3ce', [(0, 'AAAAC3NzaC1lZDI1NTE5AAAAQN73EqfyA4WneqDhgZ98TlRj9V5Wg8zCrMxTLJN1UtyfAnPUJDtfG/U0vOsP8PrnQxd41DDDnxrAXuqJz8rOagc=')]), 2052 ('ed448', 'AAAACXNzaC1lZDQ0OAAAADnRI0CQDym5IqUidLNDcSdHe54bYEwqjpjBlab8uKGoe6FRqqejha7+5U/VAHy7BmE23+ju26O9XgA=', 'AAAAObP9klqyiJSJsdFJf+xwZQdkbZGUqXE07K6e5plfRTGjYYkyWJFUNFH4jzIn9xH1TX9z9EGycPaXAA==', 448, b'0x4bf4a2b6586c60d8cdb52c2b45b897f6d2224bc37987489c0d70febb449e8c82964ed5785827be808e44d31dd31e6ff7c99f43e49f419928,0x5ebda3dbeee8df366106bb7c00d54fe5feae85a3a7aa51a17ba8a1b8fca695c1988e2a4c601b9e7b47277143b37422a522b9290f904023d1', [(0, 'AAAACXNzaC1lZDQ0OAAAAHLkSVioGMvLesZp3Tn+Z/sSK0Hl7RHsHP4q9flLzTpZG5h6JDH3VmZBEjTJ6iOLaa0v4FoNt0ng4wAB53WrlQC4h3iAusoGXnPMAKJLmqzplKOCi8HKXk8Xl8fsXbaoyhatv1OZpwJcffmh1x+x+LSgNQA=')]), 2053 ('p256', 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHkYQ0sQoq5LbJI1VMWhw3bV43TSYi3WVpqIgKcBKK91TcFFlAMZgceOHQ0xAFYcSczIttLvFu+xkcLXrRd4N7Q=', 'AAAAIQCV/1VqiCsHZm/n+bq7lHEHlyy7KFgZBEbzqYaWtbx48Q==', 256, b'nistp256,0x7918434b10a2ae4b6c923554c5a1c376d5e374d2622dd6569a8880a70128af75,0x4dc14594031981c78e1d0d3100561c49ccc8b6d2ef16efb191c2d7ad177837b4', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIAryzHDGi/TcCnbdxZkIYR5EGR6SNYXr/HlQRF8le+/IAAAAIERfzn6eHuBbqWIop2qL8S7DWRB3lenN1iyL10xYQPKw')]), 2054 ('p384', 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMYK8PUtfAlJwKaBTIGEuCzH0vqOMa4UbcjrBbTbkGVSUnfo+nuC80NCdj9JJMs1jvfF8GzKLc5z8H3nZyM741/BUFjV7rEHsQFDek4KyWvKkEgKiTlZid19VukNo1q2Hg==', 'AAAAMGsfTmdB4zHdbiQ2euTSdzM6UKEOnrVjMAWwHEYvmG5qUOcBnn62fJDRJy67L+QGdg==', 384, b'nistp384,0xc60af0f52d7c0949c0a6814c8184b82cc7d2fa8e31ae146dc8eb05b4db9065525277e8fa7b82f34342763f4924cb358e,0xf7c5f06cca2dce73f07de767233be35fc15058d5eeb107b101437a4e0ac96bca90480a89395989dd7d56e90da35ab61e', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAABpAAAAMDmHrtXCADzLvkkWG/duBAHlf6B1mVvdt6F0uzXfsf8Yub8WXNUNVnYq6ovrWPzLggAAADEA9izzwoUuFcXYRJeKcRLZEGMmSDDPzUZb7oZR0UgD1jsMQXs8UfpO31Qur/FDSCRK')]), 2055 ('p521', 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFrGthlKM152vu2Ghk+R7iO9/M6e+hTehNZ6+FBwof4HPkPB2/HHXj5+w5ynWyUrWiX5TI2riuJEIrJErcRH5LglADnJDX2w4yrKZ+wDHSz9lwh9p2F+B5R952es6gX3RJRkGA+qhKpKup8gKx78RMbleX8wgRtIu+4YMUnKb1edREiRg==', 'AAAAQgFh7VNJFUljWhhyAEiL0z+UPs/QggcMTd3Vv2aKDeBdCRl5di8r+BMm39L7bRzxRMEtW5NSKlDtE8MFEGdIE9khsw==', 521, b'nistp521,0x16b1ad86528cd79dafbb61a193e47b88ef7f33a7be8537a1359ebe141c287f81cf90f076fc71d78f9fb0e729d6c94ad6897e53236ae2b89108ac912b7111f92e094,0xe72435f6c38cab299fb00c74b3f65c21f69d85f81e51f79d9eb3a817dd125190603eaa12a92aea7c80ac7bf1131b95e5fcc2046d22efb860c52729bd5e75112246', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAACMAAAAQgCLgvftvwM3CUaigrW0yzmCHoYjC6GLtO+6S91itqpgMEtWPNlaTZH6QQqkgscijWdXx98dDkQao/gcAKVmOZKPXgAAAEIB1PIrsDF1y6poJ/czqujB7NSUWt31v+c2t6UA8m2gTA1ARuVJ9XBGLMdceOTB00Hi9psC2RYFLpaWREOGCeDa6ow=')]), 2056 ('dsa', 'AAAAB3NzaC1kc3MAAABhAJyWZzjVddGdyc5JPu/WPrC07vKRAmlqO6TUi49ah96iRcM7/D1aRMVAdYBepQ2mf1fsQTmvoC9KgQa79nN3kHhz0voQBKOuKI1ZAodfVOgpP4xmcXgjaA73Vjz22n4newAAABUA6l7/vIveaiA33YYv+SKcKLQaA8cAAABgbErc8QLw/WDz7mhVRZrU+9x3Tfs68j3eW+B/d7Rz1ZCqMYDk7r/F8dlBdQlYhpQvhuSBgzoFa0+qPvSSxPmutgb94wNqhHlVIUb9ZOJNloNr2lXiPP//Wu51TxXAEvAAAAAAYQCcQ9mufXtZa5RyfwT4NuLivdsidP4HRoLXdlnppfFAbNdbhxE0Us8WZt+a/443bwKnYxgif8dgxv5UROnWTngWu0jbJHpaDcTc9lRyTeSUiZZK312s/Sl7qDk3/Du7RUI=', 'AAAAFGx3ft7G8AQzFsjhle7PWardUXh3', 768, b'0x9c966738d575d19dc9ce493eefd63eb0b4eef29102696a3ba4d48b8f5a87dea245c33bfc3d5a44c54075805ea50da67f57ec4139afa02f4a8106bbf67377907873d2fa1004a3ae288d5902875f54e8293f8c66717823680ef7563cf6da7e277b,0xea5effbc8bde6a2037dd862ff9229c28b41a03c7,0x6c4adcf102f0fd60f3ee6855459ad4fbdc774dfb3af23dde5be07f77b473d590aa3180e4eebfc5f1d94175095886942f86e481833a056b4faa3ef492c4f9aeb606fde3036a8479552146fd64e24d96836bda55e23cffff5aee754f15c012f000,0x9c43d9ae7d7b596b94727f04f836e2e2bddb2274fe074682d77659e9a5f1406cd75b87113452cf1666df9aff8e376f02a76318227fc760c6fe5444e9d64e7816bb48db247a5a0dc4dcf654724de49489964adf5dacfd297ba83937fc3bbb4542', [(0, 'AAAAB3NzaC1kc3MAAAAo0T2t6dr8Qr5DK2B0ETwUa3BhxMLPjLY0ZtlOACmP/kUt3JgByLv+3g==')]), 2057 ('rsa', 'AAAAB3NzaC1yc2EAAAABJQAAAGEA2ChX9+mQD/NULFkBrxLDI8d1PHgrInC2u11U4Grqu4oVzKvnFROo6DZeCu6sKhFJE5CnIL7evAthQ9hkXVHDhQ7xGVauzqyHGdIU4/pHRScAYWBv/PZOlNMrSoP/PP91', 'AAAAYCMNdgyGvWpez2EjMLSbQj0nQ3GW8jzvru3zdYwtA3hblNUU9QpWNxDmOMOApkwCzUgsdIPsBxctIeWT2h+v8sVOH+d66LCaNmNR0lp+dQ+iXM67hcGNuxJwRdMupD9ZbQAAADEA7XMrMAb4WuHaFafoTfGrf6Jhdy9Ozjqi1fStuld7Nj9JkoZluiL2dCwIrxqOjwU5AAAAMQDpC1gYiGVSPeDRILr2oxREtXWOsW+/ZZTfZNX7lvoufnp+qvwZPqvZnXQFHyZ8qB0AAAAwQE0wx8TPgcvRVEVv8Wt+o1NFlkJZayWD5hqpe/8AqUMZbqfg/aiso5mvecDLFgfV', 768, b'0x25,0xd82857f7e9900ff3542c5901af12c323c7753c782b2270b6bb5d54e06aeabb8a15ccabe71513a8e8365e0aeeac2a11491390a720bedebc0b6143d8645d51c3850ef11956aeceac8719d214e3fa4745270061606ffcf64e94d32b4a83ff3cff75', [(0, 'AAAAB3NzaC1yc2EAAABgrLSC4635RCsH1b3en58NqLsrH7PKRZyb3YmRasOyr8xIZMSlKZyxNg+kkn9OgBzbH9vChafzarfHyVwtJE2IMt3uwxTIWjwgwH19tc16k8YmNfDzujmB6OFOArmzKJgJ'), (2, 'AAAADHJzYS1zaGEyLTI1NgAAAGAJszr04BZlVBEdRLGOv1rTJwPiid/0I6/MycSH+noahvUH2wjrRhqDuv51F4nKYF5J9vBsEotTSrSF/cnLsliCdvVkEfmvhdcn/jx2LWF2OfjqETiYSc69Dde9UFmAPds='), (4, 'AAAADHJzYS1zaGEyLTUxMgAAAGBxfZ2m+WjvZ5YV5RFm0+w84CgHQ95EPndoAha0PCMc93AUHBmoHnezsJvEGuLovUm35w/0POmUNHI7HzM9PECwXrV0rO6N/HL/oFxJuDYmeqCpjMVmN8QXka+yxs2GEtA=')]), 2058 ] 2059 2060 for alg, pubb64, privb64, bits, cachestr, siglist in test_keys: 2061 # Decode the blobs in the above test data. 2062 pubblob = base64decode(pubb64.encode('ASCII')) 2063 privblob = base64decode(privb64.encode('ASCII')) 2064 2065 # Check the method that examines a public blob directly 2066 # and returns an integer showing the key size. 2067 self.assertEqual(ssh_key_public_bits(alg, pubblob), bits) 2068 2069 # Make a public-only and a full ssh_key object. 2070 pubkey = ssh_key_new_pub(alg, pubblob) 2071 privkey = ssh_key_new_priv(alg, pubblob, privblob) 2072 2073 # Test that they re-export the public and private key 2074 # blobs unchanged. 2075 self.assertEqual(ssh_key_public_blob(pubkey), pubblob) 2076 self.assertEqual(ssh_key_public_blob(privkey), pubblob) 2077 self.assertEqual(ssh_key_private_blob(privkey), privblob) 2078 2079 # Round-trip through the OpenSSH wire encoding used by the 2080 # agent protocol (and the newer OpenSSH key file format), 2081 # and check the result still exports all the same blobs. 2082 osshblob = ssh_key_openssh_blob(privkey) 2083 privkey2 = ssh_key_new_priv_openssh(alg, osshblob) 2084 self.assertEqual(ssh_key_public_blob(privkey2), pubblob) 2085 self.assertEqual(ssh_key_private_blob(privkey2), privblob) 2086 self.assertEqual(ssh_key_openssh_blob(privkey2), osshblob) 2087 2088 # Test that the string description used in the host key 2089 # cache is as expected. 2090 for key in [pubkey, privkey, privkey2]: 2091 self.assertEqual(ssh_key_cache_str(key), cachestr) 2092 2093 # Now test signatures, separately for each provided flags 2094 # value. 2095 for flags, sigb64 in siglist: 2096 # Decode the signature blob from the test data. 2097 sigblob = base64decode(sigb64.encode('ASCII')) 2098 2099 # Sign our test message, and check it produces exactly 2100 # the expected signature blob. 2101 # 2102 # We do this with both the original private key and 2103 # the one we round-tripped through OpenSSH wire 2104 # format, just in case that round trip made some kind 2105 # of a mess that didn't show up in the re-extraction 2106 # of the blobs. 2107 for key in [privkey, privkey2]: 2108 self.assertEqual(ssh_key_sign( 2109 key, test_message, flags), sigblob) 2110 2111 if flags != 0: 2112 # Currently we only support _generating_ 2113 # signatures with flags != 0, not verifying them. 2114 continue 2115 2116 # Check the signature verifies successfully, with all 2117 # three of the key objects we have. 2118 for key in [pubkey, privkey, privkey2]: 2119 self.assertTrue(ssh_key_verify(key, sigblob, test_message)) 2120 2121 # A crude check that at least _something_ doesn't 2122 # verify successfully: flip a bit of the signature 2123 # and expect it to fail. 2124 # 2125 # We do this twice, at the 1/3 and 2/3 points along 2126 # the signature's length, so that in the case of 2127 # signatures in two parts (DSA-like) we try perturbing 2128 # both parts. Other than that, we don't do much to 2129 # make this a rigorous cryptographic test. 2130 for n, d in [(1,3),(2,3)]: 2131 sigbytes = list(sigblob) 2132 bit = 8 * len(sigbytes) * n // d 2133 sigbytes[bit // 8] ^= 1 << (bit % 8) 2134 badsig = bytes(sigbytes) 2135 for key in [pubkey, privkey, privkey2]: 2136 self.assertFalse(ssh_key_verify( 2137 key, badsig, test_message)) 2138 2139 def testPPKLoadSave(self): 2140 # Stability test of PPK load/save functions. 2141 input_clear_key = b"""\ 2142PuTTY-User-Key-File-3: ssh-ed25519 2143Encryption: none 2144Comment: ed25519-key-20200105 2145Public-Lines: 2 2146AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F 2147JH1W 2148Private-Lines: 1 2149AAAAIGvvIpl8jyqn8Xufkw6v3FnEGtXF3KWw55AP3/AGEBpY 2150Private-MAC: 816c84093fc4877e8411b8e5139c5ce35d8387a2630ff087214911d67417a54d 2151""" 2152 input_encrypted_key = b"""\ 2153PuTTY-User-Key-File-3: ssh-ed25519 2154Encryption: aes256-cbc 2155Comment: ed25519-key-20200105 2156Public-Lines: 2 2157AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F 2158JH1W 2159Key-Derivation: Argon2id 2160Argon2-Memory: 8192 2161Argon2-Passes: 13 2162Argon2-Parallelism: 1 2163Argon2-Salt: 37c3911bfefc8c1d11ec579627d2b3d9 2164Private-Lines: 1 2165amviz4sVUBN64jLO3gt4HGXJosUArghc4Soi7aVVLb2Tir5Baj0OQClorycuaPRd 2166Private-MAC: 6f5e588e475e55434106ec2c3569695b03f423228b44993a9e97d52ffe7be5a8 2167""" 2168 algorithm = b'ssh-ed25519' 2169 comment = b'ed25519-key-20200105' 2170 pp = b'test-passphrase' 2171 public_blob = unhex( 2172 '0000000b7373682d65643235353139000000207242b33387688f57ff218bb639' 2173 'f6d9fd213ba54f3100d5b5cb64ca6e85247d56') 2174 2175 self.assertEqual(ppk_encrypted_s(input_clear_key), (False, comment)) 2176 self.assertEqual(ppk_encrypted_s(input_encrypted_key), (True, comment)) 2177 self.assertEqual(ppk_encrypted_s("not a key file"), (False, None)) 2178 2179 self.assertEqual(ppk_loadpub_s(input_clear_key), 2180 (True, algorithm, public_blob, comment, None)) 2181 self.assertEqual(ppk_loadpub_s(input_encrypted_key), 2182 (True, algorithm, public_blob, comment, None)) 2183 self.assertEqual(ppk_loadpub_s("not a key file"), 2184 (False, None, b'', None, 2185 b'not a PuTTY SSH-2 private key')) 2186 2187 k1, c, e = ppk_load_s(input_clear_key, None) 2188 self.assertEqual((c, e), (comment, None)) 2189 k2, c, e = ppk_load_s(input_encrypted_key, pp) 2190 self.assertEqual((c, e), (comment, None)) 2191 privblob = ssh_key_private_blob(k1) 2192 self.assertEqual(ssh_key_private_blob(k2), privblob) 2193 2194 salt = unhex('37c3911bfefc8c1d11ec579627d2b3d9') 2195 with queued_specific_random_data(salt): 2196 self.assertEqual(ppk_save_sb(k1, comment, None, 2197 3, 'id', 8192, 13, 1), 2198 input_clear_key) 2199 with queued_specific_random_data(salt): 2200 self.assertEqual(ppk_save_sb(k2, comment, None, 2201 3, 'id', 8192, 13, 1), 2202 input_clear_key) 2203 2204 with queued_specific_random_data(salt): 2205 self.assertEqual(ppk_save_sb(k1, comment, pp, 2206 3, 'id', 8192, 13, 1), 2207 input_encrypted_key) 2208 with queued_specific_random_data(salt): 2209 self.assertEqual(ppk_save_sb(k2, comment, pp, 2210 3, 'id', 8192, 13, 1), 2211 input_encrypted_key) 2212 2213 # And check we can still handle v2 key files. 2214 v2_clear_key = b"""\ 2215PuTTY-User-Key-File-2: ssh-ed25519 2216Encryption: none 2217Comment: ed25519-key-20200105 2218Public-Lines: 2 2219AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F 2220JH1W 2221Private-Lines: 1 2222AAAAIGvvIpl8jyqn8Xufkw6v3FnEGtXF3KWw55AP3/AGEBpY 2223Private-MAC: 2a629acfcfbe28488a1ba9b6948c36406bc28422 2224""" 2225 v2_encrypted_key = b"""\ 2226PuTTY-User-Key-File-2: ssh-ed25519 2227Encryption: aes256-cbc 2228Comment: ed25519-key-20200105 2229Public-Lines: 2 2230AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F 2231JH1W 2232Private-Lines: 1 22334/jKlTgC652oa9HLVGrMjHZw7tj0sKRuZaJPOuLhGTvb25Jzpcqpbi+Uf+y+uo+Z 2234Private-MAC: 5b1f6f4cc43eb0060d2c3e181bc0129343adba2b 2235""" 2236 2237 self.assertEqual(ppk_encrypted_s(v2_clear_key), (False, comment)) 2238 self.assertEqual(ppk_encrypted_s(v2_encrypted_key), (True, comment)) 2239 self.assertEqual(ppk_encrypted_s("not a key file"), (False, None)) 2240 2241 self.assertEqual(ppk_loadpub_s(v2_clear_key), 2242 (True, algorithm, public_blob, comment, None)) 2243 self.assertEqual(ppk_loadpub_s(v2_encrypted_key), 2244 (True, algorithm, public_blob, comment, None)) 2245 self.assertEqual(ppk_loadpub_s("not a key file"), 2246 (False, None, b'', None, 2247 b'not a PuTTY SSH-2 private key')) 2248 2249 k1, c, e = ppk_load_s(v2_clear_key, None) 2250 self.assertEqual((c, e), (comment, None)) 2251 k2, c, e = ppk_load_s(v2_encrypted_key, pp) 2252 self.assertEqual((c, e), (comment, None)) 2253 self.assertEqual(ssh_key_private_blob(k1), privblob) 2254 self.assertEqual(ssh_key_private_blob(k2), privblob) 2255 2256 self.assertEqual(ppk_save_sb(k2, comment, None, 2257 2, 'id', 8192, 13, 1), 2258 v2_clear_key) 2259 self.assertEqual(ppk_save_sb(k1, comment, pp, 2260 2, 'id', 8192, 13, 1), 2261 v2_encrypted_key) 2262 2263 def testRSA1LoadSave(self): 2264 # Stability test of SSH-1 RSA key-file load/save functions. 2265 input_clear_key = unhex( 2266 "5353482050524956415445204B45592046494C4520464F524D415420312E310A" 2267 "000000000000000002000200BB115A85B741E84E3D940E690DF96A0CBFDC07CA" 2268 "70E51DA8234D211DE77341CEF40C214CAA5DCF68BE2127447FD6C84CCB17D057" 2269 "A74F2365B9D84A78906AEB51000625000000107273612D6B65792D3230323030" 2270 "313036208E208E0200929EE615C6FC4E4B29585E52570F984F2E97B3144AA5BD" 2271 "4C6EB2130999BB339305A21FFFA79442462A8397AF8CAC395A3A3827DE10457A" 2272 "1F1B277ABFB8C069C100FF55B1CAD69B3BD9E42456CF28B1A4B98130AFCE08B2" 2273 "8BCFFF5FFFED76C5D51E9F0100C5DE76889C62B1090A770AE68F087A19AB5126" 2274 "E60DF87710093A2AD57B3380FB0100F2068AC47ECB33BF8F13DF402BABF35EE7" 2275 "26BD32F7564E51502DF5C8F4888B2300000000") 2276 input_encrypted_key = unhex( 2277 "5353482050524956415445204b45592046494c4520464f524d415420312e310a" 2278 "000300000000000002000200bb115a85b741e84e3d940e690df96a0cbfdc07ca" 2279 "70e51da8234d211de77341cef40c214caa5dcf68be2127447fd6c84ccb17d057" 2280 "a74f2365b9d84a78906aeb51000625000000107273612d6b65792d3230323030" 2281 "3130363377f926e811a5f044c52714801ecdcf9dd572ee0a193c4f67e87ab2ce" 2282 "4569d0c5776fd6028909ed8b6d663bef15d207d3ef6307e7e21dbec56e8d8b4e" 2283 "894ded34df891bb29bae6b2b74805ac80f7304926abf01ae314dd69c64240761" 2284 "34f15d50c99f7573252993530ec9c4d5016dd1f5191730cda31a5d95d362628b" 2285 "2a26f4bb21840d01c8360e4a6ce216c4686d25b8699d45cf361663bb185e2c5e" 2286 "652012a1e0f9d6d19afbb28506f7775bfd8129") 2287 2288 comment = b'rsa-key-20200106' 2289 pp = b'test-passphrase' 2290 public_blob = unhex( 2291 "000002000006250200bb115a85b741e84e3d940e690df96a0cbfdc07ca70e51d" 2292 "a8234d211de77341cef40c214caa5dcf68be2127447fd6c84ccb17d057a74f23" 2293 "65b9d84a78906aeb51") 2294 2295 self.assertEqual(rsa1_encrypted_s(input_clear_key), (False, comment)) 2296 self.assertEqual(rsa1_encrypted_s(input_encrypted_key), 2297 (True, comment)) 2298 self.assertEqual(rsa1_encrypted_s("not a key file"), (False, None)) 2299 2300 self.assertEqual(rsa1_loadpub_s(input_clear_key), 2301 (1, public_blob, comment, None)) 2302 self.assertEqual(rsa1_loadpub_s(input_encrypted_key), 2303 (1, public_blob, comment, None)) 2304 2305 k1 = rsa_new() 2306 status, c, e = rsa1_load_s(input_clear_key, k1, None) 2307 self.assertEqual((status, c, e), (1, comment, None)) 2308 k2 = rsa_new() 2309 status, c, e = rsa1_load_s(input_clear_key, k2, None) 2310 self.assertEqual((status, c, e), (1, comment, None)) 2311 2312 with queued_specific_random_data(unhex("208e")): 2313 self.assertEqual(rsa1_save_sb(k1, comment, None), input_clear_key) 2314 with queued_specific_random_data(unhex("208e")): 2315 self.assertEqual(rsa1_save_sb(k2, comment, None), input_clear_key) 2316 2317 with queued_specific_random_data(unhex("99f3")): 2318 self.assertEqual(rsa1_save_sb(k1, comment, pp), 2319 input_encrypted_key) 2320 with queued_specific_random_data(unhex("99f3")): 2321 self.assertEqual(rsa1_save_sb(k2, comment, pp), 2322 input_encrypted_key) 2323 2324class standard_test_vectors(MyTestBase): 2325 def testAES(self): 2326 def vector(cipher, key, plaintext, ciphertext): 2327 for suffix in "hw", "sw": 2328 c = ssh_cipher_new("{}_{}".format(cipher, suffix)) 2329 if c is None: return # skip test if HW AES not available 2330 ssh_cipher_setkey(c, key) 2331 2332 # The AES test vectors are implicitly in ECB mode, 2333 # because they're testing the cipher primitive rather 2334 # than any mode layered on top of it. We fake this by 2335 # using PuTTY's CBC setting, and clearing the IV to 2336 # all zeroes before each operation. 2337 2338 ssh_cipher_setiv(c, b'\x00' * 16) 2339 self.assertEqualBin( 2340 ssh_cipher_encrypt(c, plaintext), ciphertext) 2341 2342 ssh_cipher_setiv(c, b'\x00' * 16) 2343 self.assertEqualBin( 2344 ssh_cipher_decrypt(c, ciphertext), plaintext) 2345 2346 # The test vector from FIPS 197 appendix B. (This is also the 2347 # same key whose key setup phase is shown in detail in 2348 # appendix A.) 2349 vector('aes128_cbc', 2350 unhex('2b7e151628aed2a6abf7158809cf4f3c'), 2351 unhex('3243f6a8885a308d313198a2e0370734'), 2352 unhex('3925841d02dc09fbdc118597196a0b32')) 2353 2354 # The test vectors from FIPS 197 appendix C: the key bytes go 2355 # 00 01 02 03 ... for as long as needed, and the plaintext 2356 # bytes go 00 11 22 33 ... FF. 2357 fullkey = struct.pack("B"*32, *range(32)) 2358 plaintext = struct.pack("B"*16, *[0x11*i for i in range(16)]) 2359 vector('aes128_cbc', fullkey[:16], plaintext, 2360 unhex('69c4e0d86a7b0430d8cdb78070b4c55a')) 2361 vector('aes192_cbc', fullkey[:24], plaintext, 2362 unhex('dda97ca4864cdfe06eaf70a0ec0d7191')) 2363 vector('aes256_cbc', fullkey[:32], plaintext, 2364 unhex('8ea2b7ca516745bfeafc49904b496089')) 2365 2366 def testDES(self): 2367 c = ssh_cipher_new("des_cbc") 2368 def vector(key, plaintext, ciphertext): 2369 key = unhex(key) 2370 plaintext = unhex(plaintext) 2371 ciphertext = unhex(ciphertext) 2372 2373 # Similarly to above, we fake DES ECB by using DES CBC and 2374 # resetting the IV to zero all the time 2375 ssh_cipher_setkey(c, key) 2376 ssh_cipher_setiv(c, b'\x00' * 8) 2377 self.assertEqualBin(ssh_cipher_encrypt(c, plaintext), ciphertext) 2378 ssh_cipher_setiv(c, b'\x00' * 8) 2379 self.assertEqualBin(ssh_cipher_decrypt(c, ciphertext), plaintext) 2380 2381 # Source: FIPS SP PUB 500-20 2382 2383 # 'Initial permutation and expansion tests': key fixed at 8 2384 # copies of the byte 01, but ciphertext and plaintext in turn 2385 # run through all possible values with exactly 1 bit set. 2386 # Expected plaintexts and ciphertexts (respectively) listed in 2387 # the arrays below. 2388 ipe_key = '01' * 8 2389 ipe_plaintexts = [ 2390'166B40B44ABA4BD6', '06E7EA22CE92708F', 'D2FD8867D50D2DFE', 'CC083F1E6D9E85F6', 2391'5B711BC4CEEBF2EE', '0953E2258E8E90A1', 'E07C30D7E4E26E12', '2FBC291A570DB5C4', 2392'DD7C0BBD61FAFD54', '48221B9937748A23', 'E643D78090CA4207', '8405D1ABE24FB942', 2393'CE332329248F3228', '1D1CA853AE7C0C5F', '5D86CB23639DBEA9', '1029D55E880EC2D0', 2394'8DD45A2DDF90796C', 'CAFFC6AC4542DE31', 'EA51D3975595B86B', '8B54536F2F3E64A8', 2395'866ECEDD8072BB0E', '79E90DBC98F92CCA', 'AB6A20C0620D1C6F', '25EB5FC3F8CF0621', 2396'4D49DB1532919C9F', '814EEB3B91D90726', '5E0905517BB59BCF', 'CA3A2B036DBC8502', 2397'FA0752B07D9C4AB8', 'B160E4680F6C696F', 'DF98C8276F54B04B', 'E943D7568AEC0C5C', 2398'AEB5F5EDE22D1A36', 'E428581186EC8F46', 'E1652C6B138C64A5', 'D106FF0BED5255D7', 2399'9D64555A9A10B852', 'F02B263B328E2B60', '64FEED9C724C2FAF', '750D079407521363', 2400'FBE00A8A1EF8AD72', 'A484C3AD38DC9C19', '12A9F5817FF2D65D', 'E7FCE22557D23C97', 2401'329A8ED523D71AEC', 'E19E275D846A1298', '889DE068A16F0BE6', '2B9F982F20037FA9', 2402'F356834379D165CD', 'ECBFE3BD3F591A5E', 'E6D5F82752AD63D1', 'ADD0CC8D6E5DEBA1', 2403'F15D0F286B65BD28', 'B8061B7ECD9A21E5', '424250B37C3DD951', 'D9031B0271BD5A0A', 2404'0D9F279BA5D87260', '6CC5DEFAAF04512F', '55579380D77138EF', '20B9E767B2FB1456', 2405'4BD388FF6CD81D4F', '2E8653104F3834EA', 'DD7F121CA5015619', '95F8A5E5DD31D900', 2406 ] 2407 ipe_ciphertexts = [ 2408'166B40B44ABA4BD6', '06E7EA22CE92708F', 'D2FD8867D50D2DFE', 'CC083F1E6D9E85F6', 2409'5B711BC4CEEBF2EE', '0953E2258E8E90A1', 'E07C30D7E4E26E12', '2FBC291A570DB5C4', 2410'DD7C0BBD61FAFD54', '48221B9937748A23', 'E643D78090CA4207', '8405D1ABE24FB942', 2411'CE332329248F3228', '1D1CA853AE7C0C5F', '5D86CB23639DBEA9', '1029D55E880EC2D0', 2412'8DD45A2DDF90796C', 'CAFFC6AC4542DE31', 'EA51D3975595B86B', '8B54536F2F3E64A8', 2413'866ECEDD8072BB0E', '79E90DBC98F92CCA', 'AB6A20C0620D1C6F', '25EB5FC3F8CF0621', 2414'4D49DB1532919C9F', '814EEB3B91D90726', '5E0905517BB59BCF', 'CA3A2B036DBC8502', 2415'FA0752B07D9C4AB8', 'B160E4680F6C696F', 'DF98C8276F54B04B', 'E943D7568AEC0C5C', 2416'AEB5F5EDE22D1A36', 'E428581186EC8F46', 'E1652C6B138C64A5', 'D106FF0BED5255D7', 2417'9D64555A9A10B852', 'F02B263B328E2B60', '64FEED9C724C2FAF', '750D079407521363', 2418'FBE00A8A1EF8AD72', 'A484C3AD38DC9C19', '12A9F5817FF2D65D', 'E7FCE22557D23C97', 2419'329A8ED523D71AEC', 'E19E275D846A1298', '889DE068A16F0BE6', '2B9F982F20037FA9', 2420'F356834379D165CD', 'ECBFE3BD3F591A5E', 'E6D5F82752AD63D1', 'ADD0CC8D6E5DEBA1', 2421'F15D0F286B65BD28', 'B8061B7ECD9A21E5', '424250B37C3DD951', 'D9031B0271BD5A0A', 2422'0D9F279BA5D87260', '6CC5DEFAAF04512F', '55579380D77138EF', '20B9E767B2FB1456', 2423'4BD388FF6CD81D4F', '2E8653104F3834EA', 'DD7F121CA5015619', '95F8A5E5DD31D900', 2424 ] 2425 ipe_single_bits = ["{:016x}".format(1 << bit) for bit in range(64)] 2426 for plaintext, ciphertext in zip(ipe_plaintexts, ipe_single_bits): 2427 vector(ipe_key, plaintext, ciphertext) 2428 for plaintext, ciphertext in zip(ipe_single_bits, ipe_ciphertexts): 2429 vector(ipe_key, plaintext, ciphertext) 2430 2431 # 'Key permutation tests': plaintext fixed at all zeroes, key 2432 # is a succession of tweaks of the previous key made by 2433 # replacing each 01 byte in turn with one containing a 2434 # different single set bit (e.g. 01 20 01 01 01 01 01 01). 2435 # Expected ciphertexts listed. 2436 kp_ciphertexts = [ 2437'95A8D72813DAA94D', '0EEC1487DD8C26D5', '7AD16FFB79C45926', 'D3746294CA6A6CF3', 2438'809F5F873C1FD761', 'C02FAFFEC989D1FC', '4615AA1D33E72F10', '2055123350C00858', 2439'DF3B99D6577397C8', '31FE17369B5288C9', 'DFDD3CC64DAE1642', '178C83CE2B399D94', 2440'50F636324A9B7F80', 'A8468EE3BC18F06D', 'A2DC9E92FD3CDE92', 'CAC09F797D031287', 2441'90BA680B22AEB525', 'CE7A24F350E280B6', '882BFF0AA01A0B87', '25610288924511C2', 2442'C71516C29C75D170', '5199C29A52C9F059', 'C22F0A294A71F29F', 'EE371483714C02EA', 2443'A81FBD448F9E522F', '4F644C92E192DFED', '1AFA9A66A6DF92AE', 'B3C1CC715CB879D8', 2444'19D032E64AB0BD8B', '3CFAA7A7DC8720DC', 'B7265F7F447AC6F3', '9DB73B3C0D163F54', 2445'8181B65BABF4A975', '93C9B64042EAA240', '5570530829705592', '8638809E878787A0', 2446'41B9A79AF79AC208', '7A9BE42F2009A892', '29038D56BA6D2745', '5495C6ABF1E5DF51', 2447'AE13DBD561488933', '024D1FFA8904E389', 'D1399712F99BF02E', '14C1D7C1CFFEC79E', 2448'1DE5279DAE3BED6F', 'E941A33F85501303', 'DA99DBBC9A03F379', 'B7FC92F91D8E92E9', 2449'AE8E5CAA3CA04E85', '9CC62DF43B6EED74', 'D863DBB5C59A91A0', 'A1AB2190545B91D7', 2450'0875041E64C570F7', '5A594528BEBEF1CC', 'FCDB3291DE21F0C0', '869EFD7F9F265A09', 2451 ] 2452 kp_key_repl_bytes = ["{:02x}".format(0x80>>i) for i in range(7)] 2453 kp_keys = ['01'*j + b + '01'*(7-j) 2454 for j in range(8) for b in kp_key_repl_bytes] 2455 kp_plaintext = '0' * 16 2456 for key, ciphertext in zip(kp_keys, kp_ciphertexts): 2457 vector(key, kp_plaintext, ciphertext) 2458 2459 # 'Data permutation test': plaintext fixed at all zeroes, 2460 # pairs of key and expected ciphertext listed below. 2461 dp_keys_and_ciphertexts = [ 2462'1046913489980131:88D55E54F54C97B4', '1007103489988020:0C0CC00C83EA48FD', 2463'10071034C8980120:83BC8EF3A6570183', '1046103489988020:DF725DCAD94EA2E9', 2464'1086911519190101:E652B53B550BE8B0', '1086911519580101:AF527120C485CBB0', 2465'5107B01519580101:0F04CE393DB926D5', '1007B01519190101:C9F00FFC74079067', 2466'3107915498080101:7CFD82A593252B4E', '3107919498080101:CB49A2F9E91363E3', 2467'10079115B9080140:00B588BE70D23F56', '3107911598080140:406A9A6AB43399AE', 2468'1007D01589980101:6CB773611DCA9ADA', '9107911589980101:67FD21C17DBB5D70', 2469'9107D01589190101:9592CB4110430787', '1007D01598980120:A6B7FF68A318DDD3', 2470'1007940498190101:4D102196C914CA16', '0107910491190401:2DFA9F4573594965', 2471'0107910491190101:B46604816C0E0774', '0107940491190401:6E7E6221A4F34E87', 2472'19079210981A0101:AA85E74643233199', '1007911998190801:2E5A19DB4D1962D6', 2473'10079119981A0801:23A866A809D30894', '1007921098190101:D812D961F017D320', 2474'100791159819010B:055605816E58608F', '1004801598190101:ABD88E8B1B7716F1', 2475'1004801598190102:537AC95BE69DA1E1', '1004801598190108:AED0F6AE3C25CDD8', 2476'1002911498100104:B3E35A5EE53E7B8D', '1002911598190104:61C79C71921A2EF8', 2477'1002911598100201:E2F5728F0995013C', '1002911698100101:1AEAC39A61F0A464', 2478 ] 2479 dp_plaintext = '0' * 16 2480 for key_and_ciphertext in dp_keys_and_ciphertexts: 2481 key, ciphertext = key_and_ciphertext.split(":") 2482 vector(key, dp_plaintext, ciphertext) 2483 2484 # Tests intended to select every entry in every S-box. Full 2485 # arbitrary triples (key, plaintext, ciphertext). 2486 sb_complete_tests = [ 2487 '7CA110454A1A6E57:01A1D6D039776742:690F5B0D9A26939B', 2488 '0131D9619DC1376E:5CD54CA83DEF57DA:7A389D10354BD271', 2489 '07A1133E4A0B2686:0248D43806F67172:868EBB51CAB4599A', 2490 '3849674C2602319E:51454B582DDF440A:7178876E01F19B2A', 2491 '04B915BA43FEB5B6:42FD443059577FA2:AF37FB421F8C4095', 2492 '0113B970FD34F2CE:059B5E0851CF143A:86A560F10EC6D85B', 2493 '0170F175468FB5E6:0756D8E0774761D2:0CD3DA020021DC09', 2494 '43297FAD38E373FE:762514B829BF486A:EA676B2CB7DB2B7A', 2495 '07A7137045DA2A16:3BDD119049372802:DFD64A815CAF1A0F', 2496 '04689104C2FD3B2F:26955F6835AF609A:5C513C9C4886C088', 2497 '37D06BB516CB7546:164D5E404F275232:0A2AEEAE3FF4AB77', 2498 '1F08260D1AC2465E:6B056E18759F5CCA:EF1BF03E5DFA575A', 2499 '584023641ABA6176:004BD6EF09176062:88BF0DB6D70DEE56', 2500 '025816164629B007:480D39006EE762F2:A1F9915541020B56', 2501 '49793EBC79B3258F:437540C8698F3CFA:6FBF1CAFCFFD0556', 2502 '4FB05E1515AB73A7:072D43A077075292:2F22E49BAB7CA1AC', 2503 '49E95D6D4CA229BF:02FE55778117F12A:5A6B612CC26CCE4A', 2504 '018310DC409B26D6:1D9D5C5018F728C2:5F4C038ED12B2E41', 2505 '1C587F1C13924FEF:305532286D6F295A:63FAC0D034D9F793', 2506 ] 2507 for test in sb_complete_tests: 2508 key, plaintext, ciphertext = test.split(":") 2509 vector(key, plaintext, ciphertext) 2510 2511 def testMD5(self): 2512 MD5 = lambda s: hash_str('md5', s) 2513 2514 # The test vectors from RFC 1321 section A.5. 2515 self.assertEqualBin(MD5(""), 2516 unhex('d41d8cd98f00b204e9800998ecf8427e')) 2517 self.assertEqualBin(MD5("a"), 2518 unhex('0cc175b9c0f1b6a831c399e269772661')) 2519 self.assertEqualBin(MD5("abc"), 2520 unhex('900150983cd24fb0d6963f7d28e17f72')) 2521 self.assertEqualBin(MD5("message digest"), 2522 unhex('f96b697d7cb7938d525a2f31aaf161d0')) 2523 self.assertEqualBin(MD5("abcdefghijklmnopqrstuvwxyz"), 2524 unhex('c3fcd3d76192e4007dfb496cca67e13b')) 2525 self.assertEqualBin(MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZ" 2526 "abcdefghijklmnopqrstuvwxyz0123456789"), 2527 unhex('d174ab98d277d9f5a5611c2c9f419d9f')) 2528 self.assertEqualBin(MD5("1234567890123456789012345678901234567890" 2529 "1234567890123456789012345678901234567890"), 2530 unhex('57edf4a22be3c955ac49da2e2107b67a')) 2531 2532 def testHmacMD5(self): 2533 # The test vectors from the RFC 2104 Appendix. 2534 self.assertEqualBin(mac_str('hmac_md5', unhex('0b'*16), "Hi There"), 2535 unhex('9294727a3638bb1c13f48ef8158bfc9d')) 2536 self.assertEqualBin(mac_str('hmac_md5', "Jefe", 2537 "what do ya want for nothing?"), 2538 unhex('750c783e6ab0b503eaa86e310a5db738')) 2539 self.assertEqualBin(mac_str('hmac_md5', unhex('aa'*16), unhex('dd'*50)), 2540 unhex('56be34521d144c88dbb8c733f0e8b3f6')) 2541 2542 def testSHA1(self): 2543 for hashname in ['sha1_sw', 'sha1_hw']: 2544 if ssh_hash_new(hashname) is None: 2545 continue # skip testing of unavailable HW implementation 2546 2547 # Test cases from RFC 6234 section 8.5, omitting the ones 2548 # whose input is not a multiple of 8 bits 2549 self.assertEqualBin(hash_str(hashname, "abc"), unhex( 2550 "a9993e364706816aba3e25717850c26c9cd0d89d")) 2551 self.assertEqualBin(hash_str(hashname, 2552 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), 2553 unhex("84983e441c3bd26ebaae4aa1f95129e5e54670f1")) 2554 self.assertEqualBin(hash_str_iter(hashname, 2555 ("a" * 1000 for _ in range(1000))), unhex( 2556 "34aa973cd4c4daa4f61eeb2bdbad27316534016f")) 2557 self.assertEqualBin(hash_str(hashname, 2558 "01234567012345670123456701234567" * 20), unhex( 2559 "dea356a2cddd90c7a7ecedc5ebb563934f460452")) 2560 self.assertEqualBin(hash_str(hashname, b"\x5e"), unhex( 2561 "5e6f80a34a9798cafc6a5db96cc57ba4c4db59c2")) 2562 self.assertEqualBin(hash_str(hashname, 2563 unhex("9a7dfdf1ecead06ed646aa55fe757146")), unhex( 2564 "82abff6605dbe1c17def12a394fa22a82b544a35")) 2565 self.assertEqualBin(hash_str(hashname, unhex( 2566 "f78f92141bcd170ae89b4fba15a1d59f" 2567 "3fd84d223c9251bdacbbae61d05ed115" 2568 "a06a7ce117b7beead24421ded9c32592" 2569 "bd57edeae39c39fa1fe8946a84d0cf1f" 2570 "7beead1713e2e0959897347f67c80b04" 2571 "00c209815d6b10a683836fd5562a56ca" 2572 "b1a28e81b6576654631cf16566b86e3b" 2573 "33a108b05307c00aff14a768ed735060" 2574 "6a0f85e6a91d396f5b5cbe577f9b3880" 2575 "7c7d523d6d792f6ebc24a4ecf2b3a427" 2576 "cdbbfb")), unhex( 2577 "cb0082c8f197d260991ba6a460e76e202bad27b3")) 2578 2579 def testSHA256(self): 2580 for hashname in ['sha256_sw', 'sha256_hw']: 2581 if ssh_hash_new(hashname) is None: 2582 continue # skip testing of unavailable HW implementation 2583 2584 # Test cases from RFC 6234 section 8.5, omitting the ones 2585 # whose input is not a multiple of 8 bits 2586 self.assertEqualBin(hash_str(hashname, "abc"), 2587 unhex("ba7816bf8f01cfea414140de5dae2223" 2588 "b00361a396177a9cb410ff61f20015ad")) 2589 self.assertEqualBin(hash_str(hashname, 2590 "abcdbcdecdefdefgefghfghighijhijk""ijkljklmklmnlmnomnopnopq"), 2591 unhex("248d6a61d20638b8e5c026930c3e6039" 2592 "a33ce45964ff2167f6ecedd419db06c1")) 2593 self.assertEqualBin( 2594 hash_str_iter(hashname, ("a" * 1000 for _ in range(1000))), 2595 unhex("cdc76e5c9914fb9281a1c7e284d73e67" 2596 "f1809a48a497200e046d39ccc7112cd0")) 2597 self.assertEqualBin( 2598 hash_str(hashname, "01234567012345670123456701234567" * 20), 2599 unhex("594847328451bdfa85056225462cc1d8" 2600 "67d877fb388df0ce35f25ab5562bfbb5")) 2601 self.assertEqualBin(hash_str(hashname, b"\x19"), 2602 unhex("68aa2e2ee5dff96e3355e6c7ee373e3d" 2603 "6a4e17f75f9518d843709c0c9bc3e3d4")) 2604 self.assertEqualBin( 2605 hash_str(hashname, unhex("e3d72570dcdd787ce3887ab2cd684652")), 2606 unhex("175ee69b02ba9b58e2b0a5fd13819cea" 2607 "573f3940a94f825128cf4209beabb4e8")) 2608 self.assertEqualBin(hash_str(hashname, unhex( 2609 "8326754e2277372f4fc12b20527afef0" 2610 "4d8a056971b11ad57123a7c137760000" 2611 "d7bef6f3c1f7a9083aa39d810db31077" 2612 "7dab8b1e7f02b84a26c773325f8b2374" 2613 "de7a4b5a58cb5c5cf35bcee6fb946e5b" 2614 "d694fa593a8beb3f9d6592ecedaa66ca" 2615 "82a29d0c51bcf9336230e5d784e4c0a4" 2616 "3f8d79a30a165cbabe452b774b9c7109" 2617 "a97d138f129228966f6c0adc106aad5a" 2618 "9fdd30825769b2c671af6759df28eb39" 2619 "3d54d6")), unhex( 2620 "97dbca7df46d62c8a422c941dd7e835b" 2621 "8ad3361763f7e9b2d95f4f0da6e1ccbc")) 2622 2623 def testSHA384(self): 2624 for hashname in ['sha384_sw', 'sha384_hw']: 2625 if ssh_hash_new(hashname) is None: 2626 continue # skip testing of unavailable HW implementation 2627 2628 # Test cases from RFC 6234 section 8.5, omitting the ones 2629 # whose input is not a multiple of 8 bits 2630 self.assertEqualBin(hash_str('sha384', "abc"), unhex( 2631 'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded163' 2632 '1a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7')) 2633 self.assertEqualBin(hash_str('sha384', 2634 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" 2635 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), 2636 unhex('09330c33f71147e83d192fc782cd1b4753111b173b3b05d2' 2637 '2fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039')) 2638 self.assertEqualBin(hash_str_iter('sha384', 2639 ("a" * 1000 for _ in range(1000))), unhex( 2640 '9d0e1809716474cb086e834e310a4a1ced149e9c00f24852' 2641 '7972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985')) 2642 self.assertEqualBin(hash_str('sha384', 2643 "01234567012345670123456701234567" * 20), unhex( 2644 '2fc64a4f500ddb6828f6a3430b8dd72a368eb7f3a8322a70' 2645 'bc84275b9c0b3ab00d27a5cc3c2d224aa6b61a0d79fb4596')) 2646 self.assertEqualBin(hash_str('sha384', b"\xB9"), unhex( 2647 'bc8089a19007c0b14195f4ecc74094fec64f01f90929282c' 2648 '2fb392881578208ad466828b1c6c283d2722cf0ad1ab6938')) 2649 self.assertEqualBin(hash_str('sha384', 2650 unhex("a41c497779c0375ff10a7f4e08591739")), unhex( 2651 'c9a68443a005812256b8ec76b00516f0dbb74fab26d66591' 2652 '3f194b6ffb0e91ea9967566b58109cbc675cc208e4c823f7')) 2653 self.assertEqualBin(hash_str('sha384', unhex( 2654 "399669e28f6b9c6dbcbb6912ec10ffcf74790349b7dc8fbe4a8e7b3b5621" 2655 "db0f3e7dc87f823264bbe40d1811c9ea2061e1c84ad10a23fac1727e7202" 2656 "fc3f5042e6bf58cba8a2746e1f64f9b9ea352c711507053cf4e5339d5286" 2657 "5f25cc22b5e87784a12fc961d66cb6e89573199a2ce6565cbdf13dca4038" 2658 "32cfcb0e8b7211e83af32a11ac17929ff1c073a51cc027aaedeff85aad7c" 2659 "2b7c5a803e2404d96d2a77357bda1a6daeed17151cb9bc5125a422e941de" 2660 "0ca0fc5011c23ecffefdd09676711cf3db0a3440720e1615c1f22fbc3c72" 2661 "1de521e1b99ba1bd5577408642147ed096")), unhex( 2662 '4f440db1e6edd2899fa335f09515aa025ee177a79f4b4aaf' 2663 '38e42b5c4de660f5de8fb2a5b2fbd2a3cbffd20cff1288c0')) 2664 2665 def testSHA512(self): 2666 for hashname in ['sha512_sw', 'sha512_hw']: 2667 if ssh_hash_new(hashname) is None: 2668 continue # skip testing of unavailable HW implementation 2669 2670 # Test cases from RFC 6234 section 8.5, omitting the ones 2671 # whose input is not a multiple of 8 bits 2672 self.assertEqualBin(hash_str('sha512', "abc"), unhex( 2673 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55' 2674 'd39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94f' 2675 'a54ca49f')) 2676 self.assertEqualBin(hash_str('sha512', 2677 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" 2678 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), 2679 unhex('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299' 2680 'aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26' 2681 '545e96e55b874be909')) 2682 self.assertEqualBin(hash_str_iter('sha512', 2683 ("a" * 1000 for _ in range(1000))), unhex( 2684 'e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa9' 2685 '73ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217' 2686 'ad8cc09b')) 2687 self.assertEqualBin(hash_str('sha512', 2688 "01234567012345670123456701234567" * 20), unhex( 2689 '89d05ba632c699c31231ded4ffc127d5a894dad412c0e024db872d1abd2b' 2690 'a8141a0f85072a9be1e2aa04cf33c765cb510813a39cd5a84c4acaa64d3f' 2691 '3fb7bae9')) 2692 self.assertEqualBin(hash_str('sha512', b"\xD0"), unhex( 2693 '9992202938e882e73e20f6b69e68a0a7149090423d93c81bab3f21678d4a' 2694 'ceeee50e4e8cafada4c85a54ea8306826c4ad6e74cece9631bfa8a549b4a' 2695 'b3fbba15')) 2696 self.assertEqualBin(hash_str('sha512', 2697 unhex("8d4e3c0e3889191491816e9d98bff0a0")), unhex( 2698 'cb0b67a4b8712cd73c9aabc0b199e9269b20844afb75acbdd1c153c98289' 2699 '24c3ddedaafe669c5fdd0bc66f630f6773988213eb1b16f517ad0de4b2f0' 2700 'c95c90f8')) 2701 self.assertEqualBin(hash_str('sha512', unhex( 2702 "a55f20c411aad132807a502d65824e31a2305432aa3d06d3e282a8d84e0d" 2703 "e1de6974bf495469fc7f338f8054d58c26c49360c3e87af56523acf6d89d" 2704 "03e56ff2f868002bc3e431edc44df2f0223d4bb3b243586e1a7d92493669" 2705 "4fcbbaf88d9519e4eb50a644f8e4f95eb0ea95bc4465c8821aacd2fe15ab" 2706 "4981164bbb6dc32f969087a145b0d9cc9c67c22b763299419cc4128be9a0" 2707 "77b3ace634064e6d99283513dc06e7515d0d73132e9a0dc6d3b1f8b246f1" 2708 "a98a3fc72941b1e3bb2098e8bf16f268d64f0b0f4707fe1ea1a1791ba2f3" 2709 "c0c758e5f551863a96c949ad47d7fb40d2")), unhex( 2710 'c665befb36da189d78822d10528cbf3b12b3eef726039909c1a16a270d48' 2711 '719377966b957a878e720584779a62825c18da26415e49a7176a894e7510' 2712 'fd1451f5')) 2713 2714 def testSHA3(self): 2715 # Source: all the SHA-3 test strings from 2716 # https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values#aHashing 2717 # which are a multiple of 8 bits long. 2718 2719 self.assertEqualBin(hash_str('sha3_224', ''), unhex("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7")) 2720 self.assertEqualBin(hash_str('sha3_224', unhex('a3')*200), unhex("9376816aba503f72f96ce7eb65ac095deee3be4bf9bbc2a1cb7e11e0")) 2721 self.assertEqualBin(hash_str('sha3_256', ''), unhex("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")) 2722 self.assertEqualBin(hash_str('sha3_256', unhex('a3')*200), unhex("79f38adec5c20307a98ef76e8324afbfd46cfd81b22e3973c65fa1bd9de31787")) 2723 self.assertEqualBin(hash_str('sha3_384', ''), unhex("0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004")) 2724 self.assertEqualBin(hash_str('sha3_384', unhex('a3')*200), unhex("1881de2ca7e41ef95dc4732b8f5f002b189cc1e42b74168ed1732649ce1dbcdd76197a31fd55ee989f2d7050dd473e8f")) 2725 self.assertEqualBin(hash_str('sha3_512', ''), unhex("a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")) 2726 self.assertEqualBin(hash_str('sha3_512', unhex('a3')*200), unhex("e76dfad22084a8b1467fcf2ffa58361bec7628edf5f3fdc0e4805dc48caeeca81b7c13c30adf52a3659584739a2df46be589c51ca1a4a8416df6545a1ce8ba00")) 2727 self.assertEqualBin(hash_str('shake256_114bytes', ''), unhex("46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be141e96616fb13957692cc7edd0b45ae3dc07223c8e92937bef84bc0eab862853349ec75546f58fb7c2775c38462c5010d846")) 2728 self.assertEqualBin(hash_str('shake256_114bytes', unhex('a3')*200), unhex("cd8a920ed141aa0407a22d59288652e9d9f1a7ee0c1e7c1ca699424da84a904d2d700caae7396ece96604440577da4f3aa22aeb8857f961c4cd8e06f0ae6610b1048a7f64e1074cd629e85ad7566048efc4fb500b486a3309a8f26724c0ed628001a1099422468de726f1061d99eb9e93604")) 2729 2730 def testBLAKE2b(self): 2731 # Test case from RFC 7693 appendix A. 2732 self.assertEqualBin(hash_str('blake2b', b'abc'), unhex( 2733 "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1" 2734 "7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")) 2735 2736 # A small number of test cases from the larger test vector 2737 # set, testing multiple blocks and the empty input. 2738 self.assertEqualBin(hash_str('blake2b', b''), unhex( 2739 "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419" 2740 "d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce")) 2741 self.assertEqualBin(hash_str('blake2b', unhex('00')), unhex( 2742 "2fa3f686df876995167e7c2e5d74c4c7b6e48f8068fe0e44208344d480f7904c" 2743 "36963e44115fe3eb2a3ac8694c28bcb4f5a0f3276f2e79487d8219057a506e4b")) 2744 self.assertEqualBin(hash_str('blake2b', bytes(range(255))), unhex( 2745 "5b21c5fd8868367612474fa2e70e9cfa2201ffeee8fafab5797ad58fefa17c9b" 2746 "5b107da4a3db6320baaf2c8617d5a51df914ae88da3867c2d41f0cc14fa67928")) 2747 2748 # You can get this test program to run the full version of the 2749 # test vectors by modifying the source temporarily to set this 2750 # variable to a pathname where you downloaded the JSON file 2751 # blake2-kat.json. 2752 blake2_test_vectors_path = None 2753 if blake2_test_vectors_path is not None: 2754 with open(blake2_test_vectors_path) as fh: 2755 vectors = json.load(fh) 2756 for vector in vectors: 2757 if vector['hash'] != 'blake2b': 2758 continue 2759 if len(vector['key']) != 0: 2760 continue 2761 2762 h = blake2b_new_general(len(vector['out']) // 2) 2763 ssh_hash_update(h, unhex(vector['in'])) 2764 digest = ssh_hash_digest(h) 2765 self.assertEqualBin(digest, unhex(vector['out'])) 2766 2767 def testArgon2(self): 2768 # draft-irtf-cfrg-argon2-12 section 5 2769 self.assertEqualBin( 2770 argon2('d', 32, 3, 4, 32, b'\x01' * 32, b'\x02' * 16, 2771 b'\x03' * 8, b'\x04' * 12), 2772 unhex("512b391b6f1162975371d30919734294" 2773 "f868e3be3984f3c1a13a4db9fabe4acb")) 2774 self.assertEqualBin( 2775 argon2('i', 32, 3, 4, 32, b'\x01' * 32, b'\x02' * 16, 2776 b'\x03' * 8, b'\x04' * 12), 2777 unhex("c814d9d1dc7f37aa13f0d77f2494bda1" 2778 "c8de6b016dd388d29952a4c4672b6ce8")) 2779 self.assertEqualBin( 2780 argon2('id', 32, 3, 4, 32, b'\x01' * 32, b'\x02' * 16, 2781 b'\x03' * 8, b'\x04' * 12), 2782 unhex("0d640df58d78766c08c037a34a8b53c9" 2783 "d01ef0452d75b65eb52520e96b01e659")) 2784 2785 def testHmacSHA(self): 2786 # Test cases from RFC 6234 section 8.5. 2787 def vector(key, message, s1=None, s256=None): 2788 if s1 is not None: 2789 self.assertEqualBin( 2790 mac_str('hmac_sha1', key, message), unhex(s1)) 2791 if s256 is not None: 2792 self.assertEqualBin( 2793 mac_str('hmac_sha256', key, message), unhex(s256)) 2794 vector( 2795 unhex("0b"*20), "Hi There", 2796 "b617318655057264e28bc0b6fb378c8ef146be00", 2797 "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7") 2798 vector( 2799 "Jefe", "what do ya want for nothing?", 2800 "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", 2801 "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843") 2802 vector( 2803 unhex("aa"*20), unhex('dd'*50), 2804 "125d7342b9ac11cd91a39af48aa17b4f63f175d3", 2805 "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565FE") 2806 vector( 2807 unhex("0102030405060708090a0b0c0d0e0f10111213141516171819"), 2808 unhex("cd"*50), 2809 "4c9007f4026250c6bc8414f9bf50c86c2d7235da", 2810 "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b") 2811 vector( 2812 unhex("aa"*80), 2813 "Test Using Larger Than Block-Size Key - Hash Key First", 2814 s1="aa4ae5e15272d00e95705637ce8a3b55ed402112") 2815 vector( 2816 unhex("aa"*131), 2817 "Test Using Larger Than Block-Size Key - Hash Key First", 2818 s256="60e431591ee0b67f0d8a26aacbf5b77f" 2819 "8e0bc6213728c5140546040f0ee37f54") 2820 vector( 2821 unhex("aa"*80), 2822 "Test Using Larger Than Block-Size Key and " 2823 "Larger Than One Block-Size Data", 2824 s1="e8e99d0f45237d786d6bbaa7965c7808bbff1a91") 2825 vector( 2826 unhex("aa"*131), 2827 "This is a test using a larger than block-size key and a " 2828 "larger than block-size data. The key needs to be hashed " 2829 "before being used by the HMAC algorithm.", 2830 s256="9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713938A7F51535C3A35E2") 2831 2832 def testEd25519(self): 2833 def vector(privkey, pubkey, message, signature): 2834 x, y = ecc_edwards_get_affine(eddsa_public( 2835 mp_from_bytes_le(privkey), 'ed25519')) 2836 self.assertEqual(int(y) | ((int(x) & 1) << 255), 2837 int(mp_from_bytes_le(pubkey))) 2838 pubblob = ssh_string(b"ssh-ed25519") + ssh_string(pubkey) 2839 privblob = ssh_string(privkey) 2840 sigblob = ssh_string(b"ssh-ed25519") + ssh_string(signature) 2841 pubkey = ssh_key_new_pub('ed25519', pubblob) 2842 self.assertTrue(ssh_key_verify(pubkey, sigblob, message)) 2843 privkey = ssh_key_new_priv('ed25519', pubblob, privblob) 2844 # By testing that the signature is exactly the one expected in 2845 # the test vector and not some equivalent one generated with a 2846 # different nonce, we're verifying in particular that we do 2847 # our deterministic nonce generation in the manner specified 2848 # by Ed25519. Getting that wrong would lead to no obvious 2849 # failure, but would surely turn out to be a bad idea sooner 2850 # or later... 2851 self.assertEqualBin(ssh_key_sign(privkey, message, 0), sigblob) 2852 2853 # A cherry-picked example from DJB's test vector data at 2854 # https://ed25519.cr.yp.to/python/sign.input, which is too 2855 # large to copy into here in full. 2856 privkey = unhex( 2857 'c89955e0f7741d905df0730b3dc2b0ce1a13134e44fef3d40d60c020ef19df77') 2858 pubkey = unhex( 2859 'fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c') 2860 message = unhex( 2861 '507c94c8820d2a5793cbf3442b3d71936f35fe3afef316') 2862 signature = unhex( 2863 '7ef66e5e86f2360848e0014e94880ae2920ad8a3185a46b35d1e07dea8fa8ae4' 2864 'f6b843ba174d99fa7986654a0891c12a794455669375bf92af4cc2770b579e0c') 2865 vector(privkey, pubkey, message, signature) 2866 2867 # You can get this test program to run the full version of 2868 # DJB's test vectors by modifying the source temporarily to 2869 # set this variable to a pathname where you downloaded the 2870 # file. 2871 ed25519_test_vector_path = None 2872 if ed25519_test_vector_path is not None: 2873 with open(ed25519_test_vector_path) as f: 2874 for line in iter(f.readline, ""): 2875 words = line.split(":") 2876 # DJB's test vector input format concatenates a 2877 # spare copy of the public key to the end of the 2878 # private key, and a spare copy of the message to 2879 # the end of the signature. Strip those off. 2880 privkey = unhex(words[0])[:32] 2881 pubkey = unhex(words[1]) 2882 message = unhex(words[2]) 2883 signature = unhex(words[3])[:64] 2884 vector(privkey, pubkey, message, signature) 2885 2886 def testEd448(self): 2887 def vector(privkey, pubkey, message, signature): 2888 x, y = ecc_edwards_get_affine(eddsa_public( 2889 mp_from_bytes_le(privkey), 'ed448')) 2890 self.assertEqual(int(y) | ((int(x) & 1) << 455), 2891 int(mp_from_bytes_le(pubkey))) 2892 pubblob = ssh_string(b"ssh-ed448") + ssh_string(pubkey) 2893 privblob = ssh_string(privkey) 2894 sigblob = ssh_string(b"ssh-ed448") + ssh_string(signature) 2895 pubkey = ssh_key_new_pub('ed448', pubblob) 2896 self.assertTrue(ssh_key_verify(pubkey, sigblob, message)) 2897 privkey = ssh_key_new_priv('ed448', pubblob, privblob) 2898 # Deterministic signature check as in Ed25519 2899 self.assertEqualBin(ssh_key_sign(privkey, message, 0), sigblob) 2900 2901 # Source: RFC 8032 section 7.4 2902 2903 privkey = unhex('6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b') 2904 pubkey = unhex('5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180') 2905 message = b'' 2906 signature = unhex('533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4dbb61149f05a7363268c71d95808ff2e652600') 2907 vector(privkey, pubkey, message, signature) 2908 2909 privkey = unhex('c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e') 2910 pubkey = unhex('43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480') 2911 message = unhex('03') 2912 signature = unhex('26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f4352541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cbcee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0ff3348ab21aa4adafd1d234441cf807c03a00') 2913 vector(privkey, pubkey, message, signature) 2914 2915 privkey = unhex('cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffdf60500553abc0e05cd02184bdb89c4ccd67e187951267eb328') 2916 pubkey = unhex('dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400') 2917 message = unhex('0c3e544074ec63b0265e0c') 2918 signature = unhex('1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d389dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b051068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5028961c9bf8ffd973fe5d5c206492b140e00') 2919 vector(privkey, pubkey, message, signature) 2920 2921 privkey = unhex('258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d939f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b') 2922 pubkey = unhex('3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580') 2923 message = unhex('64a65f3cdedcdd66811e2915') 2924 signature = unhex('7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4ae90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457eb1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861e72003cbae6d6b8b827e4e6c143064ff3c00') 2925 vector(privkey, pubkey, message, signature) 2926 2927 privkey = unhex('d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bff21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01') 2928 pubkey = unhex('df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00') 2929 message = unhex('bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944') 2930 signature = unhex('554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b18dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722ef552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba5f30e88e36ec2703b349ca229c2670833900') 2931 vector(privkey, pubkey, message, signature) 2932 2933 privkey = unhex('2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d37569b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5') 2934 pubkey = unhex('79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00') 2935 message = unhex('15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567cfa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072fc1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a6039c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b590316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce012d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11') 2936 signature = unhex('c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc60987fd08527c1a8e80d5823e65cafe2a3d00') 2937 vector(privkey, pubkey, message, signature) 2938 2939 privkey = unhex('872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8') 2940 pubkey = unhex('a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400') 2941 message = unhex('6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e972660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd323219b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab797172b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f52096cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db977025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f0410a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf9696149e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a6059d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87') 2942 signature = unhex('e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bddf7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed573603ce30d8bb761785dc30dbc320869e1a00') 2943 vector(privkey, pubkey, message, signature) 2944 2945 def testMontgomeryKex(self): 2946 # Unidirectional tests, consisting of an input random number 2947 # string and peer public value, giving the expected output 2948 # shared key. Source: RFC 7748 section 5.2. 2949 rfc7748s5_2 = [ 2950 ('curve25519', 2951 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4', 2952 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c', 2953 0xc3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552), 2954 ('curve25519', 2955 '4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d', 2956 'e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493', 2957 0x95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957), 2958 ('curve448', 2959 '3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3', 2960 '06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086', 2961 0xce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f), 2962 ('curve448', 2963 '203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f', 2964 '0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db', 2965 0x884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d), 2966 ] 2967 2968 for method, priv, pub, expected in rfc7748s5_2: 2969 with queued_specific_random_data(unhex(priv)): 2970 ecdh = ssh_ecdhkex_newkey(method) 2971 key = ssh_ecdhkex_getkey(ecdh, unhex(pub)) 2972 self.assertEqual(int(key), expected) 2973 2974 # Bidirectional tests, consisting of the input random number 2975 # strings for both parties, and the expected public values and 2976 # shared key. Source: RFC 7748 section 6. 2977 rfc7748s6 = [ 2978 ('curve25519', # section 6.1 2979 '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a', 2980 '8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a', 2981 '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb', 2982 'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f', 2983 0x4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742), 2984 ('curve448', # section 6.2 2985 '9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b', 2986 '9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0', 2987 '1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d', 2988 '3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609', 2989 0x07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d), 2990 ] 2991 2992 for method, apriv, apub, bpriv, bpub, expected in rfc7748s6: 2993 with queued_specific_random_data(unhex(apriv)): 2994 alice = ssh_ecdhkex_newkey(method) 2995 with queued_specific_random_data(unhex(bpriv)): 2996 bob = ssh_ecdhkex_newkey(method) 2997 self.assertEqualBin(ssh_ecdhkex_getpublic(alice), unhex(apub)) 2998 self.assertEqualBin(ssh_ecdhkex_getpublic(bob), unhex(bpub)) 2999 akey = ssh_ecdhkex_getkey(alice, unhex(bpub)) 3000 bkey = ssh_ecdhkex_getkey(bob, unhex(apub)) 3001 self.assertEqual(int(akey), expected) 3002 self.assertEqual(int(bkey), expected) 3003 3004 def testCRC32(self): 3005 self.assertEqual(crc32_rfc1662("123456789"), 0xCBF43926) 3006 self.assertEqual(crc32_ssh1("123456789"), 0x2DFD2D88) 3007 3008 # Source: 3009 # http://reveng.sourceforge.net/crc-catalogue/17plus.htm#crc.cat.crc-32-iso-hdlc 3010 # which collected these from various sources. 3011 reveng_tests = [ 3012 '000000001CDF4421', 3013 'F20183779DAB24', 3014 '0FAA005587B2C9B6', 3015 '00FF55111262A032', 3016 '332255AABBCCDDEEFF3D86AEB0', 3017 '926B559BA2DE9C', 3018 'FFFFFFFFFFFFFFFF', 3019 'C008300028CFE9521D3B08EA449900E808EA449900E8300102007E649416', 3020 '6173640ACEDE2D15', 3021 ] 3022 for vec in map(unhex, reveng_tests): 3023 # Each of these test vectors can be read two ways. One 3024 # interpretation is that the last four bytes are the 3025 # little-endian encoding of the CRC of the rest. (Because 3026 # that's how the CRC is attached to a string at the 3027 # sending end.) 3028 # 3029 # The other interpretation is that if you CRC the whole 3030 # string, _including_ the final four bytes, you expect to 3031 # get the same value for any correct string (because the 3032 # little-endian encoding matches the way the rest of the 3033 # string was interpreted as a polynomial in the first 3034 # place). That's how a receiver is intended to check 3035 # things. 3036 # 3037 # The expected output value is listed in RFC 1662, and in 3038 # the reveng.sourceforge.net catalogue, as 0xDEBB20E3. But 3039 # that's because their checking procedure omits the final 3040 # complement step that the construction procedure 3041 # includes. Our crc32_rfc1662 function does do the final 3042 # complement, so we expect the bitwise NOT of that value, 3043 # namely 0x2144DF1C. 3044 expected = struct.unpack("<L", vec[-4:])[0] 3045 self.assertEqual(crc32_rfc1662(vec[:-4]), expected) 3046 self.assertEqual(crc32_rfc1662(vec), 0x2144DF1C) 3047 3048if __name__ == "__main__": 3049 # Run the tests, suppressing automatic sys.exit and collecting the 3050 # unittest.TestProgram instance returned by unittest.main instead. 3051 testprogram = unittest.main(exit=False) 3052 3053 # If any test failed, just exit with failure status. 3054 if not testprogram.result.wasSuccessful(): 3055 childprocess.wait_for_exit() 3056 sys.exit(1) 3057 3058 # But if no tests failed, we have one last check to do: look at 3059 # the subprocess's return status, so that if Leak Sanitiser 3060 # detected any memory leaks, the success return status will turn 3061 # into a failure at the last minute. 3062 childprocess.check_return_status() 3063