Exemplo n.º 1
0
    def from_bytes(cls, capsule_bytes: bytes, params: UmbralParameters):
        """
        Instantiates a Capsule object from the serialized data.
        """
        curve = params.curve

        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        capsule_bytes_length = len(capsule_bytes)
        if capsule_bytes_length == cls.expected_bytes_length(curve,
                                                             activated=True):
            splitter = BytestringSplitter(
                (Point, point_size),  # point_e
                (Point, point_size),  # point_v
                (CurveBN, bn_size),  # bn_sig
                (Point, point_size),  # point_e_prime
                (Point, point_size),  # point_v_prime
                (Point, point_size)  # point_noninteractive
            )
        elif capsule_bytes_length == cls.expected_bytes_length(
                curve, activated=False):
            splitter = BytestringSplitter(
                (Point, point_size),  # point_e
                (Point, point_size),  # point_v
                (CurveBN, bn_size)  # bn_sig
            )
        else:
            raise ValueError(
                "Byte string does not have a valid length for a Capsule")

        components = splitter(capsule_bytes)
        return cls(params, *components)
Exemplo n.º 2
0
    def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'KFrag':
        """
        Instantiate a KFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()

        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)
        signature_size = Signature.expected_bytes_length(curve)
        arguments = {'curve': curve}

        splitter = BytestringSplitter(
            bn_size,  # id
            (CurveBN, bn_size, arguments),  # bn_key
            (Point, point_size, arguments),  # point_commitment
            (Point, point_size, arguments),  # point_precursor
            1,  # keys_in_signature
            (Signature, signature_size, arguments),  # signature_for_proxy
            (Signature, signature_size, arguments),  # signature_for_bob
        )
        components = splitter(data)

        return cls(identifier=components[0],
                   bn_key=components[1],
                   point_commitment=components[2],
                   point_precursor=components[3],
                   keys_in_signature=components[4],
                   signature_for_proxy=components[5],
                   signature_for_bob=components[6])
Exemplo n.º 3
0
    def from_bytes(cls,
                   data: bytes,
                   curve: Optional[Curve] = None) -> 'CapsuleFrag':
        """
        Instantiates a CapsuleFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()

        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)
        arguments = {'curve': curve}

        splitter = BytestringSplitter(
            (Point, point_size, arguments),  # point_e1
            (Point, point_size, arguments),  # point_v1
            bn_size,  # kfrag_id
            (Point, point_size, arguments),  # point_precursor
        )
        components = splitter(data, return_remainder=True)

        proof = components.pop() or None
        components.append(
            CorrectnessProof.from_bytes(proof, curve) if proof else None)

        return cls(*components)
