def get_entropy_input(self, security_strength, min_bits, max_bits, prediction_resistance): min_bytes = (min_bits + 7) / 8 try: ctr = 0 random_bytes = '' while len(random_bytes) < min_bytes and ctr < 10: random_bytes += ( self.qrng.wesQrngEntropyGet(min_bytes - len(random_bytes))) ctr += 1 logging.debug("Got %s bytes from qrng.", len(random_bytes)) random_bytes = utilities.binstr_leftmost(random_bytes, max_bits) if len(random_bytes) >= min_bytes: self.total_bytes += len(random_bytes) return 'SUCCESS', random_bytes else: return 'ERROR', ("Unable to get the requested entropy. " + "Only got %s bytes." % len(random_bytes)) except eWesQrngError as error: logging.error(error.msg) raise
def hash_df(self, input_string, n_bits): ''' Hash_df as specified in NIST SP800-90A, Section 10.4.1, page 67 ''' if n_bits > 255 * self.outlen: return 'ERROR', '' # Step 1 temp = '' # Step 2 len_blocks = (n_bits + self.outlen - 1) / self.outlen # Step 3 counter = 1 # Step 4 for dummy_ii in range(len_blocks): # Step 4.1 temp = temp + self.hash(struct.pack('>II', counter, n_bits) + input_string) # Step 4.2 counter += 1 # Step 5 requested_bits = utilities.binstr_leftmost(temp, n_bits) # Step 6 return 'SUCCESS', requested_bits
def hashgen(self, n_bits, V): ''' Hashgen, as specified in NIST SP800-90A, Section 10.1.1.4, page 43 ''' # Step 1 mm = (n_bits + self.outlen - 1) / self.outlen # Step 2 data = V # Step 3 W = '' # Step 4 for dummy_ii in range(mm): # Step 4.1 wi = self.hash(data) # Step 4.2 W = W + wi # Step 4.3 data = utilities.binstr_increment(data, self.seedlen) # Step 5 returned_bits = utilities.binstr_leftmost(W, n_bits) # Step 6 return returned_bits
def generate_algorithm(self, n_bits, additional_input = None): ''' CTR_DRGB_Generate_algorithm, as specified in NIST SP800-90A, Section 10.2.1.5, page 56. Generate bits either with (10.2.1.5.2) or without (10.2.1.5.2) a derivation function. ''' # Step 1 if self.counter > self.max_interval and not self.reseed_failed: return ('RESEED', '') # Step 2 if additional_input: if self.derivation: # 10.2.1.5.2, Step 2.1 status, additional_input = self.block_cipher_df( additional_input, self.seedlen) if status != 'SUCCESS': return 'ERROR', 'block_cipher_df returned [%s]' % status else: # 10.2.1.5.1, Step 2.1-2.2 additional_input = utilities.binstr_zeropad( additional_input, self.seedlen) # 10.2.1.5.1, Step 2.3 / 10.2.1.5.2, Step 2.2 self.update(additional_input) else: additional_input = utilities.binstr_zeropad('', self.seedlen) # Step 3 temp = '' # Step 4 while len(temp) < (n_bits + 7) / 8: # Step 4.1 self.V = utilities.binstr_increment(self.V, self.outlen) # Step 4.2 output_block = self.block_encrypt(self.key, self.V) # Step 4.3 temp = temp + output_block # Step 5 returned_bits = utilities.binstr_leftmost(temp, n_bits) # Step 6 self.update(additional_input) # Step 7 self.counter += 1 # Step 8 if not self.reseed_failed: return ('SUCCESS', returned_bits) else: return ('RESEED', returned_bits)
def get_entropy_input(self, security_strength, min_bits, max_bits, prediction_resistance): '''Return entropy from network source.''' if max_bits < min_bits: raise ValueError('max_length must be greater than or ' + 'equal to min_length') min_bytes = (min_bits + 7) / 8 random_bytes = '' backoff = 0.01 if not self.init_event.is_set(): while not self.init_event.is_set(): time.sleep(.1) # TODO: Make less hacky (still timing based) time.sleep(1) # Only try to get data when buffer isn't empty to prevent # a two second decay when qrng goes down and drbg is running # off old seed (qrng as seed case). if self.buff.bytes_ready() > 0: while len(random_bytes) < min_bytes: with self.lock: new_bytes = self.buff.get_random_data( min_bytes) if len(new_bytes) == 0: logging.debug("Sleep %f", backoff) if backoff > 2.0: break time.sleep(backoff) backoff = backoff * 2 else: backoff = 0.01 random_bytes += str(new_bytes) self.total_bytes += len(random_bytes) random_bytes = utilities.binstr_leftmost(random_bytes, max_bits) if len(random_bytes) >= min_bytes: return 'SUCCESS', random_bytes else: self.restart_fifo_client() return 'ERROR', (("Internal pool doesn't contain " "enough entropy. Only got %i bytes.") % len(random_bytes))
def get_entropy_input(self, security_strength, min_bits, max_bits, prediction_resistance): '''Return entropy from network source.''' # If initializing, wait up to 30 seconds to allow network to connect. if self.state < 2: timeout_start = time.time() timeout = 30 while self.state < 2 and time.time() < timeout_start + timeout: time.sleep(.1) if max_bits < min_bits: raise ValueError('max_length must be greater than or ' + 'equal to min_length') min_bytes = (min_bits + 7) / 8 # To encrypt with AES, must have blocks of 16 bytes aes_bytes = ((min_bytes + 15) / 16) * 16 random_bytes = '' backoff = 0.01 # Only try to get data when buffer isn't empty to prevent # a two second decay when network goes down and drbg is running # off old seed (network as seed case). if self.buff.bytes_ready() > 0: while len(random_bytes) < aes_bytes: with self.lock: new_bytes = self.buff.get_random_data(aes_bytes - len(random_bytes)) if len(new_bytes) == 0: logging.warning("Sleep %f", backoff) if backoff > 2.0: break time.sleep(backoff) backoff = backoff * 2 else: backoff = 0.01 random_bytes += str(new_bytes) # If we haven't hit a timeout if len(random_bytes) == aes_bytes: random_bytes = self.aes_key.encrypt(random_bytes) if len(random_bytes) > min_bytes: random_bytes = random_bytes[0:min_bytes] self.total_bytes += len(random_bytes) if (self.total_bytes > self.last_rekey + NetworkEntropySource.REKEY_PERIOD): self.rekey() random_bytes = utilities.binstr_leftmost(random_bytes, max_bits) if len(random_bytes) >= min_bytes: return 'SUCCESS', random_bytes return 'ERROR', (("Internal pool doesn't contain " "enough entropy. Only got %i bytes.") % len(random_bytes))