def encrypt(self, symmetric_algo, key, message): block_len = utils.symmetric_cipher_block_lengths[symmetric_algo] iv = Random.new().read(block_len) data = bytearray() cipher = utils.get_symmetric_cipher(symmetric_algo, key, utils.CFB, b'\x00' * block_len) padding = 0 offset = 0 if not self.integrity_protected: padding = block_len - len(message) % block_len message = message + b'\x00' * padding data.extend(cipher.encrypt(iv + iv[-2:])) cipher = utils.get_symmetric_cipher(symmetric_algo, key, utils.CFB, iv) data.extend(cipher.encrypt(message)) else: padding = block_len - (len(message) + 2 + 22) % block_len data.extend(cipher.encrypt(iv)) hash_ = SHA.new(iv) hash_.update(iv[-2:]) message = message + b'\xd3\x14' hash_.update(message) mdc = hash_.digest() message = message + mdc + (b'\x00' * padding) data.extend(cipher.encrypt(iv[-2:] + message)[:-padding]) self.data = data
def encrypt(self, symmetric_algo, key, message): block_len = utils.symmetric_cipher_block_lengths[symmetric_algo] iv = Random.new().read(block_len) data = bytearray() cipher = utils.get_symmetric_cipher( symmetric_algo, key, utils.CFB, b'\x00' * block_len ) padding = 0 if not self.integrity_protected: padding = block_len - len(message) % block_len message = message + b'\x00' * padding data.extend(cipher.encrypt(iv + iv[-2:])) cipher = utils.get_symmetric_cipher( symmetric_algo, key, utils.CFB, iv ) data.extend(cipher.encrypt(message)) else: padding = block_len - (len(message) + 2 + 22) % block_len data.extend(cipher.encrypt(iv)) hash_ = SHA.new(iv) hash_.update(iv[-2:]) message = message + b'\xd3\x14' hash_.update(message) mdc = hash_.digest() message = message + mdc + (b'\x00' * padding) data.extend(cipher.encrypt(iv[-2:] + message)[:-padding]) self.data = data
def decrypt(self, symmetric_algo, key): encrypted_data = bytes(self.data) decrypted_data = bytearray() offset = 0 padding = 0 block_len = utils.symmetric_cipher_block_lengths[symmetric_algo] encrypted_iv = encrypted_data[:block_len + 2] cipher = utils.get_symmetric_cipher(symmetric_algo, key, utils.CFB, b'\x00' * block_len) decrypted_iv = cipher.decrypt(encrypted_data[:block_len]) if self.integrity_protected: # "Unlike the Symmetrically Encrypted Data Packet, no special CFB # resynchronization is done after encrypting this prefix data." offset += block_len first_block = cipher.decrypt(encrypted_data[offset:offset + block_len]) offset += block_len iv_check = first_block[:2] if iv_check != decrypted_iv[-2:]: raise ValueError() decrypted_data.extend(first_block[2:]) # Pad the remaining data manually padding = block_len - (len(encrypted_data) - offset) % block_len encrypted_data += b'\x00' * padding else: cipher = utils.get_symmetric_cipher(symmetric_algo, key, utils.OPENPGP, encrypted_iv) decrypted_data.extend(cipher.decrypt(encrypted_data[offset:])) decrypted_data = decrypted_data[:-padding] # We run into trouble here with partial body lengths and the MDC. # Let's make pretend. mdc_data = bytearray() main_data = decrypted_data if decrypted_data[-22:-20] == b'\xd3\x14': # It's there. Hold it back. mdc_data = decrypted_data[-22:] main_data = decrypted_data[:-22] data_len = len(main_data) offset = 0 decrypted_packets = [] while offset < data_len: offset, packet = packets.packet_from_packet_data(main_data, offset) decrypted_packets.append(packet) if mdc_data: # One more for the MDC offset, packet = packets.packet_from_packet_data(mdc_data, 0) decrypted_packets.append(packet) if self.integrity_protected: if (decrypted_packets[-1].type != C.MODIFICATION_DETECTION_CODE_PACKET_TYPE): raise ValueError( 'Integrity protected message is missing modification ' 'detection code.') mdc = decrypted_packets.pop() hash_ = SHA.new(decrypted_iv) hash_.update(decrypted_iv[-2:]) hash_.update(decrypted_data[:-20]) if mdc.data != hash_.digest(): raise ValueError( 'Integrity protected message does not match modification ' 'detection code.') return open_pgp_message_from_packets(decrypted_packets)
def decrypt(self, symmetric_algo, key): encrypted_data = bytes(self.data) decrypted_data = bytearray() offset = 0 padding = 0 block_len = utils.symmetric_cipher_block_lengths[symmetric_algo] encrypted_iv = encrypted_data[:block_len + 2] cipher = utils.get_symmetric_cipher( symmetric_algo, key, utils.CFB, b'\x00' * block_len) decrypted_iv = cipher.decrypt(encrypted_data[:block_len]) if self.integrity_protected: # "Unlike the Symmetrically Encrypted Data Packet, no special CFB # resynchronization is done after encrypting this prefix data." offset += block_len first_block = cipher.decrypt( encrypted_data[offset:offset + block_len]) offset += block_len iv_check = first_block[:2] if iv_check != decrypted_iv[-2:]: raise ValueError() decrypted_data.extend(first_block[2:]) # Pad the remaining data manually padding = block_len - (len(encrypted_data) - offset) % block_len encrypted_data += b'\x00' * padding else: cipher = utils.get_symmetric_cipher( symmetric_algo, key, utils.OPENPGP, encrypted_iv) decrypted_data.extend(cipher.decrypt(encrypted_data[offset:])) decrypted_data = decrypted_data[:-padding] # We run into trouble here with partial body lengths and the MDC. # Let's make pretend. mdc_data = bytearray() main_data = decrypted_data if decrypted_data[-22:-20] == b'\xd3\x14': # It's there. Hold it back. mdc_data = decrypted_data[-22:] main_data = decrypted_data[:-22] data_len = len(main_data) offset = 0 decrypted_packets = [] while offset < data_len: offset, packet = packets.packet_from_packet_data(main_data, offset) decrypted_packets.append(packet) if mdc_data: # One more for the MDC offset, packet = packets.packet_from_packet_data(mdc_data, 0) decrypted_packets.append(packet) if self.integrity_protected: if (decrypted_packets[-1].type != C.MODIFICATION_DETECTION_CODE_PACKET_TYPE): raise ValueError( 'Integrity protected message is missing modification ' 'detection code.') mdc = decrypted_packets.pop() hash_ = SHA.new(decrypted_iv) hash_.update(decrypted_iv[-2:]) hash_.update(decrypted_data[:-20]) if mdc.data != hash_.digest(): raise ValueError( 'Integrity protected message does not match modification ' 'detection code.') return open_pgp_message_from_packets(decrypted_packets)