def __mul__(self, scalar): """Return a new point, the scalar product of this one""" if scalar < 0: raise ValueError("Scalar multiplication only defined for non-negative integers") # Trivial results if scalar == 0 or self.is_point_at_infinity(): return self.point_at_infinity() elif scalar == 1: return self.copy() # Scalar randomization scalar_blind = Integer.random(exact_bits=64) * _curve.order + scalar # Montgomery key ladder r = [self.point_at_infinity().copy(), self.copy()] bit_size = int(scalar_blind.size_in_bits()) scalar_int = int(scalar_blind) for i in range(bit_size, -1, -1): di = scalar_int >> i & 1 r[di ^ 1] += r[di] r[di].double() return r[0]
def generate_probable_prime(**kwargs): """Generate a random probable prime. The prime will not have any specific properties (e.g. it will not be a *strong* prime). Random numbers are evaluated for primality until one passes all tests, consisting of a certain number of Miller-Rabin tests with random bases followed by a single Lucas test. The number of Miller-Rabin iterations is chosen such that the probability that the output number is a non-prime is less than 1E-30 (roughly 2^{-100}). This approach is compliant to `FIPS PUB 186-4`__. :Keywords: exact_bits : integer The desired size in bits of the probable prime. It must be at least 160. randfunc : callable An RNG function where candidate primes are taken from. prime_filter : callable A function that takes an Integer as parameter and returns True if the number can be passed to further primality tests, False if it should be immediately discarded. :Return: A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1). .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf """ exact_bits = kwargs.pop("exact_bits", None) randfunc = kwargs.pop("randfunc", None) prime_filter = kwargs.pop("prime_filter", lambda x: True) if kwargs: raise ValueError("Unknown parameters: " + kwargs.keys()) if exact_bits is None: raise ValueError("Missing exact_bits parameter") if exact_bits < 160: raise ValueError("Prime number is not big enough.") if randfunc is None: randfunc = Random.new().read result = COMPOSITE while result == COMPOSITE: candidate = Integer.random(exact_bits=exact_bits, randfunc=randfunc) | 1 if not prime_filter(candidate): continue result = test_probable_prime(candidate, randfunc) return candidate
def _get_weak_domain(self): from crypto.Math.Numbers import Integer from crypto.Math import Primality p = Integer(4) while p.size_in_bits() != 1024 or Primality.test_probable_prime( p) != Primality.PROBABLY_PRIME: q1 = Integer.random(exact_bits=80) q2 = Integer.random(exact_bits=80) q = q1 * q2 z = Integer.random(exact_bits=1024 - 160) p = z * q + 1 h = Integer(2) g = 1 while g == 1: g = pow(h, z, p) h += 1 return (p, q, g)
def generate(bits, randfunc=None, domain=None): """Generate a new DSA key pair. The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_, respectively for domain generation and key pair generation. Args: bits (integer): Key length, or size (in bits) of the DSA modulus *p*. It must be 1024, 2048 or 3072. randfunc (callable): Random number generation function; it accepts a single integer N and return a string of random data N bytes long. If not specified, :func:`crypto.Random.get_random_bytes` is used. domain (tuple): The DSA domain parameters *p*, *q* and *g* as a list of 3 integers. Size of *p* and *q* must comply to `FIPS 186-4`_. If not specified, the parameters are created anew. Returns: :class:`DsaKey` : a new DSA key object Raises: ValueError : when **bits** is too little, too big, or not a multiple of 64. .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf """ if randfunc is None: randfunc = Random.get_random_bytes if domain: p, q, g = map(Integer, domain) ## Perform consistency check on domain parameters # P and Q must be prime fmt_error = test_probable_prime(p) == COMPOSITE fmt_error = test_probable_prime(q) == COMPOSITE # Verify Lagrange's theorem for sub-group fmt_error |= ((p - 1) % q) != 0 fmt_error |= g <= 1 or g >= p fmt_error |= pow(g, q, p) != 1 if fmt_error: raise ValueError("Invalid DSA domain parameters") else: p, q, g, _ = _generate_domain(bits, randfunc) L = p.size_in_bits() N = q.size_in_bits() if L != bits: raise ValueError("Mismatch between size of modulus (%d)" " and 'bits' parameter (%d)" % (L, bits)) if (L, N) not in [(1024, 160), (2048, 224), (2048, 256), (3072, 256)]: raise ValueError("Lengths of p and q (%d, %d) are not compatible" "to FIPS 186-3" % (L, N)) if not 1 < g < p: raise ValueError("Incorrent DSA generator") # B.1.1 c = Integer.random(exact_bits=N + 64, randfunc=randfunc) x = c % (q - 1) + 1 # 1 <= x <= q-1 y = pow(g, x, p) key_dict = {'y': y, 'g': g, 'p': p, 'q': q, 'x': x} return DsaKey(key_dict)