def encrypt(self, block_iterator): eof_iterator = eof_signal_iterator(block_iterator) for data, eof in eof_iterator: if not self.cipher_block: #executed only once, on the first iteration self.cipher_block = self.iv #just return the IV, to be used as the first 64 bytes of the file yield self.cipher_block if not eof: self.cipher_block = self.cipher.encrypt_block( self._xor(data, self.cipher_block)) else: #executed only once, for the last block of the file block = data if not eof else self.padding_scheme.apply(data) if len(block) == self.block_size: self.cipher_block = self.cipher.encrypt_block( self._xor(block, self.cipher_block)) elif len(block) == 2 * self.block_size: last_block = self.cipher.encrypt_block( self._xor(block[:self.block_size], self.cipher_block)) #This will append an entire block of padding (??) self.cipher_block = self.cipher.encrypt_block( self._xor(block[self.block_size:], last_block)) #set the cipher_block variable to be last block of real data #prepended to the extra block of padding self.cipher_block = last_block + self.cipher_block else: raise Exception( "Padding error: Padding scheme returned " + "data that is not a multiple of the block length") yield self.cipher_block
def decrypt(self, block_iterator): # Wrap file / list iterator inside eof_signal_iterator eof_iterator = eof_signal_iterator(block_iterator) for data, eof in eof_iterator: plaintext = self.cipher.decrypt_block(data) block = plaintext if not eof else self.padding_scheme.remove(plaintext) yield block
def decrypt(self, block_iterator): eof_iterator = eof_signal_iterator(block_iterator) #Always get the first 64 bytes of the data as IV. Even if it was already #supplied on the command line self.cipher_block, eof = next(eof_iterator) for data, eof in eof_iterator: plaintext = self._xor(self.cipher.decrypt_block(data), self.cipher_block) self.cipher_block = data block = plaintext if not eof else \ self.padding_scheme.remove(plaintext) yield block
def decrypt(self, block_iterator): # This is similar to encryption, but we check the gmac rather than generate it. bits_per_byte = 8 num_bits = bits_per_byte * self.block_size ek_nonce = GP(num_bits, int.from_bytes(self._get_xor_block(0), "little")) counter = 1 eof_iterator = eof_signal_iterator(block_iterator) (header_bytes, b) = next(eof_iterator) assert not b, "File contained only 1 block" A = GP(num_bits, int.from_bytes(header_bytes, "little")) zero = 0 Ek_0_bytes = self.cipher.encrypt_block(zero.to_bytes(self.cipher.block_size, "little")) Ek_0 = GP(num_bits, int.from_bytes(Ek_0_bytes, "little")) rolling_polynomial = A.mult(Ek_0) for ciphertext, eof in eof_iterator: if eof: break xor_block = self._get_xor_block(counter) data = self._xor(ciphertext, xor_block) counter += 1 C = GP(num_bits, int.from_bytes(ciphertext, "little")) rolling_polynomial = rolling_polynomial.xor(C).mult(Ek_0) yield data extra_block = len(self.header) << (num_bits // 2) extra_block += counter extra_block_gp = GP(num_bits, extra_block) rolling_polynomial = rolling_polynomial.xor(extra_block_gp).mult(Ek_0) gmac = rolling_polynomial.xor(ek_nonce) gmac_bytes = gmac.intval().to_bytes(self.block_size, "little") if gmac_bytes == ciphertext: print("Message verified correctly") else: print("Message not verified")
def encrypt(self, block_iterator): counter = 0 eof_iterator = eof_signal_iterator(block_iterator) for data, eof in eof_iterator: xor_block = self._get_xor_block(counter) if eof and len(data) < self.block_size: xor_block = xor_block[:len(data)] ciphertext = self._xor(data, xor_block) counter += 1 yield ciphertext
def encrypt(self, block_iterator): # Wrap file / list iterator inside eof_signal_iterator eof_iterator = eof_signal_iterator(block_iterator) for data, eof in eof_iterator: if not eof: ciphertext = self.cipher.encrypt_block(data) else: block = data if not eof else self.padding_scheme.apply(data) # Padding should return 1 or 2 blocks if len(block) == self.block_size: ciphertext = self.cipher.encrypt_block(block) elif len(block) == self.block_size * 2: ciphertext = self.cipher.encrypt_block(block[:self.block_size]) \ + self.cipher.encrypt_block(block[self.block_size:]) else: raise Exception("Padding error: Padding scheme returned data that is not a multiple of the block length") yield ciphertext
def encrypt(self, block_iterator): bits_per_byte = 8 num_bits = bits_per_byte * self.block_size ek_nonce = GP(num_bits, int.from_bytes(self._get_xor_block(0), "little")) counter = 1 assert len(self.header) <= self.block_size, "Header must be fit in a single block" A = GP(num_bits, int.from_bytes(self.header, "little")) header_bytes = int.from_bytes(self.header, "little").to_bytes(self.block_size, "little") yield header_bytes zero = 0 Ek_0_bytes = self.cipher.encrypt_block(zero.to_bytes(self.cipher.block_size, "little")) Ek_0 = GP(num_bits, int.from_bytes(Ek_0_bytes, "little")) rolling_polynomial = A.mult(Ek_0) eof_iterator = eof_signal_iterator(block_iterator) for data, eof in eof_iterator: xor_block = self._get_xor_block(counter) ciphertext = self._xor(data, xor_block) counter += 1 C = GP(num_bits, int.from_bytes(ciphertext, "little")) rolling_polynomial = rolling_polynomial.xor(C).mult(Ek_0) yield ciphertext extra_block = len(self.header) << (num_bits // 2) extra_block += counter extra_block_gp = GP(num_bits, extra_block) rolling_polynomial = rolling_polynomial.xor(extra_block_gp).mult(Ek_0) gmac = rolling_polynomial.xor(ek_nonce) yield gmac.intval().to_bytes(self.block_size, "little")