Exemplo n.º 1
0
def _decapsulate_reencrypted(pub_key: Point,
                             priv_key: BigNum,
                             orig_pub_key: Point,
                             capsule: Capsule,
                             key_length=32,
                             params: UmbralParameters = None) -> bytes:
    """Derive the same symmetric key"""
    params = params if params is not None else default_params()

    xcomp = capsule._point_noninteractive
    d = hash_to_bn([xcomp, pub_key, priv_key * xcomp], params)

    e_prime = capsule._point_eph_e_prime
    v_prime = capsule._point_eph_v_prime

    shared_key = d * (e_prime + v_prime)

    key = kdf(shared_key, key_length)

    e = capsule._point_eph_e
    v = capsule._point_eph_v
    s = capsule._bn_sig
    h = hash_to_bn([e, v], params)
    inv_d = ~d

    if not (s * inv_d) * orig_pub_key == (h * e_prime) + v_prime:
        raise GenericUmbralError()
    return key
Exemplo n.º 2
0
def split_rekey(priv_a: Union[UmbralPrivateKey, BigNum],
                pub_b: Union[UmbralPublicKey, Point],
                threshold: int,
                N: int,
                params: UmbralParameters = None) -> List[KFrag]:
    """
    Creates a re-encryption key from Alice to Bob and splits it in KFrags,
    using Shamir's Secret Sharing. Requires a threshold number of KFrags 
    out of N to guarantee correctness of re-encryption.

    Returns a list of KFrags.
    """
    params = params if params is not None else default_params()

    if isinstance(priv_a, UmbralPrivateKey):
        priv_a = priv_a.bn_key

    if isinstance(pub_b, UmbralPublicKey):
        pub_b = pub_b.point_key

    g = params.g
    pub_a = priv_a * g

    x = BigNum.gen_rand(params.curve)
    xcomp = x * g
    d = hash_to_bn([xcomp, pub_b, pub_b * x], params)

    coeffs = [priv_a * (~d)]
    coeffs += [BigNum.gen_rand(params.curve) for _ in range(threshold - 1)]

    u = params.u

    g_ab = priv_a * pub_b

    blake2b = hashes.Hash(hashes.BLAKE2b(64), backend=backend)
    blake2b.update(pub_a.to_bytes())
    blake2b.update(pub_b.to_bytes())
    blake2b.update(g_ab.to_bytes())
    hashed_dh_tuple = blake2b.finalize()

    kfrags = []
    for _ in range(N):
        id_kfrag = BigNum.gen_rand(params.curve)

        share_x = hash_to_bn([id_kfrag, hashed_dh_tuple], params)

        rk = poly_eval(coeffs, share_x)

        u1 = rk * u
        y = BigNum.gen_rand(params.curve)

        z1 = hash_to_bn([y * g, id_kfrag, pub_a, pub_b, u1, xcomp], params)
        z2 = y - priv_a * z1

        kfrag = KFrag(id_=id_kfrag, key=rk, x=xcomp, u1=u1, z1=z1, z2=z2)
        kfrags.append(kfrag)

    return kfrags
Exemplo n.º 3
0
def split_rekey(
        priv_a: Union[UmbralPrivateKey, BigNum],
        pub_b: Union[UmbralPublicKey, Point],
        threshold: int,
        N: int,
        params: UmbralParameters = None) -> Tuple[List[KFrag], List[Point]]:
    """
    Creates a re-encryption key and splits it using Shamir's Secret Sharing.
    Requires a threshold number of fragments out of N to rebuild rekey.

    Returns rekeys and the vKeys.
    """
    params = params if params is not None else default_params()

    if isinstance(priv_a, UmbralPrivateKey):
        priv_a = priv_a.bn_key

    if isinstance(pub_b, UmbralPublicKey):
        pub_b = pub_b.point_key

    g = params.g
    pub_a = priv_a * g

    x = BigNum.gen_rand(params.curve)
    xcomp = x * g
    d = hash_to_bn([xcomp, pub_b, pub_b * x], params)

    coeffs = [priv_a * (~d)]
    coeffs += [BigNum.gen_rand(params.curve) for _ in range(threshold - 1)]

    h = params.h
    u = params.u

    v_keys = [coeff * h for coeff in coeffs]

    rk_shares = []
    for _ in range(N):
        id_kfrag = BigNum.gen_rand(params.curve)
        rk = poly_eval(coeffs, id_kfrag)

        u1 = rk * u
        y = BigNum.gen_rand(params.curve)

        z1 = hash_to_bn([y * g, id_kfrag, pub_a, pub_b, u1, xcomp], params)
        z2 = y - priv_a * z1

        kFrag = KFrag(id_=id_kfrag, key=rk, x=xcomp, u1=u1, z1=z1, z2=z2)
        rk_shares.append(kFrag)

    return rk_shares, v_keys
