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 # Combination of CFrags via Shamir's Secret Sharing reconstruction xs = list() for cfrag in capsule._attached_cfrags: x = hash_to_curvebn(precursor, pub_key, dh_point, bytes(constants.X_COORDINATE), cfrag.kfrag_id, params=params) xs.append(x) 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]) # Secret value 'd' allows to make Umbral non-interactive d = hash_to_curvebn(precursor, pub_key, dh_point, bytes(constants.NON_INTERACTIVE), params=params) e, v, s = capsule.components() h = hash_to_curvebn(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
def _decapsulate_original(private_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 = private_key.bn_key * (capsule.point_e + capsule.point_v ) # type: Any key = kdf(shared_key, key_length) return key
def test_point_operations(): vector_file = os.path.join('vectors', 'vectors_point_operations.json') try: with open(vector_file) as f: vector_suite = json.load(f) except OSError: raise point1 = Point.from_bytes( bytes.fromhex(vector_suite['first Point operand'])) point2 = Point.from_bytes( bytes.fromhex(vector_suite['second Point operand'])) bn1 = CurveBN.from_bytes(bytes.fromhex(vector_suite['CurveBN operand'])) expected = dict() for op_result in vector_suite['vectors']: expected[op_result['operation']] = bytes.fromhex(op_result['result']) test = [ ('Addition', point1 + point2), ('Subtraction', point1 - point2), ('Multiplication', bn1 * point1), ('Inversion', -point1), ] for (operation, result) in test: assert result == Point.from_bytes( expected[operation]), 'Error in {}'.format(operation) test = [ ('To_affine.X', point1.to_affine()[0]), ('To_affine.Y', point1.to_affine()[1]), ] for (operation, result) in test: assert result == int.from_bytes(expected[operation], 'big'), 'Error in {}'.format(operation) assert kdf(point1, pre.DEM_KEYSIZE) == expected['kdf']
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 # type: Any priv_u = CurveBN.gen_rand(params.curve) pub_u = priv_u * g # type: Any h = hash_to_curvebn(pub_r, pub_u, params=params) s = priv_u + (priv_r * h) shared_key = (priv_r + priv_u) * alice_pubkey.point_key # type: Any # 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)
########## # Points # ########## point1 = Point.gen_rand(curve) point2 = Point.gen_rand(curve) # Expected results for some Point operations expected = [('Addition', point1 + point2), ('Subtraction', point1 - point2), ('Multiplication', bn1 * point1), ('Inversion', -point1), ('To_affine.X', point1.to_affine()[0]), ('To_affine.Y', point1.to_affine()[1]), ('kdf', kdf(point1, pre.DEM_KEYSIZE)), ] expected = [{'operation': op, 'result': hexlify(result)} for (op, result) in expected] # Definition of test vector vector_suite = { 'name': 'Test vectors for Point operations', 'params': 'default', 'first Point operand': hexlify(point1), 'second Point operand': hexlify(point2), 'CurveBN operand': hexlify(bn1), 'vectors': expected } json_file = 'vectors_point_operations.json'