Esempio n. 1
0
    def decode_point(self, serialized_point):
        assert (isinstance(serialized_point, bytes))
        if len(serialized_point) != self.element_octet_cnt:
            raise InvalidInputException(
                "Do not know how to decode %s point. Expected %d octets, but got %d."
                % (str(self), self.element_octet_cnt, len(serialized_point)))

        serialized_point = bytearray(serialized_point)
        x_lsb = (serialized_point[-1] >> 7) & 1
        serialized_point[-1] &= 0x7f
        y = int.from_bytes(serialized_point, byteorder="little")

        if y >= self.p:
            raise InvalidInputException(
                "y coordinate of point must be smaller than p.")

        # x^2 = (1 - y^2) / (a - dy^2)
        x2 = (1 - y * y) % self.p
        x2 *= NumberTheory.modinv(self.a - self.d * y * y, self.p)
        (x_pos, x_neg) = NumberTheory.sqrt_mod_p(x2, self.p)

        if x_lsb == 0:
            x = x_pos
        else:
            x = x_neg

        point = self.point(x, y)
        return point
Esempio n. 2
0
 def test_possible_divisors(self):
     self.assertEqual(
         list(sorted(NumberTheory.possible_divisors([2, 2, 3]))),
         [1, 2, 3, 4, 6, 12])
     self.assertEqual(
         list(sorted(NumberTheory.possible_divisors([2, 3, 5]))),
         [1, 2, 3, 5, 6, 10, 15, 30])
Esempio n. 3
0
 def point_addition(self, P, Q):
     x = (P.x * Q.y + Q.x * P.y) % self.p
     x = (x * NumberTheory.modinv(1 + self.d * P.x * Q.x * P.y * Q.y,
                                  self.p)) % self.p
     y = (P.y * Q.y - self.a * P.x * Q.x) % self.p
     y = (y * NumberTheory.modinv(1 - self.d * P.x * Q.x * P.y * Q.y,
                                  self.p)) % self.p
     return self.point(x, y)
Esempio n. 4
0
    def test_hweight_margin(self):
        r = int.from_bytes(os.urandom(16), byteorder="little")
        self.assertTrue(
            NumberTheory.hamming_weight_analysis(r).plausibly_random)

        n = 0x10000000000000
        self.assertFalse(
            NumberTheory.hamming_weight_analysis(n).plausibly_random)
Esempio n. 5
0
    def test_gen_prime(self):
        primes = set()
        for _ in range(15):
            p = NumberTheory.randprime_bits(6, two_msb_set=True)
            q = NumberTheory.randprime_bits(6, two_msb_set=True)
            primes.add(p)
            primes.add(q)
            n = p * q
            self.assertEqual(n.bit_length(), 12)

        # With reasonal probability, all will be hit
        self.assertEqual(primes, set([53, 59, 61]))
Esempio n. 6
0
    def test_egcd(self):
        (g, s, t) = NumberTheory.egcd(4567, 123)
        self.assertEqual(g, 1)
        self.assertEqual(s, -23)
        self.assertEqual(t, 854)

        (g, s, t) = NumberTheory.egcd(123, 4567)
        self.assertEqual(g, 1)
        self.assertEqual(s, 854)
        self.assertEqual(t, -23)

        (g, s, t) = NumberTheory.egcd(101 * 17, 101 * 11)
        self.assertEqual(g, 101)
        self.assertEqual(s, 2)
        self.assertEqual(t, -3)
Esempio n. 7
0
    def test_carryless_multiplication(self):
        for x in [0, 1, 2, 3, 4, 5, 123, 267, 498327849327]:
            self.assertEqual(NumberTheory.cl_mul(0, x), 0)
            self.assertEqual(NumberTheory.cl_mul(x, 0), 0)
            self.assertEqual(NumberTheory.cl_mul(1, x), x)
            self.assertEqual(NumberTheory.cl_mul(x, 1), x)
            self.assertEqual(NumberTheory.cl_mul(2, x), 2 * x)
            self.assertEqual(NumberTheory.cl_mul(x, 2), 2 * x)
            self.assertEqual(NumberTheory.cl_mul(x, 1024), 1024 * x)
            self.assertEqual(NumberTheory.cl_mul(1024, x), 1024 * x)

            self.assertEqual(NumberTheory.cl_mul(x, 1 | 2 | 8 | 256),
                             (1 * x) ^ (2 * x) ^ (8 * x) ^ (256 * x))
            self.assertEqual(NumberTheory.cl_mul(1 | 2 | 8 | 256, x),
                             (1 * x) ^ (2 * x) ^ (8 * x) ^ (256 * x))
