def _get_generator(p, task_monitor=None): """ Returns the generator of the Z_{p}^{*} cyclic group. We take random numbers in Z_{p}^{*} = [0, ..., p - 1], until one of them is a generator for the group. This function assumes that p is a safe prime (p = 2q + 1 with both p and q prime). See the documentation for _is_generator(p, g) for more information about testing whether a number is a generator of Z_{p}^{*}. Arguments: p::long -- A safe prime. task_monitor::TaskMonitor -- A task monitor for the process. Returns: g::long -- A generator of Z_{p}^{*} """ random = StrongRandom() candidate = random.randint(1, p - 1) if (task_monitor != None): task_monitor.tick() while (not _is_generator(p, candidate)): candidate = random.randint(1, p - 1) if (task_monitor != None): task_monitor.tick() if (params.DEBUG): assert pow(candidate, p - 1, p) == 1, \ "generator^{p-1} != 1 mod p (!) see method's " \ "algorithm explanation." return candidate # this is the generator
def rsa_compatible(n, phi): phi = long(phi) while True: e = StrongRandom().randint(1, phi - 1) if GCD(e, phi) == 1: break return RSAKey(mpz(n), mpz(e), None, None, None, 1024)
def obtain_splittings_and_schedules(input_peers, split_amount, mixing_window_mins, seed): prng_gen = SeedablePrngGenerator() prng_gen.reseed(seed) prng = StrongRandom(randfunc=prng_gen.pseudo_random_data) for input_peer in input_peers: input_peer['split'] = splitMixingAmount(split_amount, prng) input_peer['schedule'] = defineStreamingSchedule( len(input_peer['split']), mixing_window_mins, prng) return
def generate_password(pwd_length, symbols=string.ascii_letters + string.digits + string.digits): from Crypto.Random.random import StrongRandom ret = '' rnd = StrongRandom() for i in range(pwd_length): ret += rnd.choice(symbols) return ret
def __init__(self, cryptosystem): """ Generates a new key pair for the given EGCryptoSystem """ p = cryptosystem.get_prime() random = StrongRandom() inner_private_key = random.randint(1, p - 2) self.private_key = PrivateKey(cryptosystem, inner_private_key) self.public_key = self.private_key.public_key
def computeFinalPermutation(output_addresses, checksum): # Compute hex presentation of checksum seed = checksum.decode('hex') """ Create a PRNG based on Crypto.random.random, but with seedable input (instead of /dev/urandom). """ prng_input = SeedablePrngGenerator() prng_input.reseed(seed) log.debug('Seed: ' + seed.encode('hex')) prng = StrongRandom(randfunc=prng_input.pseudo_random_data) prng.shuffle(output_addresses) return output_addresses
def new(cls, collection): """ Generate a new mapping compatible with the given collection. This method produces a new CiphertextCollectionMapping object that maps the given collection into a randomly shuffled collection. To obtain said shuffled collection, simply call the apply method of the returned mapping, passing once again the collection as an argument. The reason this method takes the collection to be shuffled as an argument is to ensure that the resulting CiphertextCollectionMapping is compatible with said collection. This includes: providing a re-ordering and re-encryption for the right number of elements of the right size, as well as using the same public key for re-encryption as the one used to encrypt the elements of the original collection. Arguments: collection::CiphertextCollection -- The collection for which we wish to generate a new mapping. Returns: mapping::CiphertextCollectionMapping -- A mapping from collection to a randomly shuffled new collection. """ # Get the public key and length of the collection public_key = collection.public_key length = collection.get_length() # Create an empty mapping mapping = CiphertextCollectionMapping() # Generate a list of all collection element indexes for i in range(0, length): mapping._reordering.append(i) # Randomly permute those indexes to generate a reordering random = StrongRandom() ### random.shuffle(self._reordering) is broken upstream, workaround: _random_shuffle_in_place(random, mapping._reordering) # Generate a random re-encryption for each ciphertext in the collection for ciphertext in collection: ciphertext_len = ciphertext.get_length() reencryption = \ CiphertextReencryptionInfo.new(public_key, ciphertext_len) mapping._reencryptions.append(reencryption) # Return the generated mapping return mapping
def pallier_encrypt(key, element): assert element in [0, 1], element _n = long(key.n) while True: r = StrongRandom().randint(1, _n) if GCD(r, _n) == 1: break r = mpz(r) #key_g < n2, so no need for modulo t1 = key.g if element else 1l t2 = pow(r, key.n, key.n2) cipher = (t1 * t2) % key.n2 return long(cipher)
def sign(self, msg_hash): """Produce the DSS signature of a message. :Parameters: msg_hash : hash object The hash that was carried out over the message. The object belongs to the `Crypto.Hash` package. Under mode *'fips-186-3'*, the hash must be a FIPS approved secure hash (SHA-1 or a member of the SHA-2 family). :Return: The signature encoded as a byte string. :Raise ValueError: If the hash algorithm is incompatible to the DSA key. :Raise TypeError: If the DSA key has no private half. """ # Generate the nonce k (critical!) if self._deterministic: nonce = self._compute_nonce(msg_hash) else: if self._n > msg_hash.digest_size * 8: raise ValueError("Hash is not long enough") if not msg_hash.name.upper().startswith("SHA"): raise ValueError("Hash %s does not belong to SHS" % msg_hash.name) rng = StrongRandom(randfunc=self._randfunc) nonce = rng.randint(1, self._key.q - 1) # Perform signature using the raw API z = bytes_to_long(msg_hash.digest()[:self._n]) sig_pair = self._key._sign(z, nonce) # Encode the signature into a single byte string if self._encoding == 'binary': output = b("").join([long_to_bytes(x, self._n) for x in sig_pair]) else: # Dss-sig ::= SEQUENCE { # r OCTET STRING, # s OCTET STRING # } der_seq = DerSequence(sig_pair) output = der_seq.encode() return output
def isPrime(N, randfunc=None): """isPrime(N:long, randfunc:callable):bool Return true if N is prime. If randfunc is omitted, then Random.new().read is used. """ _import_Random() if randfunc is None: randfunc = Random.new().read randint = StrongRandom(randfunc=randfunc).randint if N == 1: return 0 if N in sieve: return 1 for i in sieve: if (N % i) == 0: return 0 # Use the accelerator if available if _fastmath is not None: return _fastmath.isPrime(N) # Compute the highest bit that's set in N N1 = N - 1L n = 1L while (n < N): n = n << 1L n = n >> 1L # Rabin-Miller test for c in sieve[:7]: a = long(c) d = 1L t = n while (t): # Iterate over the bits in N1 x = (d * d) % N if x == 1L and d != 1L and d != N1: return 0 # Square root of 1 found if N1 & t: d = (x * a) % N else: d = x t = t >> 1L if d != 1L: return 0
def new_random_polynomial(cls, modulus, degree): """ Construct a new polynomial of the given degree with random coefficients. Arguments: modulus::long -- All arithmetic for this polynomial will be performed with this modulus. That is, in the Z_{modulus} multiplicative group. degree::int -- Degree of the new polynomial. """ coefficients = [] random = StrongRandom() for i in range(0, degree + 1): coeff = random.randint(1, modulus - 1) coefficients.append(coeff) return cls(modulus, coefficients)
class FileEncryptor(object, metaclass=abc.ABCMeta): __strong_random = StrongRandom() __lock = Lock() @classmethod def gen_secret(cls, min_length, max_length): with cls.__lock: n_chars = cls.__strong_random.randrange(min_length, max_length) return Random.new().read(n_chars) @abstractclassmethod def encrypt(cls, file_in, file_out, key_or_secret): pass @abstractclassmethod def decrypt(cls, file_in, file_out, key_or_secret): pass
def new(cls, public_key, length): """ Generate a new re-encryption information object with the given length. This constructs {length} blocks of random ciphertext re-encryption information, which can be applied to a given ciphertext in order to produce a re-encrypted ciphertext. Arguments: public_key::PublicKey-- The public key to be used for re-encryption. This must be the same public key that was used to encrypt the original ciphertext. length::int -- Number of blocks of re-encryption information. Returns: reencryption_info::CiphertextReencryptionInfo -- A new CiphertextReencryptionInfo object containing length random blocks or re-encryption information. """ random = StrongRandom() # Get p and g prime = public_key.cryptosystem.get_prime() generator = public_key.cryptosystem.get_generator() # Create a new empty CiphertextReencryptionInfo object reencryption_info = CiphertextReencryptionInfo(public_key) # Add (length) random re-encryption information blocks for i in range(0, length): # Select a random integer r, 1 <= r <= p − 2 r = random.randint(1, prime - 2) # store block (g^{r}, y^{r}) gr = pow(generator, r, prime) yr = pow(public_key._key, r, prime) reencryption_info.add_block(gr, yr) assert (reencryption_info.get_length() == length) return reencryption_info
def main(): print '' print 'm', m # Secret generation a = [] a.append(generateSecret()) secretCount = numberOfSecrets * userCount - 1 print 'secretCount', secretCount for x in xrange(0, secretCount): a.append(generateSecret()) secretArray = a print 'secretArray', secretArray chunks = [ secretArray[x:x + numberOfSecrets] for x in xrange(0, len(secretArray), numberOfSecrets) ] print 'chunks', chunks # Use strong random to shuffle the array. This way our crypto program is secure (StrongRandom()).shuffle(secretArray) print 'secretArray', secretArray # user 1 things = [User1(), User2()] total = decryptData(things, 1, secretArray) print total
def generate_partial_decryption(self, ciphertext, task_monitor=None, force=False): """ Generates a partial decryption for the given ciphertext. Arguments: ciphertext::Ciphertext -- An encrypted Ciphertext object. task_monitor::TaskMonitor -- A task monitor for this task. force:bool -- Set this to true if you wish to force a decryption attempt, even when the ciphertext's stored public key fingerprint does not match that of the public key associated with this private key. Returns: partial_decryption::PartialDecryption -- A partial decryption of the given ciphertext generated with this threshold private key. Throws: IncompatibleCiphertextError -- The given ciphertext does not appear to be decryptable with the selected private key. """ # Check that the public key fingerprint stored in the ciphertext # matches the public key associated with this private key. if (not force): if (ciphertext.nbits != self.cryptosystem.get_nbits()): raise IncompatibleCiphertextError("The given ciphertext is " \ "not decryptable with the selected private key: " \ "incompatible cryptosystem/key sizes.") if (ciphertext.pk_fingerprint != self.public_key.get_fingerprint()): raise IncompatibleCiphertextError("The given ciphertext is " \ "not decryptable with the selected private key: " \ "public key fingerprint mismatch.") nbits = self.cryptosystem.get_nbits() prime = self.cryptosystem.get_prime() generator = self.cryptosystem.get_generator() key = self._key # Remember that prime is of the form p = 2*q + 1, with q prime. # (By construction, see EGCryptoSystem) q = (prime - 1) / 2 # We will need a random number generator for the proofs of partial # decryption. random = StrongRandom() # New empty partial decryption partial_decryption = PartialDecryption(nbits) # Check if we have a task monitor and register with it if (task_monitor != None): # One tick per block ticks = ciphertext.get_length() partial_decrypt_task_mon = \ task_monitor.new_subtask("Generate partial decryption", expected_ticks = ticks) # For each (gamma,delta) component in the ciphertext, generate one # partial decryption block (with proof): for gamma, delta in ciphertext: # To calculate the value of the block, elevate gamma to the # threshold private key. That is block.value = g^{rP(i)} for each # nbits block of original plaintext. value = pow(gamma, key, prime) # Generate the partial decryption proof for the block as a # Zero-Knowledge Discrete Logarithm Equality Test for # log_{g}(g^{2P(j)}) == log_{gamma}(block^2) # (See PartialDecryptionBlockProof and [TODO: Add reference] for # more information.) # Select a random s in Z_{q}^{*} s = random.randint(1, q - 1) # a = g^{s} mod p a = pow(generator, s, prime) # b = gamma^{s} mod p b = pow(gamma, s, prime) # c is SHA256(a, b, g^{2*P(j)}, block.value) the challenge # (We must use g^{2*P(j)} and not g^{P(j)}, because the first is # considered as the partial public key of trustee j and the value # of the later is unavailable at decryption combination time). sha256 = Crypto.Hash.SHA256.new() sha256.update(hex(a)) sha256.update(hex(b)) sha256.update(hex(pow(generator, 2 * key, prime))) sha256.update(hex(value)) c = int(sha256.hexdigest(), 16) # t = s + 2P(j)*c mod p-1 (P(j): trustee j's threshold private key) # (p - 1 since it is in the exponent and we are already adding the 2 # factor in 2P(j)) t = (s + 2 * key * c) % (prime - 1) # Generate the PartialDecryptionBlockProof as (a, b, t) proof = PartialDecryptionBlockProof(a, b, t) # Generate the block as (value, proof) and add it to the partial # decryption object. block = PartialDecryptionBlock(value, proof) partial_decryption.add_partial_decryption_block(block) # Update task progress if (task_monitor != None): partial_decrypt_task_mon.tick() return partial_decryption
def __init__(self): self.rnd = StrongRandom()
def create_rng(tag): rng = StrongRandom(SHAKE128.new(data=tag)) return rng
def generate_random(nbytes): ''' returns nbytes-long random string ''' return ''.join(chr(StrongRandom().randint(0, 0xFF)) for i in range(nbytes))
from __future__ import absolute_import, division, print_function from __future__ import unicode_literals from builtins import * import logging import struct import time try: from Crypto.Random.random import StrongRandom # Wrap with int() for Py2 random = lambda n: int(StrongRandom().getrandbits(n * 8)).to_bytes( n, 'big') except ImportError: from os import urandom as random try: from . import crypto except ImportError: crypto = None from i2p import util if crypto: sha256 = crypto.sha256 else: sha256 = util.sha256 from enum import Enum # # Common data types
def encrypt_bitstream(self, bitstream, pad_to=None, task_monitor=None): """ Encrypts the given bitstream into a ciphertext object. Arguments: bitstream::BitStream-- A stream of bits to encrypt (see BitStream utility class). pad_to::int -- Minimum size (in bytes) of the resulting ciphertext. Data will be padded before encryption to match this size. task_monitor::TaskMonitor -- A task monitor for this task. Returns: ciphertext:Ciphertext -- A ciphertext object encapsulating the encrypted data. """ random = StrongRandom() ## PART 1 # First, format the bitstream as per Ciphertext.py Note 001, # previous to encryption. # [size (64 bits) | message (size bits) | padding (X bits) ] ## formated_bitstream = BitStream() # The first 64 encode the size of the actual data in bits SIZE_BLOCK_LENGTH = 64 size_in_bits = bitstream.get_length() if(size_in_bits >= 2**SIZE_BLOCK_LENGTH): raise ValueError("The size of the bitstream to encrypt is larger " \ "than 16 Exabits. The current format for " \ "PloneVote ciphertext only allows encrypting a " \ "maximum of 16 Exabits of information.") formated_bitstream.put_num(size_in_bits, SIZE_BLOCK_LENGTH) # We then copy the contents of the original bitstream bitstream.seek(0) formated_bitstream.put_bitstream_copy(bitstream) # Finally, we append random data until we reach the desired pad_to # length unpadded_length = formated_bitstream.get_length() if(pad_to != None and (pad_to * 8) > unpadded_length): full_length = pad_to * 8 else: full_length = unpadded_length padding_left = full_length - unpadded_length while(padding_left > 1024): padding_bits = random.randint(1, 2**1024) formated_bitstream.put_num(padding_bits,1024) padding_left -= 1024 if(padding_left > 0): padding_bits = random.randint(1, 2**padding_left) formated_bitstream.put_num(padding_bits, padding_left) padding_left = 0 ## PART 2 # We encrypt the formated bitsteam using ElGamal into a Ciphertext # object. # See "Handbook of Applied Cryptography" Algorithm 8.18 ## # block_size is the size of each block of bits to encrypt # since we can only encrypt messages in [0, p - 1] # we should use (nbits - 1) as the block size, where # 2**(nbits - 1) < p < 2**nbits block_size = self.cryptosystem.get_nbits() - 1 prime = self.cryptosystem.get_prime() generator = self.cryptosystem.get_generator() # We pull data from the bitstream one block at a time and encrypt it formated_bitstream.seek(0) ciphertext = \ Ciphertext(self.cryptosystem.get_nbits(), self.get_fingerprint()) plaintext_bits_left = formated_bitstream.get_length() # Check if we have a task monitor and register with it if(task_monitor != None): # We will do two tick()s per block to encrypt: one for generating # the gamma component of the ciphertext block and another for the # delta component (those are the two time intensive steps, # because of exponentiation). ticks = math.ceil((1.0 * plaintext_bits_left) / block_size) * 2 encrypt_task_mon = \ task_monitor.new_subtask("Encrypt data", expected_ticks = ticks) while(plaintext_bits_left > 0): # get next block (message, m, etc) to encrypt if(plaintext_bits_left >= block_size): block = formated_bitstream.get_num(block_size) plaintext_bits_left -= block_size else: block = formated_bitstream.get_num(plaintext_bits_left) # Encrypt as if the stream was filled with random data past its # end, this avoids introducing a 0's gap during decryption to # bitstream displacement = block_size - plaintext_bits_left block = block << displacement padding = random.randint(0, 2**displacement - 1) assert (padding // 2**displacement == 0), \ "padding should be at most displacement bits long" block = block | padding plaintext_bits_left = 0 # Select a random integer k, 1 <= k <= p − 2 k = random.randint(1, prime - 2) # Compute gamma and delta gamma = pow(generator, k, prime) if(task_monitor != None): encrypt_task_mon.tick() delta = (block * pow(self._key, k, prime)) % prime if(task_monitor != None): encrypt_task_mon.tick() # Add this encrypted data portion to the ciphertext object ciphertext.append(gamma, delta) # return the ciphertext object return ciphertext
def random_int_wrapper(nbytes): """returns a random integer in [0, 256**nbytes -1 ]""" return StrongRandom().randint(0,256**nbytes - 1)
""" Crypto Utils """ import base64 import math from Crypto.Hash import SHA256 from Crypto.Random.random import StrongRandom random = StrongRandom() def random_mpz_lt(maximum, strong_random=random): n_bits = int(math.floor(math.log(maximum, 2))) res = strong_random.getrandbits(n_bits) while res >= maximum: res = strong_random.getrandbits(n_bits) return res random.mpz_lt = random_mpz_lt def hash_b64(s): """ hash the string using sha256 and produce a base64 output removes the trailing "=" """ hasher = SHA256.new(s.encode('utf-8')) result = base64.b64encode(hasher.digest())[:-1] return result