mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-06-30 19:12:48 -05:00
Add some tests of Miller-Rabin to cryptsuite.
I'm about to rewrite the Miller-Rabin testing code, so let's start by introducing a test suite that the old version passes, and then I can make sure the new one does too.
This commit is contained in:
@ -1188,6 +1188,73 @@ class keygen(MyTestBase):
|
||||
self.assertEqual(pockle_add_prime(po, 1, [2], 1),
|
||||
'POCKLE_PRIME_SMALLER_THAN_2')
|
||||
|
||||
def testMillerRabin(self):
|
||||
# A prime congruent to 3 mod 4, so M-R can only do one
|
||||
# iteration: either a^{(p-1)/2} == +1, or -1. Either counts as
|
||||
# a pass; the latter also means the number is potentially a
|
||||
# primitive root.
|
||||
n = 0xe76e6aaa42b5d7423aa4da5613eb21c3
|
||||
mr = miller_rabin_new(n)
|
||||
self.assertEqual(miller_rabin_test(mr, 2), "passed+ppr")
|
||||
self.assertEqual(miller_rabin_test(mr, 4), "passed")
|
||||
|
||||
# The 'potential primitive root' test only means that M-R
|
||||
# didn't _rule out_ the number being a primitive root, by
|
||||
# finding that any of the powers _it tested_ less than n-1
|
||||
# came out to be 1. In this case, 2 really is a primitive
|
||||
# root, but since 13 | n-1, the 13th powers mod n form a
|
||||
# multiplicative subgroup. So 2^13 is not a primitive root,
|
||||
# and yet, M-R can't tell the difference, because it only
|
||||
# tried the exponent (n-1)/2, not the actual counterexample
|
||||
# (n-1)/13.
|
||||
self.assertEqual(miller_rabin_test(mr, 2**13), "passed+ppr")
|
||||
|
||||
# A prime congruent to 1 mod a reasonably large power of 2, so
|
||||
# M-R has lots of scope to have different things happen. 3 is
|
||||
# a primitive root, so we expect that 3, 3^2, 3^4, ..., 3^256
|
||||
# should all pass for different reasons, with only the first
|
||||
# of them returning passed+ppr.
|
||||
n = 0xb1b65ebe489ff0ab4597bb67c3d22d01
|
||||
mr = miller_rabin_new(n)
|
||||
w = 3
|
||||
self.assertEqual(miller_rabin_test(mr, w), "passed+ppr")
|
||||
for i in range(1, 10):
|
||||
w = w * w % n
|
||||
self.assertEqual(miller_rabin_test(mr, w), "passed")
|
||||
|
||||
# A prime with an _absurdly_ large power-of-2 factor in its
|
||||
# multiplicative group.
|
||||
n = 0x600000000000000000000000000000000000000000000001
|
||||
mr = miller_rabin_new(n)
|
||||
w = 10
|
||||
self.assertEqual(miller_rabin_test(mr, w), "passed+ppr")
|
||||
for i in range(1, 200):
|
||||
w = w * w % n
|
||||
self.assertEqual(miller_rabin_test(mr, w), "passed")
|
||||
|
||||
# A blatantly composite number. But we still expect to see a
|
||||
# pass if we give the witness 1 (which will give a maximal
|
||||
# trailing string of 1s), or -1 (which will give -1 when
|
||||
# raised to the maximal odd factor of n-1, or indeed any other
|
||||
# odd power).
|
||||
n = 0x1010101010101010101010101010101
|
||||
mr = miller_rabin_new(n)
|
||||
self.assertEqual(miller_rabin_test(mr, 1), "passed")
|
||||
self.assertEqual(miller_rabin_test(mr, n-1), "passed")
|
||||
self.assertEqual(miller_rabin_test(mr, 2), "failed")
|
||||
|
||||
# A Carmichael number, as a proper test that M-R detects
|
||||
# things the Fermat test would not.
|
||||
#
|
||||
# (Its prime factorisation is 26823115100268314289505807 *
|
||||
# 53646230200536628579011613 * 80469345300804942868517419,
|
||||
# which is enough to re-check its Carmichaelness.)
|
||||
n = 0xffffffffffffffffcf8032f3e044b4a8b1b1bf0b526538eae953d90f44d65511
|
||||
mr = miller_rabin_new(n)
|
||||
self.assertEqual(miller_rabin_test(mr, 16), "passed")
|
||||
assert(pow(2, n-1, n) == 1) # Fermat test would pass, but ...
|
||||
self.assertEqual(miller_rabin_test(mr, 2), "failed") # ... this fails
|
||||
|
||||
class crypt(MyTestBase):
|
||||
def testSSH1Fingerprint(self):
|
||||
# Example key and reference fingerprint value generated by
|
||||
|
@ -235,7 +235,7 @@ def make_retval(rettype, word, unpack_strings):
|
||||
elif rettype == "boolean":
|
||||
assert word == b"true" or word == b"false"
|
||||
return word == b"true"
|
||||
elif rettype == "pocklestatus":
|
||||
elif rettype in {"pocklestatus", "mr_result"}:
|
||||
return word.decode("ASCII")
|
||||
raise TypeError("Can't deal with return value {!r} of type {!r}"
|
||||
.format(word, rettype))
|
||||
|
Reference in New Issue
Block a user