Esempio n. 8
0
    def check_integrity(self, msg=12345678987654321):
        # Assert gcd(e, phi(n)) == 1
        phi_n = (self.p - 1) * (self.q - 1)
        gcd = NumberTheory.gcd(phi_n, self.e)
        if gcd != 1:
            raise KeyCorruptException(
                "Expected gcd(phi(n), e) to be 1, but was %d." % (gcd))

        # Truncate msg if too large for exponent
        msg = msg % self.n

        # Calculate normale signature and verify
        sig = pow(msg, self.d, self.n)
        verify = pow(sig, self.e, self.n)
        if verify != msg:
            raise KeyCorruptException("Expected verify value %d, but got %d." %
                                      (msg, verify))

        # Test that RSA-CRT constants work
        m1 = pow(msg, self.dmp1, self.p)
        m2 = pow(msg, self.dmq1, self.q)
        sig_crt = (((self.iqmp * (m1 - m2)) % self.p) * self.q) + m2
        if sig != sig_crt:
            raise KeyCorruptException(
                "Expected same signature for naive signature as RSA-CRT signature, but former was 0x%x and latter 0x%x."
                % (sig, sig_crt))
Esempio n. 9
0
 def _judge_curve_embedding_degree(self, curve):
     d = 1
     for k in range(1, 50 + 1):
         d = (d * curve.p) % curve.n
         if d == 1:
             if (k == 1) or (NumberTheory.is_probable_prime(curve.n)):
                 fail_text = "k = %d" % (k)
             else:
                 fail_text = "k <= %d" % (k)
             literature = LiteratureReference(
                 author=[
                     "Alfred Menezes", "Scott Vanstone", "Tatsuaki Okamoto"
                 ],
                 title=
                 "Reducing Elliptic Curve Logarithms to Logarithms in a Finite Field",
                 year=1991,
                 source="ACM")
             return SecurityJudgement(
                 JudgementCode.
                 X509Cert_PublicKey_ECC_DomainParameters_CurveProperty_LowEmbeddingDegree,
                 "This curve has low embedding degree (%s), it fails the MOV condition. It can be compromised using the probabilistic polynomial-time MOV attack."
                 % (fail_text),
                 bits=0,
                 commonness=Commonness.HIGHLY_UNUSUAL,
                 literature=literature)
     return None
Esempio n. 10
0
    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
Esempio n. 11
0
 def on_curve(self, point):
     lhs = NumberTheory.binpoly_reduce(
         NumberTheory.cl_mul(point.y, point.y)
         ^ NumberTheory.cl_mul(point.x, point.y), self.intpoly)
     rhs = NumberTheory.binpoly_reduce(
         NumberTheory.cl_mul(NumberTheory.cl_mul(point.x, point.x), point.x)
         ^ NumberTheory.cl_mul(NumberTheory.cl_mul(self.a, point.x),
                               point.x) ^ self.b, self.intpoly)
     return lhs == rhs
Esempio n. 12
0
 def test_iterprimes(self):
     primes = [
         value for (no, value) in zip(range(25), NumberTheory.iter_primes())
     ]
     self.assertEqual(primes, [
         2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
         67, 71, 73, 79, 83, 89, 97
     ])
Esempio n. 13
0
 def test_probable_prime(self):
     self.assertTrue(NumberTheory.is_probable_prime(2))
     self.assertTrue(NumberTheory.is_probable_prime(3))
     self.assertTrue(NumberTheory.is_probable_prime(5))
     self.assertTrue(NumberTheory.is_probable_prime(101))
     self.assertFalse(NumberTheory.is_probable_prime(0))
     self.assertFalse(NumberTheory.is_probable_prime(1))
     self.assertFalse(NumberTheory.is_probable_prime(4))
