def _decrypt(self, ciphertext): if not 0 < ciphertext < self._n: raise ValueError("Ciphertext too large") if not self.has_private(): raise TypeError("This is not a private key") # Blinded RSA decryption (to prevent timing attacks): # Step 1: Generate random secret blinding factor r, # such that 0 < r < n-1 r = Integer.random_range(min_inclusive=1, max_exclusive=self._n) # Step 2: Compute c' = c * r**e mod n cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n # Step 3: Compute m' = c'**d mod n (ordinary RSA decryption) m1 = pow(cp, self._d % (self._p - 1), self._p) m2 = pow(cp, self._d % (self._q - 1), self._q) h = m2 - m1 while h < 0: h += self._q h = (h * self._u) % self._q mp = h * self._p + m1 # Step 4: Compute m = m**(r-1) mod n result = (r.inverse(self._n) * mp) % self._n # Verify no faults occured if ciphertext != pow(result, self._e, self._n): raise ValueError("Fault detected in RSA decryption") return result
def _decrypt(self, M): if (not hasattr(self, 'x')): raise TypeError('Private key not available in this object') r = Integer.random_range(min_inclusive=2, max_exclusive=self.p - 1, randfunc=self._randfunc) a_blind = (pow(self.g, r, self.p) * M[0]) % self.p ax = pow(a_blind, self.x, self.p) plaintext_blind = (ax.inverse(self.p) * M[1]) % self.p plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p return int(plaintext)
def _sign(self, z, k): assert 0 < k < _curve.order blind = Integer.random_range(min_inclusive=1, max_exclusive=_curve.order) blind_d = self._d * blind inv_blind_k = (blind * k).inverse(_curve.order) r = (_curve.G * k).x % _curve.order s = inv_blind_k * (blind * z + blind_d * r) % _curve.order return (r, s)
def _sign(self, m, k): if not self.has_private(): raise TypeError("DSA public key cannot be used for signing") if not (1 < k < self.q): raise ValueError("k is not between 2 and q-1") x, q, p, g = [self._key[comp] for comp in ['x', 'q', 'p', 'g']] blind_factor = Integer.random_range(min_inclusive=1, max_exclusive=q) inv_blind_k = (blind_factor * k).inverse(q) blind_x = x * blind_factor r = pow(g, k, p) % q # r = (g**k mod p) mod q s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q return map(int, (r, s))
def generate(**kwargs): """Generate a new private key on the given curve. Args: curve (string): Mandatory. It must be "P-256", "prime256v1" or "secp256r1". randfunc (callable): Optional. The RNG to read randomness from. If ``None``, :func:`Crypto.Random.get_random_bytes` is used. """ curve = kwargs.pop("curve") randfunc = kwargs.pop("randfunc", get_random_bytes) if kwargs: raise TypeError("Unknown parameters: " + str(kwargs)) d = Integer.random_range(min_inclusive=1, max_exclusive=_curve.order, randfunc=randfunc) return EccKey(curve=curve, d=d)
def miller_rabin_test(candidate, iterations, randfunc=None): """Perform a Miller-Rabin primality test on an integer. The test is specified in Section C.3.1 of `FIPS PUB 186-4`__. :Parameters: candidate : integer The number to test for primality. iterations : integer The maximum number of iterations to perform before declaring a candidate a probable prime. randfunc : callable An RNG function where bases are taken from. :Returns: ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf """ if not isinstance(candidate, Integer): candidate = Integer(candidate) if candidate in (1, 2, 3, 5): return PROBABLY_PRIME if candidate.is_even(): return COMPOSITE one = Integer(1) minus_one = Integer(candidate - 1) if randfunc is None: randfunc = Random.new().read # Step 1 and 2 m = Integer(minus_one) a = 0 while m.is_even(): m >>= 1 a += 1 # Skip step 3 # Step 4 for i in iter_range(iterations): # Step 4.1-2 base = 1 while base in (one, minus_one): base = Integer.random_range(min_inclusive=2, max_inclusive=candidate - 2) assert (2 <= base <= candidate - 2) # Step 4.3-4.4 z = pow(base, m, candidate) if z in (one, minus_one): continue # Step 4.5 for j in iter_range(1, a): z = pow(z, 2, candidate) if z == minus_one: break if z == one: return COMPOSITE else: return COMPOSITE # Step 5 return PROBABLY_PRIME
def _compute_nonce(self, msg_hash): return Integer.random_range(min_inclusive=1, max_exclusive=self._key._curve.order, randfunc=self._randfunc)
def _compute_nonce(self, msg_hash): # hash is not used return Integer.random_range(min_inclusive=1, max_exclusive=self._order, randfunc=self._randfunc)
def generate(bits, randfunc): """Randomly generate a fresh, new ElGamal key. The key will be safe for use for both encryption and signature (although it should be used for **only one** purpose). Args: bits (int): Key length, or size (in bits) of the modulus *p*. The recommended value is 2048. randfunc (callable): Random number generation function; it should accept a single integer *N* and return a string of random *N* random bytes. Return: an :class:`ElGamalKey` object """ obj = ElGamalKey() # Generate a safe prime p # See Algorithm 4.86 in Handbook of Applied Cryptography obj.p = generate_probable_safe_prime(exact_bits=bits, randfunc=randfunc) q = (obj.p - 1) >> 1 # Generate generator g while 1: # Choose a square residue; it will generate a cyclic group of order q. obj.g = pow( Integer.random_range(min_inclusive=2, max_exclusive=obj.p, randfunc=randfunc), 2, obj.p) # We must avoid g=2 because of Bleichenbacher's attack described # in "Generating ElGamal signatures without knowning the secret key", # 1996 if obj.g in (1, 2): continue # Discard g if it divides p-1 because of the attack described # in Note 11.67 (iii) in HAC if (obj.p - 1) % obj.g == 0: continue # g^{-1} must not divide p-1 because of Khadir's attack # described in "Conditions of the generator for forging ElGamal # signature", 2011 ginv = obj.g.inverse(obj.p) if (obj.p - 1) % ginv == 0: continue # Found break # Generate private key x obj.x = Integer.random_range(min_inclusive=2, max_exclusive=obj.p - 1, randfunc=randfunc) # Generate public key y obj.y = pow(obj.g, obj.x, obj.p) return obj