Exemplo n.º 4
0
    def _reconstruct_shamirs_secret(self,
                                    pub_a: Union[UmbralPublicKey, Point],
                                    priv_b: Union[UmbralPrivateKey, BigNum],
                                    params: UmbralParameters = None) -> None:

        params = params if params is not None else default_params()

        if isinstance(priv_b, UmbralPrivateKey):
            priv_b = priv_b.bn_key

        if isinstance(pub_a, UmbralPublicKey):
            pub_a = pub_a.point_key

        g = params.g
        pub_b = priv_b * g
        g_ab = priv_b * pub_a

        blake2b = hashes.Hash(hashes.BLAKE2b(64), backend=backend)
        blake2b.update(pub_a.to_bytes())
        blake2b.update(pub_b.to_bytes())
        blake2b.update(g_ab.to_bytes())
        hashed_dh_tuple = blake2b.finalize()

        id_cfrag_pairs = list(self._attached_cfrags.items())
        id_0, cfrag_0 = id_cfrag_pairs[0]
        x_0 = hash_to_bn([id_0, hashed_dh_tuple], params)
        if len(id_cfrag_pairs) > 1:
            xs = [
                hash_to_bn([_id, hashed_dh_tuple], params)
                for _id in self._attached_cfrags.keys()
            ]
            lambda_0 = lambda_coeff(x_0, xs)
            e = lambda_0 * cfrag_0.point_eph_e1
            v = lambda_0 * cfrag_0.point_eph_v1

            for id_i, cfrag in id_cfrag_pairs[1:]:
                x_i = hash_to_bn([id_i, hashed_dh_tuple], params)
                lambda_i = lambda_coeff(x_i, xs)
                e = e + (lambda_i * cfrag.point_eph_e1)
                v = v + (lambda_i * cfrag.point_eph_v1)
        else:
            e = cfrag_0.point_eph_e1
            v = cfrag_0.point_eph_v1

        self._point_eph_e_prime = e
        self._point_eph_v_prime = v
        self._point_noninteractive = cfrag_0.point_eph_ni
Exemplo n.º 5
0
def _check_challenge(capsule: Capsule,
                     cfrag: CapsuleFrag,
                     challenge_resp: ChallengeResponse,
                     pub_a: Point,
                     pub_b: Point,
                     challenge_metadata: bytes = None,
                     params: UmbralParameters = None) -> bool:
    params = params if params is not None else default_params()

    e = capsule._point_eph_e
    v = capsule._point_eph_v

    e1 = cfrag.point_eph_e1
    v1 = cfrag.point_eph_v1
    xcomp = cfrag.point_eph_ni
    kfrag_id = cfrag.bn_kfrag_id

    e2 = challenge_resp.point_eph_e2
    v2 = challenge_resp.point_eph_v2

    g = params.g
    u = params.u

    u1 = challenge_resp.point_kfrag_commitment
    u2 = challenge_resp.point_kfrag_pok

    z1 = challenge_resp.bn_kfrag_sig1
    z2 = challenge_resp.bn_kfrag_sig2
    z3 = challenge_resp.bn_sig

    g_y = (z2 * g) + (z1 * pub_a)

    hash_input = [e, e1, e2, v, v1, v2, u, u1, u2]
    if challenge_metadata is not None:
        hash_input.append(challenge_metadata)

    h = hash_to_bn(hash_input, params)

    check31 = z1 == hash_to_bn([g_y, kfrag_id, pub_a, pub_b, u1, xcomp],
                               params)
    check32 = z3 * e == e2 + (h * e1)
    check33 = z3 * u == u2 + (h * u1)
    check34 = z3 * v == v2 + (h * v1)

    return check31 & check32 & check33 & check34