Esempio n. 14
0
    def test_sqrt_5_mod_8(self):
        for p in [11948800825345174421]:
            self.assertEqual(p % 8, 5)

            for value in [1, 123, 123456789, 0x123456789]:
                value = value % p
                sqr = (value * value) % p
                (sqrt_pos, sqrt_neg) = NumberTheory.sqrt_mod_p(sqr, p)
                self.assertEqual((sqrt_pos & 1), 0)
                self.assertEqual((sqrt_neg & 1), 1)
                self.assertEqual((sqrt_pos * sqrt_pos) % p, sqr)
Esempio n. 15
0
 def _select_q(self, p):
     if not self._args.close_q:
         while True:
             yield self._prime_db.get(bitlen=self._q_bitlen,
                                      primetype=self._primetype)
     else:
         q = p
         while True:
             q += 2 * random.randint(1, self._args.q_stepping)
             if NumberTheory.is_probable_prime(q):
                 yield q
Esempio n. 16
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        if (not self._args.force) and os.path.exists(self._args.outfile):
            raise UnfulfilledPrerequisitesException(
                "File/directory %s already exists. Remove it first or use --force."
                % (self._args.outfile))

        self._prime_db = PrimeDB(self._args.prime_db,
                                 generator_program=self._args.generator)
        q = self._prime_db.get(args.N_bits)
        if self._args.verbose >= 1:
            print("Chosen q = 0x%x" % (q))

        bit_diff = args.L_bits - q.bit_length()
        while True:
            r = NumberTheory.randint_bits(bit_diff, two_msb_set=True)
            p = (r * q) + 1
            if NumberTheory.is_probable_prime(p):
                break
        if self._args.verbose >= 1:
            print("Chosen p = 0x%x" % (p))

        assert (q.bit_length() == args.N_bits)
        assert (p.bit_length() == args.L_bits)
        assert ((p - 1) % q == 0)

        # Non-verifiable method of generating g, see A.2.1 of FIPS 186-4, pg. 41
        e = (p - 1) // q
        while True:
            h = random.randint(2, p - 2)
            g = pow(h, e, p)
            if g == 1:
                continue
            break

        if self._args.verbose >= 1:
            print("Chosen g = 0x%x" % (g))

        dsa_parameters = DSAParameters.create(p=p, q=q, g=g)
        dsa_parameters.write_pemfile(self._args.outfile)
Esempio n. 17
0
    def test_sqrt_3_mod_4(self):
        p = 9937818373633759003
        self.assertEqual(p % 4, 3)

        for value in [1, 123, 123456789, 0x123456789]:
            value = value % p
            sqr = (value * value) % p
            (sqrt_pos, sqrt_neg) = NumberTheory.sqrt_mod_p(sqr, p)
            self.assertEqual((sqrt_pos & 1), 0)
            self.assertEqual((sqrt_neg & 1), 1)
            self.assertEqual((sqrt_pos * sqrt_pos) % p, sqr)
            self.assertEqual((sqrt_neg * sqrt_neg) % p, sqr)
Esempio n. 18
0
 def point_addition(self, P, Q):
     if P is None:
         # O + Q = Q
         return Q
     elif Q is None:
         # P + O = P
         return P
     elif ((P.x == Q.x) and (((P.y + Q.y) % self.p) == 0)):
         # P + (-P) = O
         return None
     elif P == Q:
         # Point doubling
         s = ((3 * P.x**2) + self.a) * NumberTheory.modinv(2 * P.y, self.p)
         x = (s * s - (2 * P.x)) % self.p
         y = (s * (P.x - x) - P.y) % self.p
         return EllipticCurvePoint(self, x, y)
     else:
         # Point addition
         s = (P.y - Q.y) * NumberTheory.modinv(P.x - Q.x, self.p)
         x = ((s**2) - P.x - Q.x) % self.p
         y = (s * (P.x - x) - P.y) % self.p
         return EllipticCurvePoint(self, x, y)
