Пример #1
0
    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
Пример #2
0
 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)
Пример #3
0
    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)
Пример #4
0
    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))
Пример #5
0
def generate(**kwargs):
    """Generate a new private key on the given curve.

    :Keywords:
      curve : string
        Mandatory. It must be "P-256", "prime256v1" or "secp256r1".
      randfunc : callable
        Optional. The RNG to read randomness from.
        If ``None``, the system source 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)
Пример #6
0
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.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 xrange(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 xrange(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
Пример #7
0
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.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 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 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
Пример #8
0
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
    # See Algorithm 4.80 in Handbook of Applied Cryptography
    # Note that the order of the group is n=p-1=2q, where q is prime
    while 1:
        # We must avoid g=2 because of Bleichenbacher's attack described
        # in "Generating ElGamal signatures without knowning the secret key",
        # 1996
        #
        obj.g = Integer.random_range(min_inclusive=3,
                                     max_exclusive=obj.p,
                                     randfunc=randfunc)
        safe = 1
        if pow(obj.g, 2, obj.p) == 1:
            safe = 0
        if safe and pow(obj.g, q, obj.p) == 1:
            safe = 0
        # Discard g if it divides p-1 because of the attack described
        # in Note 11.67 (iii) in HAC
        if safe and (obj.p - 1) % obj.g == 0:
            safe = 0
        # 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 safe and (obj.p - 1) % ginv == 0:
            safe = 0
        if safe:
            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
Пример #9
0
 def _compute_nonce(self, msg_hash):
     return Integer.random_range(min_inclusive=1,
                                 max_exclusive=_curve.order,
                                 randfunc=self._randfunc)
Пример #10
0
 def _compute_nonce(self, msg_hash):
     # hash is not used
     return Integer.random_range(min_inclusive=1,
                                 max_exclusive=self._order,
                                 randfunc=self._randfunc)
Пример #11
0
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
Пример #12
0
 def _compute_nonce(self, msg_hash):
     return Integer.random_range(min_inclusive=1,
                                 max_exclusive=_curve.order,
                                 randfunc=self._randfunc)
Пример #13
0
 def _compute_nonce(self, msg_hash):
     # hash is not used
     return Integer.random_range(min_inclusive=1,
                                 max_exclusive=self._order,
                                 randfunc=self._randfunc)
Пример #14
0
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).

    :Parameters:
        bits : int
            Key length, or size (in bits) of the modulus *p*.
            Recommended value is 2048.
        randfunc : callable
            Random number generation function; it should accept
            a single integer N and return a string of random data
            N bytes long.

    :attention: You should always use a cryptographically secure random number generator,
        such as the one defined in the ``Cryptodome.Random`` module; **don't** just use the
        current time and the ``random`` module.

    :Return: An ElGamal key object (`ElGamalKey`).
    """
    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
    # See Algorithm 4.80 in Handbook of Applied Cryptography
    # Note that the order of the group is n=p-1=2q, where q is prime
    while 1:
        # We must avoid g=2 because of Bleichenbacher's attack described
        # in "Generating ElGamal signatures without knowning the secret key",
        # 1996
        #
        obj.g = Integer.random_range(min_inclusive=3,
                                     max_exclusive=obj.p,
                                     randfunc=randfunc)
        safe = 1
        if pow(obj.g, 2, obj.p)==1:
            safe=0
        if safe and pow(obj.g, q, obj.p)==1:
            safe=0
        # Discard g if it divides p-1 because of the attack described
        # in Note 11.67 (iii) in HAC
        if safe and (obj.p-1) % obj.g == 0:
            safe=0
        # 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 safe and (obj.p-1) % ginv == 0:
            safe=0
        if safe:
            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