def encrypt(self, passphrases_and_keys, symmetric_algorithm=9): cipher, key_bytes, key_block_bytes = self.get_cipher( symmetric_algorithm) if not cipher: raise Exception("Unsupported cipher") prefix = Crypto.Random.new().read(key_block_bytes) prefix += prefix[-2:] key = Crypto.Random.new().read(key_bytes) session_cipher = cipher(key)(None) to_encrypt = prefix + self._message.to_bytes() mdc = OpenPGP.ModificationDetectionCodePacket( Crypto.Hash.SHA.new(to_encrypt + b'\xD3\x14').digest()) to_encrypt += mdc.to_bytes() def doEncrypt(cipher): ctx = cipher.encryptor() return lambda x: ctx.update(x) + ctx.finalize() encrypted = [ OpenPGP.IntegrityProtectedDataPacket( self._block_pad_unpad(key_block_bytes, to_encrypt, doEncrypt(session_cipher))) ] if not isinstance(passphrases_and_keys, collections.Iterable) or hasattr( passphrases_and_keys, 'encode'): passphrases_and_keys = [passphrases_and_keys] for psswd in passphrases_and_keys: if isinstance(psswd, OpenPGP.PublicKeyPacket): if not psswd.key_algorithm in [1, 2, 3]: raise Exception("Only RSA keys are supported.") rsa = self.__class__(psswd).public_key() pkcs1 = Crypto.Cipher.PKCS1_v1_5.new(rsa) esk = pkcs1.encrypt( pack('!B', symmetric_algorithm) + key + pack('!H', OpenPGP.checksum(key))) esk = pack('!H', OpenPGP.bitlength(esk)) + esk encrypted = [ OpenPGP.AsymmetricSessionKeyPacket( psswd.key_algorithm, psswd.fingerprint(), esk) ] + encrypted elif hasattr(psswd, 'encode'): psswd = psswd.encode('utf-8') s2k = OpenPGP.S2K(Crypto.Random.new().read(10)) packet_cipher = cipher(s2k.make_key(psswd, key_bytes))(None) esk = self._block_pad_unpad( key_block_bytes, pack('!B', symmetric_algorithm) + key, doEncrypt(packet_cipher)) encrypted = [ OpenPGP.SymmetricSessionKeyPacket(s2k, esk, symmetric_algorithm) ] + encrypted return OpenPGP.Message(encrypted)