Esempio n. 19
0
    def _judge_binary_field_curve(self, curve):
        judgements = SecurityJudgements()

        literature = LiteratureReference(
            author=["Steven D. Galbraith", "Shishay W. Gebregiyorgis"],
            title=
            "Summation polynomial algorithms for elliptic curves in characteristic two",
            year=2014,
            source="Progress in Cryptology -- INDOCRYPT 2014; LNCS 8885")
        judgements += SecurityJudgement(
            JudgementCode.X509Cert_PublicKey_ECC_DomainParameters_BinaryField,
            "Binary finite field elliptic curve is used. Recent advances in cryptography show there might be efficient attacks on such curves, hence it is recommended to use prime-field curves instead.",
            commonness=Commonness.UNUSUAL,
            literature=literature)

        EFpm = curve.n * curve.h
        if (EFpm % 2) == 1:
            # Supersingular: #E(F_p^m) = 1 mod p
            literature = LiteratureReference(
                author=[
                    "Alfred Menezes", "Scott Vanstone", "Tatsuaki Okamoto"
                ],
                title=
                "Reducing Elliptic Curve Logarithms to Logarithms in a Finite Field",
                year=1991,
                source="ACM")
            judgements += SecurityJudgement(
                JudgementCode.
                X509Cert_PublicKey_ECC_DomainParameters_CurveProperty_SupersingularCurve,
                "This curve is supersingular, #E(F_p^m) = 1 mod p. The curve can be attacked using an probabilistic polynomial-time MOV attack.",
                bits=0,
                commonness=Commonness.HIGHLY_UNUSUAL,
                literature=literature)

        if not NumberTheory.is_probable_prime(curve.m):
            literature = LiteratureReference(
                author=[
                    "Jeffrey Hoffstein", "Jill Pipher", "Joseph Silverman"
                ],
                title="An Introduction to Mathematical Cryptography",
                year=2008,
                source="Springer")
            judgements += SecurityJudgement(
                JudgementCode.
                X509Cert_PublicKey_ECC_DomainParameters_CurveProperty_WeilDescent,
                "Binary finite field elliptic curve has a field size that is non-primem, F(2^%d). Weil Descent attacks could be successful.",
                bits=0,
                commonness=Commonness.HIGHLY_UNUSUAL,
                literature=literature)

        return judgements
Esempio n. 20
0
    def create(cls,
               p,
               q,
               e=0x10001,
               swap_e_d=False,
               valid_only=True,
               carmichael_totient=False):
        n = p * q
        if not carmichael_totient:
            totient = (p - 1) * (q - 1)
        else:
            totient = NumberTheory.lcm(p - 1, q - 1)
        gcd = NumberTheory.gcd(e, totient)
        if (gcd != 1) and valid_only:
            raise KeyCorruptException(
                "e = 0x%x isnt't relative prime to totient, gcd = 0x%x. Either accept broken keys or fix e."
                % (e, gcd))
        d = NumberTheory.modinv(e, totient)
        if swap_e_d:
            (e, d) = (d, e)

        dmp1 = d % (p - 1)
        dmq1 = d % (q - 1)
        iqmp = NumberTheory.modinv(q, p)
        asn1 = cls._ASN1_MODEL()
        asn1["version"] = 0
        asn1["modulus"] = n
        asn1["publicExponent"] = e
        asn1["privateExponent"] = d
        asn1["prime1"] = p
        asn1["prime2"] = q
        asn1["exponent1"] = dmp1
        asn1["exponent2"] = dmq1
        asn1["coefficient"] = iqmp
        der = pyasn1.codec.der.encoder.encode(asn1)
        return cls(der)
Esempio n. 21
0
 def test_gcd_n_phi_n(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0x1fd22b50d1e28365855635,
                       0x3af25062dcf148b85084f5).write()
         output = self._run_x509sak(
             ["genbrokenrsa", "--bitlen", "257", "--gcd-n-phi-n",
              "-v"]).stdout
         key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0]
         self.assertEqual(key.n.bit_length(), 257)
         self.assertEqual(key.p, 0x1fd22b50d1e28365855635)
         self.assertEqual(key.q,
                          0xea778f672d05715314fd556a2667dca7743e33da973)
         self.assertEqual((key.q - 1) % (2 * key.p), 0)
         self.assertNotEqual(NumberTheory.gcd(key.n, key.phi_n), 1)
         self.assertEqual(key.e, 0x10001)
         self.assertIn(b"gcd(n, phi(n)) = p", output)
         key.check_integrity()
