def _generate_domain(L, randfunc): """Generate a new set of DSA domain parameters""" N = {1024: 160, 2048: 224, 3072: 256}.get(L) if N is None: raise ValueError("Invalid modulus length (%d)" % L) outlen = SHA256.digest_size * 8 n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1 b_ = L - 1 - (n * outlen) # Generate q (A.1.1.2) q = Integer(4) upper_bit = 1 << (N - 1) while test_probable_prime(q, randfunc) != PROBABLY_PRIME: seed = randfunc(64) U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1) q = U | upper_bit | 1 assert (q.size_in_bits() == N) # Generate p (A.1.1.2) offset = 1 upper_bit = 1 << (L - 1) while True: V = [ SHA256.new(seed + Integer(offset + j).to_bytes()).digest() for j in iter_range(n + 1) ] V = [Integer.from_bytes(v) for v in V] W = sum([V[i] * (1 << (i * outlen)) for i in iter_range(n)], (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen))) X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L} assert (X.size_in_bits() == L) c = X % (q * 2) p = X - (c - 1) # 2q divides (p-1) if p.size_in_bits() == L and \ test_probable_prime(p, randfunc) == PROBABLY_PRIME: break offset += n + 1 # Generate g (A.2.3, index=1) e = (p - 1) // q for count in itertools.count(1): U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes() W = Integer.from_bytes(SHA256.new(U).digest()) g = pow(W, e, p) if g != 1: break return (p, q, g, seed)
def _generate_domain(L, randfunc): """Generate a new set of DSA domain parameters""" N = { 1024:160, 2048:224, 3072:256 }.get(L) if N is None: raise ValueError("Invalid modulus length (%d)" % L) outlen = SHA256.digest_size * 8 n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1 b_ = L - 1 - (n * outlen) # Generate q (A.1.1.2) q = Integer(4) upper_bit = 1 << (N - 1) while test_probable_prime(q, randfunc) != PROBABLY_PRIME: seed = randfunc(64) U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1) q = U | upper_bit | 1 assert(q.size_in_bits() == N) # Generate p (A.1.1.2) offset = 1 upper_bit = 1 << (L - 1) while True: V = [ SHA256.new(seed + Integer(offset + j).to_bytes()).digest() for j in iter_range(n + 1) ] V = [ Integer.from_bytes(v) for v in V ] W = sum([V[i] * (1 << (i * outlen)) for i in iter_range(n)], (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen))) X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L} assert(X.size_in_bits() == L) c = X % (q * 2) p = X - (c - 1) # 2q divides (p-1) if p.size_in_bits() == L and \ test_probable_prime(p, randfunc) == PROBABLY_PRIME: break offset += n + 1 # Generate g (A.2.3, index=1) e = (p - 1) // q for count in itertools.count(1): U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes() W = Integer.from_bytes(SHA256.new(U).digest()) g = pow(W, e, p) if g != 1: break return (p, q, g, seed)
def MGF1(mgfSeed, maskLen, hash_gen): """Mask Generation Function, described in `B.2.1 of RFC8017 <https://tools.ietf.org/html/rfc8017>`_. :param mfgSeed: seed from which the mask is generated :type mfgSeed: byte string :param maskLen: intended length in bytes of the mask :type maskLen: integer :param hash_gen: A module or a hash object from :mod:`Cryptodome.Hash` :type hash_object: :return: the mask, as a *byte string* """ T = b"" for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)): c = long_to_bytes(counter, 4) hobj = hash_gen.new() hobj.update(mgfSeed + c) T = T + hobj.digest() assert (len(T) >= maskLen) return T[:maskLen]
def MGF1(mgfSeed, maskLen, hash_gen): """Mask Generation Function, described in `B.2.1 of RFC8017 <https://tools.ietf.org/html/rfc8017>`_. :param mfgSeed: seed from which the mask is generated :type mfgSeed: byte string :param maskLen: intended length in bytes of the mask :type maskLen: integer :param hash_gen: A module or a hash object from :mod:`Cryptodome.Hash` :type hash_object: :return: the mask, as a *byte string* """ T = b"" for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)): c = long_to_bytes(counter, 4) hobj = hash_gen.new() hobj.update(mgfSeed + c) T = T + hobj.digest() assert(len(T) >= maskLen) return T[:maskLen]
def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None): """Derive one key from a password (or passphrase). This function performs key derivation according to an old version of the PKCS#5 standard (v1.5) or `RFC2898 <https://www.ietf.org/rfc/rfc2898.txt>`_. .. warning:: Newer applications should use the more secure and versatile :func:`PBKDF2` instead. Args: password (string): The secret password to generate the key from. salt (byte string): An 8 byte string to use for better protection from dictionary attacks. This value does not need to be kept secret, but it should be randomly chosen for each derivation. dkLen (integer): The length of the desired key. The default is 16 bytes, suitable for instance for :mod:`Cryptodome.Cipher.AES`. count (integer): The number of iterations to carry out. The recommendation is 1000 or more. hashAlgo (module): The hash algorithm to use, as a module or an object from the :mod:`Cryptodome.Hash` package. The digest length must be no shorter than ``dkLen``. The default algorithm is :mod:`Cryptodome.Hash.SHA1`. Return: A byte string of length ``dkLen`` that can be used as key. """ if not hashAlgo: hashAlgo = SHA1 password = tobytes(password) pHash = hashAlgo.new(password + salt) digest = pHash.digest_size if dkLen > digest: raise TypeError( "Selected hash algorithm has a too short digest (%d bytes)." % digest) if len(salt) != 8: raise ValueError("Salt is not 8 bytes long (%d bytes instead)." % len(salt)) for i in iter_range(count - 1): pHash = pHash.new(pHash.digest()) return pHash.digest()[:dkLen]
def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen): """ Implement the ``EMSA-PSS-ENCODE`` function, as defined in PKCS#1 v2.1 (RFC3447, 9.1.1). The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` as input, and hash it internally. Here, we expect that the message has already been hashed instead. :Parameters: mhash : hash object The hash object that holds the digest of the message being signed. emBits : int Maximum length of the final encoding, in bits. randFunc : callable An RNG function that accepts as only parameter an int, and returns a string of random bytes, to be used as salt. mgf : callable A mask generation function that accepts two parameters: a string to use as seed, and the lenth of the mask to generate, in bytes. sLen : int Length of the salt, in bytes. :Return: An ``emLen`` byte long string that encodes the hash (with ``emLen = \ceil(emBits/8)``). :Raise ValueError: When digest or salt length are too big. """ emLen = ceil_div(emBits, 8) # Bitmask of digits that fill up lmask = 0 for i in iter_range(8 * emLen - emBits): lmask = lmask >> 1 | 0x80 # Step 1 and 2 have been already done # Step 3 if emLen < mhash.digest_size + sLen + 2: raise ValueError("Digest or salt length are too long" " for given key size.") # Step 4 salt = randFunc(sLen) # Step 5 m_prime = bchr(0) * 8 + mhash.digest() + salt # Step 6 h = mhash.new() h.update(m_prime) # Step 7 ps = bchr(0) * (emLen - sLen - mhash.digest_size - 2) # Step 8 db = ps + bchr(1) + salt # Step 9 dbMask = mgf(h.digest(), emLen - mhash.digest_size - 1) # Step 10 maskedDB = strxor(db, dbMask) # Step 11 maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] # Step 12 em = maskedDB + h.digest() + bchr(0xBC) return em
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 lucas_test(candidate): """Perform a Lucas primality test on an integer. The test is specified in Section C.3.3 of `FIPS PUB 186-4`__. :Parameters: candidate : integer The number to test for primality. :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) # Step 1 if candidate in (1, 2, 3, 5): return PROBABLY_PRIME if candidate.is_even() or candidate.is_perfect_square(): return COMPOSITE # Step 2 def alternate(): value = 5 while True: yield value if value > 0: value += 2 else: value -= 2 value = -value for D in alternate(): if candidate in (D, -D): continue js = Integer.jacobi_symbol(D, candidate) if js == 0: return COMPOSITE if js == -1: break # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer) # Step 3 # This is \delta(n) = n - jacobi(D/n) K = candidate + 1 # Step 4 r = K.size_in_bits() - 1 # Step 5 # U_1=1 and V_1=P U_i = Integer(1) V_i = Integer(1) U_temp = Integer(0) V_temp = Integer(0) # Step 6 for i in iter_range(r - 1, -1, -1): # Square # U_temp = U_i * V_i % candidate U_temp.set(U_i) U_temp *= V_i U_temp %= candidate # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate V_temp.set(U_i) V_temp *= U_i V_temp *= D V_temp.multiply_accumulate(V_i, V_i) if V_temp.is_odd(): V_temp += candidate V_temp >>= 1 V_temp %= candidate # Multiply if K.get_bit(i): # U_i = (((U_temp + V_temp) * K) >> 1) % candidate U_i.set(U_temp) U_i += V_temp if U_i.is_odd(): U_i += candidate U_i >>= 1 U_i %= candidate # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate V_i.set(V_temp) V_i.multiply_accumulate(U_temp, D) if V_i.is_odd(): V_i += candidate V_i >>= 1 V_i %= candidate else: U_i.set(U_temp) V_i.set(V_temp) # Step 7 if U_i == 0: return PROBABLY_PRIME return COMPOSITE
def scrypt(password, salt, key_len, N, r, p, num_keys=1): """Derive one or more keys from a passphrase. This function performs key derivation according to the `scrypt`_ algorithm, introduced in Percival's paper `"Stronger key derivation via sequential memory-hard functions"`__. This implementation is based on `RFC7914`__. Args: password (string): The secret pass phrase to generate the keys from. salt (string): A string to use for better protection from dictionary attacks. This value does not need to be kept secret, but it should be randomly chosen for each derivation. It is recommended to be at least 8 bytes long. key_len (integer): The length in bytes of every derived key. N (integer): CPU/Memory cost parameter. It must be a power of 2 and less than :math:`2^{32}`. r (integer): Block size parameter. p (integer): Parallelization parameter. It must be no greater than :math:`(2^{32}-1)/(4r)`. num_keys (integer): The number of keys to derive. Every key is :data:`key_len` bytes long. By default, only 1 key is generated. The maximum cumulative length of all keys is :math:`(2^{32}-1)*32` (that is, 128TB). A good choice of parameters *(N, r , p)* was suggested by Colin Percival in his `presentation in 2009`__: - *(16384, 8, 1)* for interactive logins (<=100ms) - *(1048576, 8, 1)* for file encryption (<=5s) Return: A byte string or a tuple of byte strings. .. _scrypt: http://www.tarsnap.com/scrypt.html .. __: http://www.tarsnap.com/scrypt/scrypt.pdf .. __: https://tools.ietf.org/html/rfc7914 .. __: http://www.tarsnap.com/scrypt/scrypt-slides.pdf """ if 2**(bit_size(N) - 1) != N: raise ValueError("N must be a power of 2") if N >= 2**32: raise ValueError("N is too big") if p > ((2**32 - 1) * 32) // (128 * r): raise ValueError("p or r are too big") prf_hmac_sha256 = lambda p, s: HMAC.new(p, s, SHA256).digest() stage_1 = PBKDF2(password, salt, p * 128 * r, 1, prf=prf_hmac_sha256) scryptROMix = _raw_scrypt_lib.scryptROMix core = _raw_salsa20_lib.Salsa20_8_core # Parallelize into p flows data_out = [] for flow in iter_range(p): idx = flow * 128 * r buffer_out = create_string_buffer(128 * r) result = scryptROMix(stage_1[idx:idx + 128 * r], buffer_out, c_size_t(128 * r), N, core) if result: raise ValueError("Error %X while running scrypt" % result) data_out += [get_raw_buffer(buffer_out)] dk = PBKDF2(password, b"".join(data_out), key_len * num_keys, 1, prf=prf_hmac_sha256) if num_keys == 1: return dk kol = [ dk[idx:idx + key_len] for idx in iter_range(0, key_len * num_keys, key_len) ] return kol
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 _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen): """ Implement the ``EMSA-PSS-VERIFY`` function, as defined in PKCS#1 v2.1 (RFC3447, 9.1.2). ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, and hash it internally. Here, we expect that the message has already been hashed instead. :Parameters: mhash : hash object The hash object that holds the digest of the message to be verified. em : string The signature to verify, therefore proving that the sender really signed the message that was received. emBits : int Length of the final encoding (em), in bits. mgf : callable A mask generation function that accepts two parameters: a string to use as seed, and the lenth of the mask to generate, in bytes. sLen : int Length of the salt, in bytes. :Raise ValueError: When the encoding is inconsistent, or the digest or salt lengths are too big. """ emLen = ceil_div(emBits, 8) # Bitmask of digits that fill up lmask = 0 for i in iter_range(8*emLen-emBits): lmask = lmask >> 1 | 0x80 # Step 1 and 2 have been already done # Step 3 if emLen < mhash.digest_size+sLen+2: return False # Step 4 if ord(em[-1:]) != 0xBC: raise ValueError("Incorrect signature") # Step 5 maskedDB = em[:emLen-mhash.digest_size-1] h = em[emLen-mhash.digest_size-1:-1] # Step 6 if lmask & bord(em[0]): raise ValueError("Incorrect signature") # Step 7 dbMask = mgf(h, emLen-mhash.digest_size-1) # Step 8 db = strxor(maskedDB, dbMask) # Step 9 db = bchr(bord(db[0]) & ~lmask) + db[1:] # Step 10 if not db.startswith(bchr(0)*(emLen-mhash.digest_size-sLen-2) + bchr(1)): raise ValueError("Incorrect signature") # Step 11 if sLen > 0: salt = db[-sLen:] else: salt = b"" # Step 12 m_prime = bchr(0)*8 + mhash.digest() + salt # Step 13 hobj = mhash.new() hobj.update(m_prime) hp = hobj.digest() # Step 14 if h != hp: raise ValueError("Incorrect signature")
def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen): """ Implement the ``EMSA-PSS-ENCODE`` function, as defined in PKCS#1 v2.1 (RFC3447, 9.1.1). The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` as input, and hash it internally. Here, we expect that the message has already been hashed instead. :Parameters: mhash : hash object The hash object that holds the digest of the message being signed. emBits : int Maximum length of the final encoding, in bits. randFunc : callable An RNG function that accepts as only parameter an int, and returns a string of random bytes, to be used as salt. mgf : callable A mask generation function that accepts two parameters: a string to use as seed, and the lenth of the mask to generate, in bytes. sLen : int Length of the salt, in bytes. :Return: An ``emLen`` byte long string that encodes the hash (with ``emLen = \ceil(emBits/8)``). :Raise ValueError: When digest or salt length are too big. """ emLen = ceil_div(emBits, 8) # Bitmask of digits that fill up lmask = 0 for i in iter_range(8*emLen-emBits): lmask = lmask >> 1 | 0x80 # Step 1 and 2 have been already done # Step 3 if emLen < mhash.digest_size+sLen+2: raise ValueError("Digest or salt length are too long" " for given key size.") # Step 4 salt = randFunc(sLen) # Step 5 m_prime = bchr(0)*8 + mhash.digest() + salt # Step 6 h = mhash.new() h.update(m_prime) # Step 7 ps = bchr(0)*(emLen-sLen-mhash.digest_size-2) # Step 8 db = ps + bchr(1) + salt # Step 9 dbMask = mgf(h.digest(), emLen-mhash.digest_size-1) # Step 10 maskedDB = strxor(db, dbMask) # Step 11 maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] # Step 12 em = maskedDB + h.digest() + bchr(0xBC) return em
def _tonelli_shanks(n, p): """Tonelli-shanks algorithm for computing the square root of n modulo a prime p. n must be in the range [0..p-1]. p must be at least even. The return value r is the square root of modulo p. If non-zero, another solution will also exist (p-r). Note we cannot assume that p is really a prime: if it's not, we can either raise an exception or return the correct value. """ # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm if n in (0, 1): return n if p % 4 == 3: root = pow(n, (p + 1) // 4, p) if pow(root, 2, p) != n: raise ValueError("Cannot compute square root") return root s = 1 q = (p - 1) // 2 while not (q & 1): s += 1 q >>= 1 z = n.__class__(2) while True: euler = pow(z, (p - 1) // 2, p) if euler == 1: z += 1 continue if euler == p - 1: break # Most probably p is not a prime raise ValueError("Cannot compute square root") m = s c = pow(z, q, p) t = pow(n, q, p) r = pow(n, (q + 1) // 2, p) while t != 1: for i in iter_range(0, m): if pow(t, 2**i, p) == 1: break if i == m: raise ValueError("Cannot compute square root of %d mod %d" % (n, p)) b = pow(c, 2**(m - i - 1), p) m = i c = b**2 % p t = (t * b**2) % p r = (r * b) % p if pow(r, 2, p) != n: raise ValueError("Cannot compute square root") return r
def _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen): """ Implement the ``EMSA-PSS-VERIFY`` function, as defined in PKCS#1 v2.1 (RFC3447, 9.1.2). ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, and hash it internally. Here, we expect that the message has already been hashed instead. :Parameters: mhash : hash object The hash object that holds the digest of the message to be verified. em : string The signature to verify, therefore proving that the sender really signed the message that was received. emBits : int Length of the final encoding (em), in bits. mgf : callable A mask generation function that accepts two parameters: a string to use as seed, and the lenth of the mask to generate, in bytes. sLen : int Length of the salt, in bytes. :Raise ValueError: When the encoding is inconsistent, or the digest or salt lengths are too big. """ emLen = ceil_div(emBits, 8) # Bitmask of digits that fill up lmask = 0 for i in iter_range(8 * emLen - emBits): lmask = lmask >> 1 | 0x80 # Step 1 and 2 have been already done # Step 3 if emLen < mhash.digest_size + sLen + 2: raise ValueError("Incorrect signature") # Step 4 if ord(em[-1:]) != 0xBC: raise ValueError("Incorrect signature") # Step 5 maskedDB = em[:emLen - mhash.digest_size - 1] h = em[emLen - mhash.digest_size - 1:-1] # Step 6 if lmask & bord(em[0]): raise ValueError("Incorrect signature") # Step 7 dbMask = mgf(h, emLen - mhash.digest_size - 1) # Step 8 db = strxor(maskedDB, dbMask) # Step 9 db = bchr(bord(db[0]) & ~lmask) + db[1:] # Step 10 if not db.startswith( bchr(0) * (emLen - mhash.digest_size - sLen - 2) + bchr(1)): raise ValueError("Incorrect signature") # Step 11 if sLen > 0: salt = db[-sLen:] else: salt = b"" # Step 12 m_prime = bchr(0) * 8 + mhash.digest() + salt # Step 13 hobj = mhash.new() hobj.update(m_prime) hp = hobj.digest() # Step 14 if h != hp: raise ValueError("Incorrect signature")
def HKDF(master, key_len, salt, hashmod, num_keys=1, context=None): """Derive one or more keys from a master secret using the HMAC-based KDF defined in RFC5869_. This KDF is not suitable for deriving keys from a password or for key stretching. Use :func:`PBKDF2` instead. HKDF is a key derivation method approved by NIST in `SP 800 56C`__. Args: master (byte string): The unguessable value used by the KDF to generate the other keys. It must be a high-entropy secret, though not necessarily uniform. It must not be a password. salt (byte string): A non-secret, reusable value that strengthens the randomness extraction step. Ideally, it is as long as the digest size of the chosen hash. If empty, a string of zeroes in used. key_len (integer): The length in bytes of every derived key. hashmod (module): A cryptographic hash algorithm from :mod:`Cryptodome.Hash`. :mod:`Cryptodome.Hash.SHA512` is a good choice. num_keys (integer): The number of keys to derive. Every key is :data:`key_len` bytes long. The maximum cumulative length of all keys is 255 times the digest size. context (byte string): Optional identifier describing what the keys are used for. Return: A byte string or a tuple of byte strings. .. _RFC5869: http://tools.ietf.org/html/rfc5869 .. __: http://csrc.nist.gov/publications/nistpubs/800-56C/SP-800-56C.pdf """ output_len = key_len * num_keys if output_len > (255 * hashmod.digest_size): raise ValueError("Too much secret data to derive") if not salt: salt = b'\x00' * hashmod.digest_size if context is None: context = b"" # Step 1: extract hmac = HMAC.new(salt, master, digestmod=hashmod) prk = hmac.digest() # Step 2: expand t = [b""] n = 1 tlen = 0 while tlen < output_len: hmac = HMAC.new(prk, t[-1] + context + struct.pack('B', n), digestmod=hashmod) t.append(hmac.digest()) tlen += hashmod.digest_size n += 1 derived_output = b"".join(t) if num_keys == 1: return derived_output[:key_len] kol = [ derived_output[idx:idx + key_len] for idx in iter_range(0, output_len, key_len) ] return list(kol[:num_keys])
def _tonelli_shanks(n, p): """Tonelli-shanks algorithm for computing the square root of n modulo a prime p. n must be in the range [0..p-1]. p must be at least even. The return value r is the square root of modulo p. If non-zero, another solution will also exist (p-r). Note we cannot assume that p is really a prime: if it's not, we can either raise an exception or return the correct value. """ # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm if n in (0, 1): return n if p % 4 == 3: root = pow(n, (p + 1) // 4, p) if pow(root, 2, p) != n: raise ValueError("Cannot compute square root") return root s = 1 q = (p - 1) // 2 while not (q & 1): s += 1 q >>= 1 z = n.__class__(2) while True: euler = pow(z, (p - 1) // 2, p) if euler == 1: z += 1 continue if euler == p - 1: break # Most probably p is not a prime raise ValueError("Cannot compute square root") m = s c = pow(z, q, p) t = pow(n, q, p) r = pow(n, (q + 1) // 2, p) while t != 1: for i in iter_range(0, m): if pow(t, 2**i, p) == 1: break if i == m: raise ValueError("Cannot compute square root of %d mod %d" % (n, p)) b = pow(c, 2**(m - i - 1), p) m = i c = b**2 % p t = (t * b**2) % p r = (r * b) % p if pow(r, 2, p) != n: raise ValueError("Cannot compute square root") return r
def lucas_test(candidate): """Perform a Lucas primality test on an integer. The test is specified in Section C.3.3 of `FIPS PUB 186-4`__. :Parameters: candidate : integer The number to test for primality. :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) # Step 1 if candidate in (1, 2, 3, 5): return PROBABLY_PRIME if candidate.is_even() or candidate.is_perfect_square(): return COMPOSITE # Step 2 def alternate(): value = 5 while True: yield value if value > 0: value += 2 else: value -= 2 value = -value for D in alternate(): if candidate in (D, -D): continue js = Integer.jacobi_symbol(D, candidate) if js == 0: return COMPOSITE if js == -1: break # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer) # Step 3 # This is \delta(n) = n - jacobi(D/n) K = candidate + 1 # Step 4 r = K.size_in_bits() - 1 # Step 5 # U_1=1 and V_1=P U_i = Integer(1) V_i = Integer(1) U_temp = Integer(0) V_temp = Integer(0) # Step 6 for i in iter_range(r - 1, -1, -1): # Square # U_temp = U_i * V_i % candidate U_temp.set(U_i) U_temp *= V_i U_temp %= candidate # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate V_temp.set(U_i) V_temp *= U_i V_temp *= D V_temp.multiply_accumulate(V_i, V_i) if V_temp.is_odd(): V_temp += candidate V_temp >>= 1 V_temp %= candidate # Multiply if K.get_bit(i): # U_i = (((U_temp + V_temp) * K) >> 1) % candidate U_i.set(U_temp) U_i += V_temp if U_i.is_odd(): U_i += candidate U_i >>= 1 U_i %= candidate # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate V_i.set(V_temp) V_i.multiply_accumulate(U_temp, D) if V_i.is_odd(): V_i += candidate V_i >>= 1 V_i %= candidate else: U_i.set(U_temp) V_i.set(V_temp) # Step 7 if U_i == 0: return PROBABLY_PRIME return COMPOSITE