Exemplo n.º 6
0
    def verify(self, params: UmbralParameters = None) -> bool:
        params = params if params is not None else default_params()

        e = self._point_eph_e
        v = self._point_eph_v
        s = self._bn_sig
        h = hash_to_bn([e, v], params)

        return s * params.g == v + (h * e)
Exemplo n.º 7
0
    def verify(self, pub_a, pub_b, params: "UmbralParameters" = None):
        params = params if params is not None else default_params()

        u1 = self.point_commitment
        z1 = self.bn_sig1
        z2 = self.bn_sig2
        x = self.point_eph_ni

        g_y = (z2 * params.g) + (z1 * pub_a)

        return z1 == hash_to_bn([g_y, self.bn_id, pub_a, pub_b, u1, x], params)
Exemplo n.º 8
0
def _challenge(kfrag: KFrag,
               capsule: Capsule,
               cfrag: CapsuleFrag,
               challenge_metadata: bytes = None,
               params: UmbralParameters = None) -> ChallengeResponse:
    params = params if params is not None else default_params()

    e1 = cfrag.point_eph_e1
    v1 = cfrag.point_eph_v1

    e = capsule._point_eph_e
    v = capsule._point_eph_v

    u = params.u
    u1 = kfrag.point_commitment

    t = BigNum.gen_rand(params.curve)
    e2 = t * e
    v2 = t * v
    u2 = t * u

    hash_input = [e, e1, e2, v, v1, v2, u, u1, u2]
    if challenge_metadata is not None:
        hash_input.append(challenge_metadata)

    h = hash_to_bn(hash_input, params)

    z3 = t + h * kfrag.bn_key

    ch_resp = ChallengeResponse(e2=e2,
                                v2=v2,
                                u1=u1,
                                u2=u2,
                                z1=kfrag.bn_sig1,
                                z2=kfrag.bn_sig2,
                                z3=z3)

    # Check correctness of original ciphertext (check nº 2) at the end
    # to avoid timing oracles
    if not capsule.verify(params):
        raise capsule.NotValid("Capsule verification failed.")

    return ch_resp
Exemplo n.º 9
0
    def verify(self, pub_a, pub_b, params: "UmbralParameters" = None):
        params = params if params is not None else default_params()

        u = params.u

        u1 = self.point_commitment
        z1 = self.bn_sig1
        z2 = self.bn_sig2
        x = self.point_eph_ni
        key = self.bn_key

        # We check that the commitment u1 is well-formed
        check_kfrag_1 = u1 == key * u

        # We check the Schnorr signature over the kfrag components
        g_y = (z2 * params.g) + (z1 * pub_a)
        check_kfrag_2 = z1 == hash_to_bn(
            [g_y, self.bn_id, pub_a, pub_b, u1, x], params)

        return check_kfrag_1 & check_kfrag_2
Exemplo n.º 10
0
def _encapsulate(alice_pub_key: Point,
                 key_length=32,
                 params: UmbralParameters = None) -> Tuple[bytes, Capsule]:
    """Generates a symmetric key and its associated KEM ciphertext"""
    params = params if params is not None else default_params()

    g = params.g

    priv_r = BigNum.gen_rand(params.curve)
    pub_r = priv_r * g

    priv_u = BigNum.gen_rand(params.curve)
    pub_u = priv_u * g

    h = hash_to_bn([pub_r, pub_u], params)
    s = priv_u + (priv_r * h)

    shared_key = (priv_r + priv_u) * alice_pub_key

    # Key to be used for symmetric encryption
    key = kdf(shared_key, key_length)

    return key, Capsule(point_eph_e=pub_r, point_eph_v=pub_u, bn_sig=s)