Esempio n. 22
0
    def analyze(self,
                signature_alg_oid,
                signature_alg_params,
                signature,
                root_cert=None):
        judgements = SecurityJudgements()
        signature_alg = SignatureAlgorithms.lookup("oid", signature_alg_oid)
        if signature_alg is None:
            judgements += SecurityJudgement(
                JudgementCode.X509Cert_Signature_Function_Unknown,
                "Certificate has unknown signature algorithm with OID %s. Cannot make security determination."
                % (signature_alg_oid),
                commonness=Commonness.HIGHLY_UNUSUAL,
                compatibility=Compatibility.LIMITED_SUPPORT)
            result = {
                "name": str(signature_alg_oid),
                "pretty": str(signature_alg_oid),
                "security": judgements,
            }
            return result

        if isinstance(signature_alg.value.oid, (tuple, list)):
            # Have more than one OID for this
            if signature_alg.value.oid[0] != signature_alg_oid:
                judgements += SecurityJudgement(
                    JudgementCode.X509Cert_Signature_Function_DeprecatedOID,
                    "Signature algorithm uses alternate OID %s for algorithm %s. Preferred OID would be %s."
                    % (signature_alg_oid, signature_alg.name,
                       signature_alg.value.oid[0]),
                    commonness=Commonness.HIGHLY_UNUSUAL,
                    compatibility=Compatibility.LIMITED_SUPPORT)

        if signature_alg.value.hash_fnc is not None:
            # Signature algorithm already implies a concrete hash function, already done.
            hash_fnc = signature_alg.value.hash_fnc
        else:
            # Signature algorithms depends and is not implied.
            (hash_fnc, new_judgements) = self._determine_hash_function(
                signature_alg, signature_alg_params)
            judgements += new_judgements

        if signature_alg.value.sig_fnc == SignatureFunctions.ecdsa:
            # Decode ECDSA signature
            asn1_details = ASN1Tools.safe_decode(
                signature, asn1_spec=rfc3279.ECDSA_Sig_Value())
            judgements += self._DER_VALIDATOR_ECDSA_SIGNATURE.validate(
                asn1_details)
            if (asn1_details.asn1 is not None) and (root_cert is not None):
                if root_cert.pubkey.pk_alg.value.cryptosystem == Cryptosystems.ECC_ECDSA:
                    # Check that this is really a potential parent CA certificate
                    ca_curve = root_cert.pubkey.curve
                    hweight_analysis = NumberTheory.hamming_weight_analysis(
                        int(asn1_details.asn1["r"]),
                        min_bit_length=ca_curve.field_bits)
                    if not hweight_analysis.plausibly_random:
                        judgements += SecurityJudgement(
                            JudgementCode.
                            X509Cert_Signature_ECDSA_R_BitBiasPresent,
                            "Hamming weight of ECDSA signature R parameter is %d at bitlength %d, but expected a weight between %d and %d when randomly chosen; this is likely not coincidential."
                            %
                            (hweight_analysis.hweight, hweight_analysis.bitlen,
                             hweight_analysis.rnd_min_hweight,
                             hweight_analysis.rnd_max_hweight),
                            commonness=Commonness.HIGHLY_UNUSUAL)
                    hweight_analysis = NumberTheory.hamming_weight_analysis(
                        int(asn1_details.asn1["s"]),
                        min_bit_length=ca_curve.field_bits)
                    if not hweight_analysis.plausibly_random:
                        judgements += SecurityJudgement(
                            JudgementCode.
                            X509Cert_Signature_ECDSA_S_BitBiasPresent,
                            "Hamming weight of ECDSA signature S parameter is %d at bitlength %d, but expected a weight between %d and %d when randomly chosen; this is likely not coincidential."
                            %
                            (hweight_analysis.hweight, hweight_analysis.bitlen,
                             hweight_analysis.rnd_min_hweight,
                             hweight_analysis.rnd_max_hweight),
                            commonness=Commonness.HIGHLY_UNUSUAL)

        elif signature_alg.value.sig_fnc == SignatureFunctions.dsa:
            # Decode DSA signature
            asn1_details = ASN1Tools.safe_decode(
                signature, asn1_spec=rfc3279.Dss_Sig_Value())
            judgements += self._DER_VALIDATOR_DSA_SIGNATURE.validate(
                asn1_details)
            if (asn1_details.asn1 is not None) and (root_cert is not None):
                if root_cert is not None:
                    if root_cert.pubkey.pk_alg.value.cryptosystem == Cryptosystems.DSA:
                        field_width = root_cert.pubkey.q.bit_length()

                        hweight_analysis = NumberTheory.hamming_weight_analysis(
                            int(asn1_details.asn1["r"]),
                            min_bit_length=field_width)
                        if not hweight_analysis.plausibly_random:
                            judgements += SecurityJudgement(
                                JudgementCode.
                                X509Cert_Signature_DSA_R_BitBiasPresent,
                                "Hamming weight of DSA signature R parameter is %d at bitlength %d, but expected a weight between %d and %d when randomly chosen; this is likely not coincidential."
                                % (hweight_analysis.hweight,
                                   hweight_analysis.bitlen,
                                   hweight_analysis.rnd_min_hweight,
                                   hweight_analysis.rnd_max_hweight),
                                commonness=Commonness.HIGHLY_UNUSUAL)

                        hweight_analysis = NumberTheory.hamming_weight_analysis(
                            int(asn1_details.asn1["s"]),
                            min_bit_length=field_width)
                        if not hweight_analysis.plausibly_random:
                            judgements += SecurityJudgement(
                                JudgementCode.
                                X509Cert_Signature_DSA_S_BitBiasPresent,
                                "Hamming weight of DSA signature S parameter is %d at bitlength %d, but expected a weight between %d and %d when randomly chosen; this is likely not coincidential."
                                % (hweight_analysis.hweight,
                                   hweight_analysis.bitlen,
                                   hweight_analysis.rnd_min_hweight,
                                   hweight_analysis.rnd_max_hweight),
                                commonness=Commonness.HIGHLY_UNUSUAL)

        result = {
            "name":
            signature_alg.name,
            "sig_fnc":
            self.algorithm("sig_fnc").analyze(signature_alg.value.sig_fnc),
            "security":
            judgements,
        }
        if hash_fnc is not None:
            result.update({
                "pretty":
                signature_alg.value.sig_fnc.value.pretty_name + " with " +
                hash_fnc.value.pretty_name,
                "hash_fnc":
                self.algorithm("hash_fnc").analyze(hash_fnc),
            })
        else:
            result.update({
                "pretty":
                "%s with undetermined hash function" %
                (signature_alg.value.sig_fnc.value.pretty_name)
            })
        return result
