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
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]
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)