Ejemplo n.º 1
0
def _prove_correctness(cfrag: CapsuleFrag, kfrag: KFrag, capsule: Capsule, 
                       metadata: bytes=None, params: UmbralParameters=None
                      ) -> CorrectnessProof:
    params = params if params is not None else default_params()

    e1 = cfrag._point_e1
    v1 = cfrag._point_v1

    e = capsule._point_e
    v = capsule._point_v

    u = params.u
    u1 = kfrag._point_commitment

    rk = kfrag._bn_key

    t = CurveBN.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 metadata is not None:
        hash_input.append(metadata)

    h = CurveBN.hash_to_bn(*hash_input, params=params)

    z3 = t + h * rk

    cfrag.proof = CorrectnessProof(point_e2=e2, 
                                   point_v2=v2, 
                                   point_kfrag_commitment=u1,
                                   point_kfrag_pok=u2,
                                   bn_kfrag_sig1=kfrag._bn_sig1,
                                   bn_kfrag_sig2=kfrag._bn_sig2,
                                   bn_sig=z3,
                                   metadata=metadata)

    # 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.")
Ejemplo n.º 2
0
    def expected_bytes_length(cls, curve: Optional[EllipticCurve] = 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)
Ejemplo n.º 3
0
    def verify(self) -> bool:

        g = self._umbral_params.g
        e = self._point_e
        v = self._point_v
        s = self._bn_sig
        h = CurveBN.hash(e, v, params=self._umbral_params)

        result = s * g == v + (h * e)  # type: bool
        return result
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
    def get_size(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.get_size(curve)
        point_size = Point.get_size(curve)

        return (bn_size * 4) + (point_size * 2)
Ejemplo n.º 6
0
    def get_size(cls, curve: ec.EllipticCurve = 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.get_size(curve=curve)
        point_size = Point.get_size(curve=curve)

        return (bn_size * 3) + (point_size * 4)
Ejemplo n.º 7
0
def prove_cfrag_correctness(
        cfrag: "CapsuleFrag",
        kfrag: "KFrag",
        capsule: "Capsule",
        metadata: bytes = None,
        params: UmbralParameters = None) -> "CorrectnessProof":
    params = params if params is not None else default_params()

    rk = kfrag._bn_key
    t = CurveBN.gen_rand(params.curve)
    ####
    ## Here are the formulaic constituents shared with `assess_cfrag_correctness`.
    ####
    e = capsule._point_e
    v = capsule._point_v

    e1 = cfrag._point_e1
    v1 = cfrag._point_v1

    u = params.u
    u1 = kfrag._point_commitment

    e2 = t * e
    v2 = t * v
    u2 = t * u

    hash_input = [e, e1, e2, v, v1, v2, u, u1, u2]
    if metadata is not None:
        hash_input.append(metadata)
    h = CurveBN.hash(*hash_input, params=params)

    z1 = kfrag._bn_sig1
    z2 = kfrag._bn_sig2
    z3 = t + h * rk
    ########

    cfrag.attach_proof(e2, v2, u1, u2, z1, z2, z3, metadata)

    # 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.")
Ejemplo n.º 8
0
    def gen_key(
            cls,
            params: Optional[UmbralParameters] = None) -> 'UmbralPrivateKey':
        """
        Generates a private key and returns it.
        """
        if params is None:
            params = default_params()

        bn_key = CurveBN.gen_rand(params.curve)
        return cls(bn_key, params)
Ejemplo n.º 9
0
def test_bad_capsule_fails_reencryption(alices_keys):
    priv_key_alice, pub_key_alice = alices_keys

    kfrags = pre.split_rekey(priv_key_alice, pub_key_alice, 1, 2)

    bollocks_capsule = Capsule(point_e=Point.gen_rand(),
                               point_v=Point.gen_rand(),
                               bn_sig=CurveBN.gen_rand())

    with pytest.raises(Capsule.NotValid):
        pre.reencrypt(kfrags[0], bollocks_capsule)
Ejemplo n.º 10
0
def test_bad_capsule_fails_reencryption(kfrags):
    params = default_params()

    bollocks_capsule = Capsule(params,
                               point_e=Point.gen_rand(),
                               point_v=Point.gen_rand(),
                               bn_sig=CurveBN.gen_rand())

    for kfrag in kfrags:
        with pytest.raises(Capsule.NotValid):
            pre.reencrypt(kfrag, bollocks_capsule)
Ejemplo n.º 11
0
    def get_size(cls, curve: ec.EllipticCurve = None):
        """
        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.get_size(curve)
        point_size = Point.get_size(curve)

        return (bn_size * 1) + (point_size * 3)
Ejemplo 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.get_size(curve)
        point_size = Point.get_size(curve)
        data = BytesIO(data)

        # CurveBNs are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        id = data.read(bn_size)
        key = CurveBN.from_bytes(data.read(bn_size), curve)
        ni = Point.from_bytes(data.read(point_size), curve)
        commitment = Point.from_bytes(data.read(point_size), curve)
        xcoord = Point.from_bytes(data.read(point_size), curve)
        sig1 = CurveBN.from_bytes(data.read(bn_size), curve)
        sig2 = CurveBN.from_bytes(data.read(bn_size), curve)

        return cls(id, key, ni, commitment, xcoord, sig1, sig2)
Ejemplo n.º 13
0
def lambda_coeff(id_i: CurveBN, selected_ids: List[CurveBN]) -> CurveBN:
    ids = [x for x in selected_ids if x != id_i]

    if not ids:
        return CurveBN.from_int(1, id_i.curve)

    result = ids[0] / (ids[0] - id_i)
    for id_j in ids[1:]:
        result = result * id_j / (id_j - id_i)

    return result
Ejemplo n.º 14
0
def test_capsule_equality():
    params = default_params()

    one_capsule = Capsule(params,
                          point_e=Point.gen_rand(),
                          point_v=Point.gen_rand(),
                          bn_sig=CurveBN.gen_rand())

    another_capsule = Capsule(params,
                              point_e=Point.gen_rand(),
                              point_v=Point.gen_rand(),
                              bn_sig=CurveBN.gen_rand())

    assert one_capsule != another_capsule

    activated_capsule = Capsule(params,
                                point_e_prime=Point.gen_rand(),
                                point_v_prime=Point.gen_rand(),
                                point_noninteractive=Point.gen_rand())

    assert activated_capsule != one_capsule
Ejemplo n.º 15
0
    def from_bytes(cls,
                   signature_as_bytes: bytes,
                   der_encoded: bool = False,
                   curve: Optional[Curve] = None) -> 'Signature':
        curve = curve if curve is not None else default_curve()
        if der_encoded:
            r, s = decode_dss_signature(signature_as_bytes)
        else:
            expected_len = cls.expected_bytes_length(curve)
            if not len(signature_as_bytes) == expected_len:
                raise ValueError(
                    "Looking for exactly {} bytes if you call from_bytes \
                    with der_encoded=False and curve={}.".format(
                        expected_len, curve))
            else:
                r = int.from_bytes(signature_as_bytes[:(expected_len // 2)],
                                   "big")
                s = int.from_bytes(signature_as_bytes[(expected_len // 2):],
                                   "big")

        return cls(CurveBN.from_int(r, curve), CurveBN.from_int(s, curve))
Ejemplo n.º 16
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)
Ejemplo n.º 17
0
def prove_cfrag_correctness(cfrag: 'CapsuleFrag',
                            kfrag: 'KFrag',
                            capsule: 'Capsule',
                            metadata: Optional[bytes] = None
                            ) -> 'CorrectnessProof':

    params = capsule._umbral_params

    rk = kfrag._bn_key
    t = CurveBN.gen_rand(params.curve)
    ####
    # Here are the formulaic constituents shared with `assess_cfrag_correctness`.
    ####
    e = capsule._point_e
    v = capsule._point_v

    e1 = cfrag._point_e1
    v1 = cfrag._point_v1

    u = params.u
    u1 = kfrag._point_commitment

    e2 = t * e
    v2 = t * v
    u2 = t * u

    hash_input = (e, e1, e2, v, v1, v2, u, u1, u2)
    if metadata is not None:
        hash_input += (metadata,)
    h = CurveBN.hash(*hash_input, params=params)
    ########

    z3 = t + h * rk

    cfrag.attach_proof(e2, v2, u1, u2, metadata=metadata, z3=z3, kfrag_signature=kfrag.signature)

    # Check correctness of original ciphertext (check nº 2) at the end
    # to avoid timing oracles
    if not capsule.verify():
        raise capsule.NotValid("Capsule verification failed.")
Ejemplo n.º 18
0
def _encapsulate(alice_pubkey: UmbralPublicKey,
                 key_length: int = DEM_KEYSIZE) -> Tuple[bytes, Capsule]:
    """Generates a symmetric key and its associated KEM ciphertext"""

    params = alice_pubkey.params
    g = params.g

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

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

    h = CurveBN.hash(pub_r, pub_u, params=params)
    s = priv_u + (priv_r * h)

    shared_key = (priv_r + priv_u) * alice_pubkey.point_key

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

    return key, Capsule(point_e=pub_r, point_v=pub_u, bn_sig=s, params=params)
Ejemplo n.º 19
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 = CurveBN.gen_rand(params.curve)
    pub_r = priv_r * g

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

    h = CurveBN.hash_to_bn(pub_r, pub_u, params=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_e=pub_r, point_v=pub_u, bn_sig=s)
Ejemplo n.º 20
0
def test_cannot_create_capsule_from_bogus_material(alices_keys):
    params = alices_keys[0].params

    with pytest.raises(TypeError):
        _capsule_of_questionable_parentage = Capsule(params,
                                                     point_e=Point.gen_rand(),
                                                     point_v=42,
                                                     bn_sig=CurveBN.gen_rand())

    with pytest.raises(TypeError):
        _capsule_of_questionable_parentage = Capsule(params,
                                                     point_e=Point.gen_rand(),
                                                     point_v=Point.gen_rand(),
                                                     bn_sig=42)
Ejemplo n.º 21
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)
Ejemplo n.º 22
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.get_size(curve)
        point_size = Point.get_size(curve)
        data = BytesIO(data)

        # CurveBNs are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        e2 = Point.from_bytes(data.read(point_size), curve)
        v2 = Point.from_bytes(data.read(point_size), curve)
        kfrag_commitment = Point.from_bytes(data.read(point_size), curve)
        kfrag_pok = Point.from_bytes(data.read(point_size), curve)
        kfrag_sig1 = CurveBN.from_bytes(data.read(bn_size), curve)
        kfrag_sig2 = CurveBN.from_bytes(data.read(bn_size), curve)
        sig = CurveBN.from_bytes(data.read(bn_size), curve)

        metadata = data.read() or None

        return cls(e2, v2, kfrag_commitment, kfrag_pok, 
                   kfrag_sig1, kfrag_sig2, sig, metadata=metadata)
Ejemplo n.º 23
0
    def get_order_from_curve(cls, curve: ec.EllipticCurve=None):
        """
        Returns the order from the given curve as a CurveBN.
        """
        curve = curve if curve is not None else default_curve()
        try:
            curve_nid = backend._elliptic_curve_to_nid(curve)
        except AttributeError:
            # Presume that the user passed in the curve_nid
            curve_nid = curve

        group = openssl._get_ec_group_by_curve_nid(curve_nid)
        order = openssl._get_ec_order_by_curve_nid(curve_nid)

        return CurveBN(order, curve_nid, group, order)
Ejemplo n.º 24
0
def test_bad_capsule_fails_reencryption(alices_keys, bobs_keys):
    delegating_privkey, _signing_privkey = alices_keys
    signer_alice = Signer(_signing_privkey)

    _receiving_privkey, receiving_pubkey = bobs_keys

    kfrags = pre.split_rekey(delegating_privkey, signer_alice,
                             receiving_pubkey, 1, 2)

    bollocks_capsule = Capsule(point_e=Point.gen_rand(),
                               point_v=Point.gen_rand(),
                               bn_sig=CurveBN.gen_rand())

    with pytest.raises(Capsule.NotValid):
        pre.reencrypt(kfrags[0], bollocks_capsule)
def test_curvebn_hash():

    vector_file = os.path.join('vectors', 'vectors_curvebn_hash.json')
    try:
        with open(vector_file) as f:
            vector_suite = json.load(f)
    except OSError:
        raise

    params = default_params()

    for vector in vector_suite['vectors']:
        hash_input = [bytes.fromhex(item['bytes']) for item in vector['input']]
        expected = CurveBN.from_bytes(bytes.fromhex(vector['output']))
        assert hash_to_curvebn(*hash_input, params=params) == expected
Ejemplo n.º 26
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)
Ejemplo n.º 27
0
    def prove_correctness(self,
                          capsule,
                          kfrag,
                          metadata: Optional[bytes] = None):

        params = capsule.params

        # Check correctness of original ciphertext
        if not capsule.verify():
            raise capsule.NotValid("Capsule verification failed.")

        rk = kfrag.bn_key
        t = CurveBN.gen_rand(params.curve)
        ####
        # Here are the formulaic constituents shared with `verify_correctness`.
        ####
        e = capsule.point_e
        v = capsule.point_v

        e1 = self.point_e1
        v1 = self.point_v1

        u = params.u
        u1 = kfrag.point_commitment

        e2 = t * e  # type: Any
        v2 = t * v  # type: Any
        u2 = t * u  # type: Any

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

        h = hash_to_curvebn(*hash_input,
                            params=params,
                            hash_class=ExtendedKeccak)
        ########

        z3 = t + h * rk

        self.attach_proof(e2,
                          v2,
                          u1,
                          u2,
                          metadata=metadata,
                          z3=z3,
                          kfrag_signature=kfrag.signature_for_bob)
Ejemplo n.º 28
0
def test_capsule_creation(alices_keys):
    with pytest.raises(TypeError):
        rare_capsule = Capsule()  # Alice cannot make a capsule this way.

    # Some users may create capsules their own way.
    custom_capsule = Capsule(point_e=Point.gen_rand(),
                             point_v=Point.gen_rand(),
                             bn_sig=CurveBN.gen_rand())

    assert isinstance(custom_capsule, Capsule)

    # Typical Alice, constructing a typical capsule
    _, alices_public_key = alices_keys
    plaintext = b'peace at dawn'
    ciphertext, typical_capsule = pre.encrypt(alices_public_key, plaintext)

    assert isinstance(typical_capsule, Capsule)
Ejemplo n.º 29
0
def _mock_ursula_reencrypts(ursula, corrupt_cfrag: bool = False):
    delegating_privkey = UmbralPrivateKey.gen_key()
    _symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey())
    signing_privkey = UmbralPrivateKey.gen_key()
    signing_pubkey = signing_privkey.get_pubkey()
    signer = Signer(signing_privkey)
    priv_key_bob = UmbralPrivateKey.gen_key()
    pub_key_bob = priv_key_bob.get_pubkey()
    kfrags = pre.generate_kfrags(delegating_privkey=delegating_privkey,
                                 signer=signer,
                                 receiving_pubkey=pub_key_bob,
                                 threshold=2,
                                 N=4,
                                 sign_delegating_key=False,
                                 sign_receiving_key=False)
    capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob,
                                 signing_pubkey)

    ursula_pubkey = ursula.stamp.as_umbral_pubkey()

    alice_address = canonical_address_from_umbral_key(signing_pubkey)
    blockhash = bytes(32)

    specification = b''.join((bytes(capsule), bytes(ursula_pubkey),
                              bytes(ursula.decentralized_identity_evidence),
                              alice_address, blockhash))

    bobs_signer = Signer(priv_key_bob)
    task_signature = bytes(bobs_signer(specification))

    metadata = bytes(ursula.stamp(task_signature))

    cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata)

    if corrupt_cfrag:
        cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)

    cfrag_signature = bytes(ursula.stamp(bytes(cfrag)))

    bob = Bob.from_public_keys(verifying_key=pub_key_bob)
    task = WorkOrder.Task(capsule, task_signature, cfrag, cfrag_signature)
    work_order = WorkOrder(bob, None, alice_address, [task], None, ursula,
                           blockhash)

    evidence = IndisputableEvidence(task, work_order)
    return evidence
Ejemplo n.º 30
0
    def gen_rand(cls, curve: Optional[Curve] = None) -> 'Point':
        """
        Returns a Point object with a cryptographically secure EC_POINT based
        on the provided curve.
        """
        curve = curve if curve is not None else default_curve()

        rand_point = openssl._get_new_EC_POINT(curve)
        rand_bn = CurveBN.gen_rand(curve).bignum

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_mul(curve.ec_group, rand_point,
                                            backend._ffi.NULL, curve.generator,
                                            rand_bn, bn_ctx)
            backend.openssl_assert(res == 1)

        return cls(rand_point, curve)