Exemplo n.º 4
0
    def from_bytes(cls, capsule_bytes: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiates a Capsule object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        if len(capsule_bytes) == cls.expected_bytes_length(curve,
                                                           activated=True):
            splitter = BytestringSplitter(
                (Point, point_size),  # point_e
                (Point, point_size),  # point_v
                (CurveBN, bn_size),  # bn_sig
                (Point, point_size),  # point_e_prime
                (Point, point_size),  # point_v_prime
                (Point, point_size)  # point_noninteractive
            )
        else:
            splitter = BytestringSplitter(
                (Point, point_size),  # point_e
                (Point, point_size),  # point_v
                (CurveBN, bn_size)  # bn_sig
            )

        components = splitter(capsule_bytes)
        return cls(*components)
Exemplo n.º 5
0
    def expected_bytes_length(cls, curve: Optional[Curve] = None) -> int:
        """
        Returns the size (in bytes) of a Capsule given the curve.
        If no curve is provided, it will use the default curve.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        return (bn_size * 1) + (point_size * 2)
Exemplo n.º 6
0
    def expected_bytes_length(cls, curve: ec.EllipticCurve = None):
        """
        Returns the size (in bytes) of a KFrag given the curve.
        If no curve is provided, it will use the default curve.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        return (bn_size * 4) + (point_size * 3)
Exemplo n.º 7
0
    def expected_bytes_length(cls, curve: Optional[Curve] = None):
        """
        Returns the size (in bytes) of a CorrectnessProof without the metadata.
        If no curve is given, it will use the default curve.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve=curve)
        point_size = Point.expected_bytes_length(curve=curve)

        return (bn_size * 3) + (point_size * 4)
Exemplo n.º 8
0
    def expected_bytes_length(cls,
                              curve: Optional[EllipticCurve] = None) -> int:
        """
        Returns the size (in bytes) of a CapsuleFrag given the curve without
        the CorrectnessProof.
        If no curve is provided, it will use the default curve.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        return (bn_size * 1) + (point_size * 4)
Exemplo n.º 9
0
def test_serialization_rotations_of_1(curve):

    size_in_bytes = CurveBN.expected_bytes_length(curve)
    for i in range(size_in_bytes):
        lonely_one = 1 << i
        bn = CurveBN.from_int(lonely_one, curve)
        lonely_one_in_bytes = lonely_one.to_bytes(size_in_bytes, 'big')

        # Check serialization
        assert bn.to_bytes() == lonely_one_in_bytes

        # Check deserialization
        assert CurveBN.from_bytes(lonely_one_in_bytes, curve) == bn
Exemplo n.º 10
0
    def expected_bytes_length(cls,
                              curve: ec.EllipticCurve = None,
                              activated=False):
        """
        Returns the size (in bytes) of a Capsule given the curve.
        If no curve is provided, it will use the default curve.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        if not activated:
            return (bn_size * 1) + (point_size * 2)
        else:
            return (bn_size * 1) + (point_size * 5)
Exemplo n.º 11
0
    def expected_bytes_length(cls, curve: Optional[Curve] = None) -> int:
        """
        Returns the size (in bytes) of a KFrag given the curve.
        If no curve is provided, it will use the default curve.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        # self.id --> 1 bn_size
        # self.bn_key --> 1 bn_size
        # self.point_commitment --> 1 point_size
        # self.point_precursor --> 1 point_size
        # self.signature_for_proxy --> 2 bn_size
        # self.signature_for_bob --> 2 bn_size
        # self.keys_in_signature --> 1

        return bn_size * 6 + point_size * 2 + 1
Exemplo n.º 12
0
    def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiate a KFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()

        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        splitter = BytestringSplitter(
            bn_size,  # id
            (CurveBN, bn_size),  # bn_key
            (Point, point_size),  # point_noninteractive
            (Point, point_size),  # point_commitment
            (Point, point_size),  # point_xcoord
            (Signature, Signature.expected_bytes_length(curve)))
        components = splitter(data)

        return cls(*components)
Exemplo n.º 13
0
    def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiate CorrectnessProof from serialized data.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        splitter = BytestringSplitter(
            (Point, point_size),  # point_e2
            (Point, point_size),  # point_v2
            (Point, point_size),  # point_kfrag_commitment
            (Point, point_size),  # point_kfrag_pok
            (CurveBN, bn_size),  # bn_sig
            (Signature),  # kfrag_signature
        )
        components = splitter(data, return_remainder=True)
        metadata = components.pop(-1) or None

        return cls(*components, metadata=metadata)
Exemplo n.º 14
0
    def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'CorrectnessProof':
        """
        Instantiate CorrectnessProof from serialized data.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)
        arguments = {'curve': curve}
        splitter = BytestringSplitter(
            (Point, point_size, arguments),  # point_e2
            (Point, point_size, arguments),  # point_v2
            (Point, point_size, arguments),  # point_kfrag_commitment
            (Point, point_size, arguments),  # point_kfrag_pok
            (CurveBN, bn_size, arguments),  # bn_sig
            (Signature, Signature.expected_bytes_length(curve), arguments),  # kfrag_signature
        )
        components = splitter(data, return_remainder=True)
        components.append(components.pop() or None)

        return cls(*components)
Exemplo n.º 15
0
    def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiates a CapsuleFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()

        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)

        splitter = BytestringSplitter(
            (Point, point_size),  # point_e1
            (Point, point_size),  # point_v1
            bn_size,  # kfrag_id
            (Point, point_size),  # point_noninteractive
            (Point, point_size)  # point_xcoord
        )
        components = splitter(data, return_remainder=True)

        proof = components.pop(-1) or None
        proof = CorrectnessProof.from_bytes(proof, curve) if proof else None
        return cls(*components, proof)
Exemplo n.º 16
0
    def from_bytes(cls, capsule_bytes: bytes,
                   params: UmbralParameters) -> 'Capsule':
        """
        Instantiates a Capsule object from the serialized data.
        """
        curve = params.curve

        bn_size = CurveBN.expected_bytes_length(curve)
        point_size = Point.expected_bytes_length(curve)
        arguments = {'curve': curve}

        if len(capsule_bytes) == cls.expected_bytes_length(curve):
            splitter = BytestringSplitter(
                (Point, point_size, arguments),  # point_e
                (Point, point_size, arguments),  # point_v
                (CurveBN, bn_size, arguments)  # bn_sig
            )
        else:
            raise ValueError(
                "Byte string does not have a valid length for a Capsule")

        components = splitter(capsule_bytes)
        return cls(params, *components)
Exemplo n.º 17
0
def test_invalid_deserialization(curve):
	size_in_bytes = CurveBN.expected_bytes_length(curve)
	
	# All-zeros bytestring are invalid (i.e., 0 < bn < order of the curve)
	zero_bytes = bytes(size_in_bytes)
	with pytest.raises(ValueError):
		_bn = CurveBN.from_bytes(zero_bytes, curve)

	# All-ones bytestring is invalid too (since it's greater than order)
	lots_of_ones = 2**(8*size_in_bytes) - 1
	lots_of_ones = lots_of_ones.to_bytes(size_in_bytes, 'big')
	with pytest.raises(ValueError):
		_bn = CurveBN.from_bytes(lots_of_ones, curve)

	# Serialization of `order` is invalid since it's not strictly lower than 
	# the order of the curve
	order = default_backend()._bn_to_int(curve.order)
	with pytest.raises(ValueError):
		_bn = CurveBN.from_bytes(order.to_bytes(size_in_bytes, 'big'), curve)

	# On the other hand, serialization of `order - 1` is valid
	order -= 1
	_bn = CurveBN.from_bytes(order.to_bytes(size_in_bytes, 'big'), curve)
Exemplo n.º 18
0
def split_rekey(delegating_privkey: UmbralPrivateKey, signer: Signer,
                receiving_pubkey: UmbralPublicKey, threshold: int,
                N: int) -> 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.
    """

    if threshold <= 0 or threshold > N:
        raise ValueError(
            'Arguments threshold and N must satisfy 0 < threshold <= N')

    if delegating_privkey.params != receiving_pubkey.params:
        raise ValueError("Keys must have the same parameter set.")

    params = delegating_privkey.params

    g = params.g

    pubkey_a_point = delegating_privkey.get_pubkey().point_key
    privkey_a_bn = delegating_privkey.bn_key

    pubkey_b_point = receiving_pubkey.point_key

    # 'ni' stands for 'Non Interactive'.
    # This point is used as an ephemeral public key in a DH key exchange,
    # and the resulting shared secret 'd' allows to make Umbral non-interactive
    priv_ni = CurveBN.gen_rand(params.curve)
    ni = priv_ni * g
    d = CurveBN.hash(ni,
                     pubkey_b_point,
                     pubkey_b_point * priv_ni,
                     params=params)

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

    u = params.u

    # 'xcoord' stands for 'X coordinate'.
    # This point is used as an ephemeral public key in a DH key exchange,
    # and the resulting shared secret 'dh_xcoord' contributes to prevent
    # reconstruction of the re-encryption key without Bob's intervention
    priv_xcoord = CurveBN.gen_rand(params.curve)
    xcoord = priv_xcoord * g

    dh_xcoord = priv_xcoord * pubkey_b_point

    blake2b = hashes.Hash(hashes.BLAKE2b(64), backend=backend)
    blake2b.update(xcoord.to_bytes())
    blake2b.update(pubkey_b_point.to_bytes())
    blake2b.update(dh_xcoord.to_bytes())
    hashed_dh_tuple = blake2b.finalize()

    bn_size = CurveBN.expected_bytes_length(params.curve)

    kfrags = []
    for _ in range(N):
        id = os.urandom(bn_size)

        share_x = CurveBN.hash(id, hashed_dh_tuple, params=params)

        rk = poly_eval(coeffs, share_x)

        u1 = rk * u

        kfrag_validity_message = bytes().join(
            bytes(material) for material in (id, pubkey_a_point,
                                             pubkey_b_point, u1, ni, xcoord))
        signature = signer(kfrag_validity_message)

        kfrag = KFrag(id=id,
                      bn_key=rk,
                      point_noninteractive=ni,
                      point_commitment=u1,
                      point_xcoord=xcoord,
                      signature=signature)

        kfrags.append(kfrag)

    return kfrags
Exemplo n.º 19
0
def generate_kfrags(
    delegating_privkey: UmbralPrivateKey,
    receiving_pubkey: UmbralPublicKey,
    threshold: int,
    N: int,
    signer: Signer,
    sign_delegating_key: Optional[bool] = True,
    sign_receiving_key: Optional[bool] = True,
) -> List[KFrag]:
    """
    Creates a re-encryption key from Alice's delegating public key to Bob's
    receiving public key, and splits it in KFrags, using Shamir's Secret Sharing.
    Requires a threshold number of KFrags out of N.

    Returns a list of N KFrags
    """

    if threshold <= 0 or threshold > N:
        raise ValueError(
            'Arguments threshold and N must satisfy 0 < threshold <= N')

    if delegating_privkey.params != receiving_pubkey.params:
        raise ValueError("Keys must have the same parameter set.")

    params = delegating_privkey.params

    g = params.g

    delegating_pubkey = delegating_privkey.get_pubkey()

    bob_pubkey_point = receiving_pubkey.point_key

    # The precursor point is used as an ephemeral public key in a DH key exchange,
    # and the resulting shared secret 'dh_point' is used to derive other secret values
    private_precursor = CurveBN.gen_rand(params.curve)
    precursor = private_precursor * g  # type: Any

    dh_point = private_precursor * bob_pubkey_point

    # Secret value 'd' allows to make Umbral non-interactive
    d = hash_to_curvebn(precursor,
                        bob_pubkey_point,
                        dh_point,
                        bytes(constants.NON_INTERACTIVE),
                        params=params)

    # Coefficients of the generating polynomial
    coefficients = [delegating_privkey.bn_key * (~d)]
    coefficients += [
        CurveBN.gen_rand(params.curve) for _ in range(threshold - 1)
    ]

    bn_size = CurveBN.expected_bytes_length(params.curve)

    kfrags = list()
    for _ in range(N):
        kfrag_id = os.urandom(bn_size)

        # The index of the re-encryption key share (which in Shamir's Secret
        # Sharing corresponds to x in the tuple (x, f(x)), with f being the
        # generating polynomial), is used to prevent reconstruction of the
        # re-encryption key without Bob's intervention
        share_index = hash_to_curvebn(precursor,
                                      bob_pubkey_point,
                                      dh_point,
                                      bytes(constants.X_COORDINATE),
                                      kfrag_id,
                                      params=params)

        # The re-encryption key share is the result of evaluating the generating
        # polynomial for the index value
        rk = poly_eval(coefficients, share_index)

        commitment = rk * params.u  # type: Any

        validity_message_for_bob = (
            kfrag_id,
            delegating_pubkey,
            receiving_pubkey,
            commitment,
            precursor,
        )  # type: Any
        validity_message_for_bob = bytes().join(
            bytes(item) for item in validity_message_for_bob)
        signature_for_bob = signer(validity_message_for_bob)

        if sign_delegating_key and sign_receiving_key:
            mode = DELEGATING_AND_RECEIVING
        elif sign_delegating_key:
            mode = DELEGATING_ONLY
        elif sign_receiving_key:
            mode = RECEIVING_ONLY
        else:
            mode = NO_KEY

        validity_message_for_proxy = [kfrag_id, commitment, precursor,
                                      mode]  # type: Any

        if sign_delegating_key:
            validity_message_for_proxy.append(delegating_pubkey)
        if sign_receiving_key:
            validity_message_for_proxy.append(receiving_pubkey)

        validity_message_for_proxy = bytes().join(
            bytes(item) for item in validity_message_for_proxy)
        signature_for_proxy = signer(validity_message_for_proxy)

        kfrag = KFrag(
            identifier=kfrag_id,
            bn_key=rk,
            point_commitment=commitment,
            point_precursor=precursor,
            signature_for_proxy=signature_for_proxy,
            signature_for_bob=signature_for_bob,
            keys_in_signature=mode,
        )

        kfrags.append(kfrag)

    return kfrags
Exemplo n.º 20
0
def split_rekey(privkey_a_bn: Union[UmbralPrivateKey, CurveBN],
                signer_a: Signer,
                pubkey_b_point: 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()

    g = params.g

    if isinstance(privkey_a_bn, UmbralPrivateKey):
        pubkey_a_point = privkey_a_bn.get_pubkey().point_key
        privkey_a_bn = privkey_a_bn.bn_key
    else:
        pubkey_a_point = privkey_a_bn * g

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

    # 'ni' stands for 'Non Interactive'.
    # This point is used as an ephemeral public key in a DH key exchange,
    # and the resulting shared secret 'd' allows to make Umbral non-interactive
    priv_ni = CurveBN.gen_rand(params.curve)
    ni = priv_ni * g
    d = CurveBN.hash(ni,
                     pubkey_b_point,
                     pubkey_b_point * priv_ni,
                     params=params)

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

    u = params.u

    # 'xcoord' stands for 'X coordinate'.
    # This point is used as an ephemeral public key in a DH key exchange,
    # and the resulting shared secret 'dh_xcoord' contributes to prevent
    # reconstruction of the re-encryption key without Bob's intervention
    priv_xcoord = CurveBN.gen_rand(params.curve)
    xcoord = priv_xcoord * g

    dh_xcoord = priv_xcoord * pubkey_b_point

    blake2b = hashes.Hash(hashes.BLAKE2b(64), backend=backend)
    blake2b.update(xcoord.to_bytes())
    blake2b.update(pubkey_b_point.to_bytes())
    blake2b.update(dh_xcoord.to_bytes())
    hashed_dh_tuple = blake2b.finalize()

    bn_size = CurveBN.expected_bytes_length(params.curve)

    kfrags = []
    for _ in range(N):
        id = os.urandom(bn_size)

        share_x = CurveBN.hash(id, hashed_dh_tuple, params=params)

        rk = poly_eval(coeffs, share_x)

        u1 = rk * u

        kfrag_validity_message = bytes().join(
            bytes(material) for material in (id, pubkey_a_point,
                                             pubkey_b_point, u1, ni, xcoord))
        signature = signer_a(kfrag_validity_message)

        kfrag = KFrag(id=id,
                      bn_key=rk,
                      point_noninteractive=ni,
                      point_commitment=u1,
                      point_xcoord=xcoord,
                      signature=signature)
        kfrags.append(kfrag)

    return kfrags