Example #1
0
    def reencrypt(
        self, rekey: Tuple[tuple, Tuple[bytes,
                                        bytes]], ciphertext: Tuple[bytes,
                                                                   bytes]
    ) -> Tuple[Tuple[bytes, bytes], Tuple[bytes, bytes]]:
        """
        Re-encrypt for public key
        rekey is (rk, encrypted_eph), same as output of rekey()
        ciphertext is a tuple in the same format as output of encrypt()

        Output is two tuples: data encrypted with an ephemeral key
        and the ephemeral private key encrypted for recepient (Bob)
        """
        rk, encrypted_eph = rekey
        rk = umbral.RekeyFrag(rk[0],
                              ec.deserialize(self.pre.ecgroup, rk[1]),
                              pre=PRE)
        ekey, edata = ciphertext
        ekey = umbral.EncryptedKey(ekey=ec.deserialize(self.pre.ecgroup,
                                                       ekey[0]),
                                   re_id=ekey[1])

        ekey = self.pre.reencrypt(rk, ekey)

        ekey = (ec.serialize(ekey.ekey), ekey.re_id)
        return (ekey, edata), encrypted_eph
Example #2
0
    def decrypt(self,
                edata: Tuple[bytes, bytes],
                privkey: bytes = None) -> bytes:
        """
        Decrypt data encrypted by ECIES
        edata = (ekey, edata)
            ekey is needed to reconstruct a DH secret
            edata encrypted by the block cipher
            privkey is optional private key if we want to use something else
            than what keypair uses
        """
        if isinstance(edata[0], tuple) and isinstance(edata[1], tuple):
            # In case it was re-encrypted data
            return self.decrypt_reencrypted(edata)

        ekey, edata = edata
        # When it comes to decrypt(), ekey[1] is always None
        # we could use that and save 2 bytes,
        # but it makes the code less readable
        ekey = umbral.EncryptedKey(ekey=ec.deserialize(API.PRE.ecgroup,
                                                       ekey[0]),
                                   re_id=ekey[1])
        if privkey is None:
            privkey = self._priv_key
        else:
            privkey = ec.deserialize(API.PRE.ecgroup, privkey)

        key = self.pre.decapsulate(privkey, ekey)
        cipher = SecretBox(key)
        return cipher.decrypt(edata)
    def combine(self,
                shares: Tuple[Tuple[bytes, bytes], Tuple[bytes, bytes]]
                ) -> Tuple[Tuple[bytes, bytes], Tuple[bytes, bytes]]:
        ekeys = [umbral.EncryptedKey(
                    ekey=ec.deserialize(self.pre.ecgroup, share[0][0][0]),
                    re_id=share[0][0][1])
                 for share in shares]
        ekey = self.pre.combine(ekeys)
        ekey = (ec.serialize(ekey.ekey), ekey.re_id)

        # Everything except ekey is the same for all shares!
        # TODO instead of trusting the first share, trust the majority
        return (ekey, shares[0][0][1]), shares[0][1]
Example #4
0
def ecies_reencrypt(
    rekey: Union[bytes, umbral.RekeyFrag],
    enc_key: Union[bytes, umbral.EncryptedKey],
) -> umbral.EncryptedKey:
    """
    Re-encrypts the key provided.

    :param rekey: Re-encryption key to use
    :param enc_key: Encrypted key to re-encrypt

    :return: The re-encrypted key
    """
    if type(rekey) == bytes:
        rekey = umbral.RekeyFrag(None, priv_bytes2ec(rekey))
    if type(enc_key) == bytes:
        enc_key = umbral.EncryptedKey(priv_bytes2ec(enc_key), None)
    return PRE.reencrypt(rekey, enc_key)