def test_pollard_rho_give_up(self): # There's a small chance this test may fail. :-) p = 95749913370328252241446208736506188314802113993127662348226135040475696867509 q = 99274458486037483860318981815348157562287354834427068777154647405331367500099 n = p * q self.assertIsNone(NumberTheory.pollard_rho(n, max_iterations=10))
def test_pollard_rho_prime(self): p = 2003 self.assertIsNone(NumberTheory.pollard_rho(p), None)
def test_pollard_rho_success(self): p = 3513360553 q = 2841366767 n = p * q self.assertIn(NumberTheory.pollard_rho(n), [p, q])
def analyze_n(self, n): judgements = SecurityJudgements() if n < 0: judgements += SecurityJudgement( JudgementCode.X509Cert_PublicKey_RSA_Modulus_Negative, "Modulus uses incorrect encoding, representation is a negative integer.", commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) # Fix up n so it's a positive integer for the rest of the tests bitlen = (n.bit_length() + 7) // 8 * 8 mask = (1 << bitlen) - 1 n = n & mask elif n == 0: judgements += SecurityJudgement( JudgementCode.X509Cert_PublicKey_RSA_Modulus_Zero, "Modulus is zero, this is definitely a broken RSA public key.", bits=0, commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) elif n == 1: judgements += SecurityJudgement( JudgementCode.X509Cert_PublicKey_RSA_Modulus_One, "Modulus is one, this is definitely a broken RSA public key.", bits=0, commonness=Commonness.HIGHLY_UNUSUAL, compatibility=Compatibility.STANDARDS_DEVIATION) if self._test_probable_prime: if NumberTheory.is_probable_prime(n): judgements += SecurityJudgement( JudgementCode.X509Cert_PublicKey_RSA_Modulus_Prime, "Modulus is prime, not a compound integer as we would expect for RSA.", bits=0) if self._pollards_rho_iterations > 0: small_factor = NumberTheory.pollard_rho( n, max_iterations=self._pollards_rho_iterations) if small_factor is not None: judgements += SecurityJudgement( JudgementCode.X509Cert_PublicKey_RSA_Modulus_Factorable, "Modulus has small factor (%d) and is therefore trivially factorable." % (small_factor), bits=0) match = ModulusDB().find(n) if match is not None: judgements += SecurityJudgement( JudgementCode. X509Cert_PublicKey_RSA_Modulus_FactorizationKnown, "Modulus is known to be compromised: %s" % (match.text), bits=0) hweight_analysis = NumberTheory.hamming_weight_analysis(n) if (hweight_analysis is not None) and (not hweight_analysis.plausibly_random): judgements += SecurityJudgement( JudgementCode.X509Cert_PublicKey_RSA_Modulus_BitBiasPresent, "Modulus does not appear to be random. Expected a Hamming weight between %d and %d for a %d bit modulus, but found Hamming weight %d." % (hweight_analysis.rnd_min_hweight, hweight_analysis.rnd_max_hweight, hweight_analysis.bitlen, hweight_analysis.hweight), commonness=Commonness.HIGHLY_UNUSUAL) # We estimate the complexity of factoring the modulus by the asymptotic # complexity of the GNFS. bits_security = NumberTheory.asymtotic_complexity_gnfs_bits(n) judgements += self.algorithm("bits").analyze( JudgementCode.X509Cert_PublicKey_RSA_Modulus_LengthInBits, bits_security) return judgements