def test_edge_nomod(self): self.assertEquals(rsa.modexp(0, 0, 100), 1) self.assertEquals(rsa.modexp(0, 1, 100), 0) self.assertEquals(rsa.modexp(0, 10, 100), 0) self.assertEquals(rsa.modexp(1, 0, 100), 1) self.assertEquals(rsa.modexp(1, 1, 100), 1) self.assertEquals(rsa.modexp(1, 13, 100), 1) self.assertEquals(rsa.modexp(5, 0, 100), 1) self.assertEquals(rsa.modexp(5, 1, 100), 5) self.assertEquals(rsa.modexp(5, 2, 100), 25)
def CheckSignatureWeak(pubKey, message, signature): """Weak signature checking.""" e, n = pubKey k = KEY_BYTESIZE if len(signature) != k: return False s = BytesToInteger(signature) m = rsa.modexp(s, e, n) try: encodedMessage = IntegerToBytes(m, k) except Exception as ex: print('Failed conversion to bytes:', str(ex)) return False H = sha256(message) # This is probably the most common way this bug can manifest: we have a # regular expression that only verifies there is at least one '\xff' byte # in the padding, but does not state how many are expected. Moreover, it # does not check while this regexp covers the full string, allowing for # signatures, like ours, with garbage appended after the hash. if re.match(b'\x00\x01' + b'[\xff]+' + b'\x00' + re.escape(ASN1_GOOP + H), encodedMessage): return True return False
def test_stress(self): R = random.Random(34) for i in range(50): x = R.randint(0, 100) y = R.randint(0, 100) n = R.randint(1, 100) self.assertEquals(rsa.modexp(x, y, n), (x ** y) % n)
def bits(pub, priv, c, oracle): n = pub[1] e = pub[0] two_e = rsa.modexp(2, e, n) b = [] for i in xrange(1025): c = (c * two_e) % n b.append(oracle(c)) return b
def test_mod_edge(self): self.assertEquals(rsa.modexp(5, 2, 1), 0) self.assertEquals(rsa.modexp(0, 0, 1), 0) self.assertEquals(rsa.modexp(0, 1, 1), 0) self.assertEquals(rsa.modexp(1, 0, 1), 0) self.assertEquals(rsa.modexp(1, 1, 1), 0) self.assertEquals(rsa.modexp(5, 2, 1), 0)
def unpadded_msg_recovery_oracle(): pub, oracle = get_rsa_unpadded_dec_oracle(1024) m = "Hello World!" print "M is '%s'" % m c = rsa.encrypt(pub, m) print "C is %d\n" % c # use the decryption oracle print "Using decryption oracle..." m2 = oracle(c) print "Decrypted '%s'\n" % m2 print "Testing that decryption oracle will reject this ciphertext" print "Using decryption oracle..." m2 = oracle(c) # pick random S > 1 mod N such that S has a multiplicative inverse mod N print "\nSearching for suitable S > 1 mod N" E, N = pub S, S_inv = None, None while True: S = random.randint(2, N-1) if S == E: continue S_inv = rsa.invmod(S, N) if S_inv: break print "Doing the attack with S == %d, S_inv == %d" % (S, S_inv) c_prime = (rsa.modexp(S, E, N) * c) % N print "Using decryption oracle..." m_prime = long(binascii.hexlify(oracle(c_prime)), 16) m2 = rsa._tohex(m_prime * S_inv % N) print "Messsage is '%s'" % m2
def test_mod_parity(self): for i in range(1, 20): self.assertEquals(rsa.modexp(2, i, 2), 0) self.assertEquals(rsa.modexp(3, i, 2), 1)
def test_small_powers_nomod(self): for b in (2, 5): for i in range(10): self.assertEquals(rsa.modexp(b, i, 10000000), b ** i)