Example #1
0
def _decapsulate_reencrypted(receiving_privkey: UmbralPrivateKey,
                             capsule: Capsule,
                             key_length: int = DEM_KEYSIZE) -> bytes:
    """Derive the same symmetric key"""
    params = capsule._umbral_params

    pub_key = receiving_privkey.get_pubkey().point_key
    priv_key = receiving_privkey.bn_key

    ni = capsule._point_noninteractive
    d = CurveBN.hash(ni, pub_key, priv_key * ni, params=params)

    e_prime = capsule._point_e_prime
    v_prime = capsule._point_v_prime

    shared_key = d * (e_prime + v_prime)

    key = kdf(shared_key, key_length)

    e = capsule._point_e
    v = capsule._point_v
    s = capsule._bn_sig
    h = CurveBN.hash(e, v, params=params)
    inv_d = ~d
    orig_pub_key = capsule.get_correctness_keys()['delegating'].point_key

    if not (s * inv_d) * orig_pub_key == (h * e_prime) + v_prime:
        raise GenericUmbralError()
    return key
Example #2
0
def _decapsulate_reencrypted(receiving_privkey: UmbralPrivateKey,
                             capsule: Capsule,
                             key_length: int = DEM_KEYSIZE) -> bytes:
    """Derive the same symmetric encapsulated_key"""

    params = capsule.params

    pub_key = receiving_privkey.get_pubkey().point_key
    priv_key = receiving_privkey.bn_key

    precursor = capsule._attached_cfrags[0]._point_precursor
    dh_point = priv_key * precursor

    from constant_sorrow import constants

    # Combination of CFrags via Shamir's Secret Sharing reconstruction
    if len(capsule._attached_cfrags) > 1:
        xs = [
            CurveBN.hash(precursor,
                         pub_key,
                         dh_point,
                         bytes(constants.X_COORDINATE),
                         cfrag._kfrag_id,
                         params=params) for cfrag in capsule._attached_cfrags
        ]

        e_summands, v_summands = list(), list()
        for cfrag, x in zip(capsule._attached_cfrags, xs):
            if precursor != cfrag._point_precursor:
                raise ValueError("Attached CFrags are not pairwise consistent")

            lambda_i = lambda_coeff(x, xs)
            e_summands.append(lambda_i * cfrag._point_e1)
            v_summands.append(lambda_i * cfrag._point_v1)

        e_prime = sum(e_summands[1:], e_summands[0])
        v_prime = sum(v_summands[1:], v_summands[0])
    else:
        e_prime = capsule._attached_cfrags[0]._point_e1
        v_prime = capsule._attached_cfrags[0]._point_v1

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

    e, v, s = capsule.components()
    h = CurveBN.hash(e, v, params=params)

    orig_pub_key = capsule.get_correctness_keys(
    )['delegating'].point_key  # type: ignore

    if not (s / d) * orig_pub_key == (h * e_prime) + v_prime:
        raise GenericUmbralError()

    shared_key = d * (e_prime + v_prime)
    encapsulated_key = kdf(shared_key, key_length)
    return encapsulated_key
Example #3
0
def _decapsulate_reencrypted(pub_key: Point, priv_key: CurveBN,
                            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 = CurveBN.hash_to_bn(xcomp, pub_key, priv_key * xcomp, params=params)

    e_prime = capsule._point_e_prime
    v_prime = capsule._point_v_prime

    shared_key = d * (e_prime + v_prime)

    key = kdf(shared_key, key_length)

    e = capsule._point_e
    v = capsule._point_v
    s = capsule._bn_sig
    h = CurveBN.hash_to_bn(e, v, params=params)
    inv_d = ~d

    if not (s*inv_d) * orig_pub_key == (h*e_prime) + v_prime:
        raise GenericUmbralError()
    return key
Example #4
0
def _decapsulate_original(priv_key: UmbralPrivateKey,
                          capsule: Capsule,
                          key_length: int = DEM_KEYSIZE) -> bytes:
    """Derive the same symmetric key"""

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

    shared_key = priv_key.bn_key * (capsule._point_e + capsule._point_v
                                    )  # type: Any
    key = kdf(shared_key, key_length)
    return key
Example #5
0
def _decapsulate_original(priv_key: CurveBN, capsule: Capsule, key_length=32,
                          params: UmbralParameters=None) -> bytes:
    """Derive the same symmetric key"""
    params = params if params is not None else default_params()

    shared_key = priv_key * (capsule._point_e+capsule._point_v)
    key = kdf(shared_key, key_length)

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

    return key
Example #6
0
def encrypt(plaintext, associated_data=None):
    """
    Encrypts plaintext with ChaCha20. They key used is the HKDF hash of the
    byte representation of a random point on the chosen elliptic curve.
    Returns (private_key_point, ciphertext).
    """

    nonce = os.urandom(NONCE_SIZE)
    key_point = point.Point.gen_rand()
    key = utils.kdf(key_point, KEY_SIZE)

    ciphertext = ChaCha20Poly1305(key).encrypt(nonce,
                                               plaintext,
                                               associated_data)
    return key_point, nonce + ciphertext
Example #7
0
def _decapsulate_original(priv_key: UmbralPrivateKey,
                          capsule: Capsule,
                          key_length: int = DEM_KEYSIZE) -> bytes:
    """Derive the same symmetric key"""

    priv_key = priv_key.bn_key

    shared_key = priv_key * (capsule._point_e + capsule._point_v)
    key = kdf(shared_key, key_length)

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

    return key
Example #8
0
def decrypt(ciphertext, key, associated_data=None):
    """
    Decrypts ciphertext.
    Returns plaintext.
    """

    # the key returned by encrypt() is a point obj, has to be hashed for ChaCha
    if isinstance(key, point.Point):
        key = utils.kdf(key, KEY_SIZE)

    nonce = ciphertext[:NONCE_SIZE]
    cipher_without_nonce = ciphertext[NONCE_SIZE:]
    plaintext = ChaCha20Poly1305(key).decrypt(
        nonce, cipher_without_nonce, associated_data
    )
    return plaintext
Example #9
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)
Example #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 = 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)