def _judge_curve_cofactor(self, curve): judgements = SecurityJudgements() if curve.h is None: judgements += SecurityJudgement( JudgementCode. X509Cert_PublicKey_ECC_DomainParameters_Cofactor_Missing, "Curve cofactor h is not present in explicit domain parameter encoding. This is allowed, but highly unusual.", commonness=Commonness.HIGHLY_UNUSUAL) else: if curve.h <= 0: judgements += SecurityJudgement( JudgementCode. X509Cert_PublicKey_ECC_DomainParameters_CurveProperty_Cofactor_Invalid, "Curve cofactor h = %d is zero or negative. This is invalid." % (curve.h), bits=0, commonness=Commonness.HIGHLY_UNUSUAL) elif curve.h > 8: judgements += SecurityJudgement( JudgementCode. X509Cert_PublicKey_ECC_DomainParameters_CurveProperty_Cofactor_Large, "Curve cofactor is unusually large, h = %d. This is an indication the curve has non-ideal cryptographic properties; would expect h <= 8." % (curve.h), commonness=Commonness.HIGHLY_UNUSUAL) if curve.curvetype == "prime": field_size = curve.p elif curve.curvetype == "binary": # TODO: For GF(p), the number of group elements is simply p. # For GF(2^m), I'm fairly certiain it is the reduction # polynomial (essentially, it's modular polynomial arithmetic). # Not 100% sure though. Verify. field_size = curve.int_poly # Hasse Theorem on Elliptic Curves: # p - (2 * sqrt(p)) + 1 <= #E(F_p) <= p + (2 * sqrt(p)) + 1 # #E(F_p) = n h # h >= (p - (2 * sqrt(p)) + 1) / n # h <= (p + (2 * sqrt(p)) + 1) / n sqrt_p = NumberTheory.isqrt(field_size) hasse_h_min = (field_size - (2 * (sqrt_p + 1)) + 1) // curve.n hasse_h_max = (field_size + (2 * (sqrt_p + 1)) + 1) // curve.n if not (hasse_h_min <= curve.h <= hasse_h_max): literature = LiteratureReference( author="Helmut Hasse", title= "Zur Theorie der abstrakten elliptischen Funktionenkörper. I, II & III", year=1936, source="Crelle's Journal") judgements += SecurityJudgement( JudgementCode. X509Cert_PublicKey_ECC_DomainParameters_CurveProperty_Cofactor_OutsideHasseBound, "Curve cofactor h = %d is outside the Hasse bound (%d <= h <= %d). Cofactor therefore is invalid." % (curve.h, hasse_h_min, hasse_h_max), bits=0, commonness=Commonness.HIGHLY_UNUSUAL, literature=literature) return judgements
def test_isqrt(self): self.assertEqual(NumberTheory.isqrt(0), 0) self.assertEqual(NumberTheory.isqrt(1), 1) self.assertEqual(NumberTheory.isqrt(2), 1) self.assertEqual(NumberTheory.isqrt(3), 1) self.assertEqual(NumberTheory.isqrt(4), 2) self.assertEqual(NumberTheory.isqrt(5), 2) self.assertEqual(NumberTheory.isqrt(27), 5) self.assertEqual(NumberTheory.isqrt(35), 5) self.assertEqual(NumberTheory.isqrt(36), 6) self.assertEqual(NumberTheory.isqrt(123456789), 11111) self.assertEqual(NumberTheory.isqrt(1234567890), 35136)