Exemplo n.º 1
0
    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)