Esempio n. 23
0
 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))
Esempio n. 24
0
 def test_pollard_rho_success(self):
     p = 3513360553
     q = 2841366767
     n = p * q
     self.assertIn(NumberTheory.pollard_rho(n), [p, q])
Esempio n. 25
0
 def test_pollard_rho_prime(self):
     p = 2003
     self.assertIsNone(NumberTheory.pollard_rho(p), None)
Esempio n. 26
0
 def test_crt(self):
     moduli = {2: 1, 3: 2, 5: 3, 7: 4, 11: 5, 13: 6, 17: 7}
     solution = NumberTheory.solve_crt(moduli)
     for (modulus, remainder) in moduli.items():
         self.assertEqual(solution % modulus, remainder)
Esempio n. 27
0
 def test_modinv(self):
     p = 2003
     for _ in range(10):
         r = random.randint(2, p - 1)
         inv = NumberTheory.modinv(r, p)
         self.assertEqual(r * inv % p, 1)
Esempio n. 28
0
 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)
Esempio n. 29
0
 def test_factor(self):
     self.assertEqual(list(sorted(NumberTheory.factor(101 * 211))),
                      [101, 211])
     self.assertEqual(list(sorted(NumberTheory.factor(2**4))), [2, 2, 2, 2])
     self.assertEqual(list(sorted(NumberTheory.factor(2 * 2 * 3 * 3 * 5))),
                      [2, 2, 3, 3, 5])
Esempio n. 30
0
 def test_find_small_factor(self):
     self.assertEqual(NumberTheory.find_small_factor(7 * 2003), 7)
     self.assertEqual(NumberTheory.find_small_factor(2 * 2003), 2)
     self.assertEqual(NumberTheory.find_small_factor(71 * 2003), 71)
     self.assertEqual(NumberTheory.find_small_factor(2003), None)