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 update(self, data): ''' CTR_DRBG_Update as specified in NIST SP800-90A, Section 10.2.1.2, page 52. Updates the internal state using the provided data.' ''' if (self.seedlen & 7) or (self.keylen & 7) or (self.outlen & 7): raise NotImplementedError( 'Only 0 mod 8 is supported for key/block sizes.') if type(data) is not str: raise ValueError('CTR_DRBG_Update requires string input.') seedlenbytes = self.seedlen / 8 if len(data) != seedlenbytes: raise ValueError( ('CTR_DRBG_Update requires exactly seedlen of data ' '(received %d bytes, expected %d).') % (len(data), seedlenbytes)) # Step 1 temp = '' # Step 2 while len(temp) < seedlenbytes: # Step 2.1 self.V = utilities.binstr_increment(self.V, self.outlen) # Step 2.2 output_block = self.block_encrypt(self.key, self.V) # Step 2.3 temp = temp + output_block # Step 3-4, the XOR function automatically truncates to match # input lengths temp = utilities.binstr_xor(data, temp) # Step 5 self.key = temp[:self.keylen / 8] # Step 6 self.V = temp[self.keylen / 8:][:self.outlen / 8] # Step 7 self.scheduled = False return