def test_verify(testerchain, signature_verifier): message = os.urandom(100) # Generate Umbral key umbral_privkey = UmbralPrivateKey.gen_key() umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False) # Sign message using SHA-256 hash cryptography_priv_key = umbral_privkey.to_cryptography_privkey() signature_der_bytes = cryptography_priv_key.sign(message, ec.ECDSA(hashes.SHA256())) signature = Signature.from_bytes(signature_der_bytes, der_encoded=True) # Prepare message hash hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend) hash_ctx.update(message) message_hash = hash_ctx.finalize() # Get recovery id (v) before using contract # First try v = 0 recoverable_signature = bytes(signature) + bytes([0]) pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, message_hash, hasher=None) \ .format(compressed=False) if pubkey_bytes != umbral_pubkey_bytes: # Extracted public key is not ours, that means v = 1 recoverable_signature = bytes(signature) + bytes([1]) # Verify signature assert signature_verifier.functions.\ verify(message, recoverable_signature, umbral_pubkey_bytes[1:], ALGORITHM_SHA256).call() # Verify signature using wrong key umbral_privkey = UmbralPrivateKey.gen_key() umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False) assert not signature_verifier.functions.\ verify(message, recoverable_signature, umbral_pubkey_bytes[1:], ALGORITHM_SHA256).call()
def test_cannot_attach_cfrag_without_proof(): """ However, even when properly attaching keys, we can't attach the CFrag if it is unproven. """ params = default_params() capsule = Capsule(params, point_e=Point.gen_rand(), point_v=Point.gen_rand(), bn_sig=CurveBN.gen_rand()) cfrag = CapsuleFrag( point_e1=Point.gen_rand(), point_v1=Point.gen_rand(), kfrag_id=os.urandom(10), point_precursor=Point.gen_rand(), ) key_details = capsule.set_correctness_keys( UmbralPrivateKey.gen_key().get_pubkey(), UmbralPrivateKey.gen_key().get_pubkey(), UmbralPrivateKey.gen_key().get_pubkey()) delegating_details, receiving_details, verifying_details = key_details assert all((delegating_details, receiving_details, verifying_details)) with pytest.raises(cfrag.NoProofProvided): capsule.attach_cfrag(cfrag)
def test_verify(testerchain, signature_verifier): message = os.urandom(100) # Generate Umbral key umbral_privkey = UmbralPrivateKey.gen_key() umbral_pubkey = umbral_privkey.get_pubkey() umbral_pubkey_bytes = umbral_pubkey.to_bytes(is_compressed=False) # Sign message using SHA-256 hash signer = Signer(umbral_privkey) signature = signer(message) # Get recovery id (v) before using contract v = get_signature_recovery_value(message, signature, umbral_pubkey) recoverable_signature = bytes(signature) + v # Verify signature assert signature_verifier.functions.verify(message, recoverable_signature, umbral_pubkey_bytes[1:], ALGORITHM_SHA256).call() # Verify signature using wrong key umbral_privkey = UmbralPrivateKey.gen_key() umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False) assert not signature_verifier.functions.verify(message, recoverable_signature, umbral_pubkey_bytes[1:], ALGORITHM_SHA256).call()
def test_privkey_roundtrip(p): insecure_scrypt_cost = 5 # This is deliberately insecure, just to make it faster k = UmbralPrivateKey.gen_key() rt = UmbralPrivateKey.from_bytes(k.to_bytes(password=p, _scrypt_cost=insecure_scrypt_cost), password=p, _scrypt_cost=insecure_scrypt_cost) assert(k.get_pubkey() == rt.get_pubkey())
def get_reseller_pubkeys(ethPk): try: reseller_privkey = UmbralPrivateKey.from_bytes(bytes.fromhex(ethPk)) except IndexError: reseller_privkey = UmbralPrivateKey.gen_key() return reseller_privkey.get_pubkey();
def generate_keys(path): """ Generate public and private keys Args: path (str): path where the public and private key files should be stored Returns: privkeys, pubkeys (dict, dict): private and public keys dict containing enc and sig keys """ enc_privkey = UmbralPrivateKey.gen_key() sig_privkey = UmbralPrivateKey.gen_key() if not os.path.exists(path): try: os.makedirs(path) except OSError as exc: if exc.errno != errno.EEXIST: raise privkeys = { 'enc': enc_privkey.to_bytes().hex(), 'sig': sig_privkey.to_bytes().hex(), } with open(os.path.join(path, 'private.json'), 'w+') as f: json.dump(privkeys, f) enc_pubkey = enc_privkey.get_pubkey() sig_pubkey = sig_privkey.get_pubkey() pubkeys = { 'enc': enc_pubkey.to_bytes().hex(), 'sig': sig_pubkey.to_bytes().hex() } with open(os.path.join(path, 'public.json'), 'w+') as f: json.dump(pubkeys, f) return privkeys, pubkeys
def act_as_bob(self, name): print("act_as_bob") dirname = "accounts/" + name + "/" fname = dirname+"recipent.private.json" with open(fname) as data_file: data = json.load(data_file) enc_privkey = UmbralPrivateKey.from_bytes(bytes.fromhex(data["enc"])) sig_privkey = UmbralPrivateKey.from_bytes(bytes.fromhex(data["sig"])) bob_enc_keypair = DecryptingKeypair(private_key=enc_privkey) bob_sig_keypair = SigningKeypair(private_key=sig_privkey) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] bob = Bob( is_me=True, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[self.ursula], save_metadata=False, network_middleware=RestMiddleware(), ) return bob
def test_simple_api(N, M, curve=default_curve()): """Manually injects umbralparameters for multi-curve testing.""" params = UmbralParameters(curve=curve) delegating_privkey = UmbralPrivateKey.gen_key(params=params) delegating_pubkey = delegating_privkey.get_pubkey() signing_privkey = UmbralPrivateKey.gen_key(params=params) signing_pubkey = signing_privkey.get_pubkey() signer = Signer(signing_privkey) receiving_privkey = UmbralPrivateKey.gen_key(params=params) receiving_pubkey = receiving_privkey.get_pubkey() plain_data = b'peace at dawn' ciphertext, capsule = pre.encrypt(delegating_pubkey, plain_data) cleartext = pre.decrypt(ciphertext, capsule, delegating_privkey) assert cleartext == plain_data capsule.set_correctness_keys(delegating=delegating_pubkey, receiving=receiving_pubkey, verifying=signing_pubkey) kfrags = pre.split_rekey(delegating_privkey, signer, receiving_pubkey, M, N) for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, capsule) capsule.attach_cfrag(cfrag) reenc_cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey) assert reenc_cleartext == plain_data
def test_private_key_serialization(random_ec_curvebn1): priv_key = random_ec_curvebn1 umbral_key = UmbralPrivateKey(priv_key, default_params()) encoded_key = umbral_key.to_bytes() decoded_key = UmbralPrivateKey.from_bytes(encoded_key) assert priv_key == decoded_key.bn_key
def test_public_key_serialization(random_ec_curvebn1): umbral_key = UmbralPrivateKey(random_ec_curvebn1, default_params()).get_pubkey() pub_point = umbral_key.point_key encoded_key = umbral_key.to_bytes() decoded_key = UmbralPublicKey.from_bytes(encoded_key) assert pub_point == decoded_key.point_key
def reveal_private_keys(self, username): private_keys = self.user_path + username + self.private_key_path with open(private_keys) as data_file: data = json.load(data_file) enc_privkey = UmbralPrivateKey.from_bytes(bytes.fromhex(data["enc"])) sig_privkey = UmbralPrivateKey.from_bytes(bytes.fromhex(data["sig"])) return enc_privkey, sig_privkey
def test_key_encoder_decoder(random_ec_curvebn1): priv_key = random_ec_curvebn1 umbral_key = UmbralPrivateKey(priv_key, default_params()) encoded_key = umbral_key.to_bytes(encoder=base64.urlsafe_b64encode) decoded_key = UmbralPrivateKey.from_bytes(encoded_key, decoder=base64.urlsafe_b64decode) assert decoded_key.to_bytes() == umbral_key.to_bytes()
def make_random_bob(): """Generates a random ephemeral Bob instance.""" bob_verifying_secret = UmbralPrivateKey.gen_key() bob_verifying_key = bob_verifying_secret.pubkey decrypting_secret = UmbralPrivateKey.gen_key() decrypting_key = decrypting_secret.pubkey bob = Bob.from_public_keys(verifying_key=bob_verifying_key, encrypting_key=decrypting_key, federated_only=False) return bob
def test_private_key_serialization_with_encryption(random_ec_curvebn1): priv_key = random_ec_curvebn1 umbral_key = UmbralPrivateKey(priv_key, default_params()) insecure_cost = 15 # This is deliberately insecure, just to make the tests faster encoded_key = umbral_key.to_bytes(password=b'test', _scrypt_cost=insecure_cost) decoded_key = UmbralPrivateKey.from_bytes(encoded_key, password=b'test', _scrypt_cost=insecure_cost) assert priv_key == decoded_key.bn_key
def create_policy(self, label: bytes, alice_privkey: UmbralPrivateKey, bob_pubkey: UmbralPublicKey, policy_expiration, m: int, n: int): """ Create a Policy with Alice granting Bob access to `label` DataSource :param label: A label to represent the policies data :param alice_privkey: Alice's private key :param bob_pubkey: Bob's public key :param policy_expiration: Datetime of policy expiration duration :param m: Minimum number of KFrags needed to rebuild ciphertext :param n: Total number of rekey shares to generate :return: The policy granted to Bob """ # This is not how this should be implemented, but I am still figuring out # the keying material and why it is randomly generated when a character is # initialized, instead of being derived from the keys like the other powers # or explained how it should be stored. d = DelegatingPower() d.umbral_keying_material = UmbralKeyingMaterial.from_bytes( alice_privkey.to_bytes() + alice_privkey.get_pubkey().to_bytes()) # Initialize Alice ALICE = Alice( crypto_power_ups=[ SigningPower(keypair=SigningKeypair(alice_privkey)), EncryptingPower(keypair=EncryptingKeypair(alice_privkey)), # DelegatingPower d ], network_middleware=RestMiddleware(), known_nodes=(self.ursula, ), federated_only=True, always_be_learning=True) # Initialize Bob BOB = Bob(crypto_power_ups=[ SigningPower(pubkey=bob_pubkey), EncryptingPower(pubkey=bob_pubkey) ], known_nodes=(self.ursula, ), federated_only=True, always_be_learning=True) # Alice grants a policy for Bob policy = ALICE.grant(BOB, label, m=m, n=n, expiration=policy_expiration) return policy
def test_create_bob_card_inline(click_runner, alice_verifying_key, alice_nickname): command = ('contacts', 'create', '--type', 'b', '--verifying-key', UmbralPrivateKey.gen_key().get_pubkey().hex(), '--encrypting-key', UmbralPrivateKey.gen_key().get_pubkey().hex(), '--nickname', 'hans') assert len(os.listdir(Card.CARD_DIR)) == 3 result = click_runner.invoke(nucypher_cli, command, catch_exceptions=False) assert result.exit_code == 0, result.output assert 'Saved new card' in result.output assert len(os.listdir(Card.CARD_DIR)) == 4
def create_new_user(self, name, password): print("create_new_user") passphrase = password direco = "accounts/"+ name # alice_config = AliceConfiguration( # config_root=os.path.join(direco), # is_me=True, known_nodes={self.ursula}, start_learning_now=True, # federated_only=True, learn_on_same_thread=True, # ) # alice_config.initialize(password=passphrase) # alice_config.keyring.unlock(password=passphrase) # alice_config_file = alice_config.to_configuration_file() alice_config = AliceConfiguration( config_root=os.path.join(direco), # is_me=True, known_nodes={self.ursula}, start_learning_now=False, federated_only=True, learn_on_same_thread=True, ) alice_config.initialize(password=passphrase) alice_config.keyring.unlock(password=passphrase) # print(dir(alice_config.keyring)) alice = alice_config.produce() alice_config_file = alice_config.to_configuration_file() alice.start_learning_loop(now=True) enc_privkey = UmbralPrivateKey.gen_key() sig_privkey = UmbralPrivateKey.gen_key() doctor_privkeys = { 'enc': enc_privkey.to_bytes().hex(), 'sig': sig_privkey.to_bytes().hex(), } DOCTOR_PUBLIC_JSON = direco + '/recipent.public.json' DOCTOR_PRIVATE_JSON = direco + '/recipent.private.json' with open(DOCTOR_PRIVATE_JSON, 'w') as f: json.dump(doctor_privkeys, f) enc_pubkey = enc_privkey.get_pubkey() sig_pubkey = sig_privkey.get_pubkey() doctor_pubkeys = { 'enc': enc_pubkey.to_bytes().hex(), 'sig': sig_pubkey.to_bytes().hex() } with open(DOCTOR_PUBLIC_JSON, 'w') as f: json.dump(doctor_pubkeys, f) # print(dir(alice)) return alice
def get_instance(self): if not self._unique_instance: set_default_curve() self.bb = BulletinBoard.get_instance() self.proxy = Proxy.get_instance() self.private_key = UmbralPrivateKey.gen_key() self.public_key = self.private_key.get_pubkey() self.singning_key = UmbralPrivateKey.gen_key() self.verifying_key = self.singning_key.get_pubkey() self.signer = Signer(private_key=self.singning_key) self.voters = [] self._unique_instance = self.__internal_new__() return self._unique_instance
def _generate_signing_keys() -> Tuple[UmbralPrivateKey, UmbralPublicKey]: """ TODO: Do we really want to use Umbral keys for signing? Perhaps we can use Curve25519/EdDSA for signatures? """ privkey = UmbralPrivateKey.gen_key() pubkey = privkey.get_pubkey() return privkey, pubkey
def __init__(self, pubkey: UmbralPublicKey = None, keypair: keypairs.Keypair = None, generate_keys_if_needed=True) -> None: if keypair and pubkey: raise ValueError( "Pass keypair or pubkey_bytes (or neither), but not both.") elif keypair: self.keypair = keypair else: # They didn't pass a keypair; we'll make one with the bytes or # UmbralPublicKey if they provided such a thing. if pubkey: try: key_to_pass_to_keypair = pubkey.as_umbral_pubkey() except AttributeError: try: key_to_pass_to_keypair = UmbralPublicKey.from_bytes( pubkey) except TypeError: key_to_pass_to_keypair = pubkey else: # They didn't even pass pubkey_bytes. We'll generate a keypair. key_to_pass_to_keypair = UmbralPrivateKey.gen_key() self.keypair = self._keypair_class( umbral_key=key_to_pass_to_keypair)
def _encrypt_credential_and_voter_short_private_key( self, credential: Tuple[UmbralPublicKey, Signer], private_key: UmbralPrivateKey) -> Dict[str, Tuple[bytes, Capsule]]: """encrypt credential and voter short private key Arguments: credential {Tuple[UmbralPublicKey, Signer]} private_key {UmbralPrivateKey} Returns: Dict[str, Tuple[bytes, Capsule]] -- need to save Capsule """ credential_bytes = credential[0].to_bytes() + bytes(credential[1]) private_key_bytes = private_key.to_bytes() (enc_credential, c_capsule) = encrypt(self.public_key, credential_bytes) (enc_private_key, p_capsule) = encrypt(self.public_key, private_key_bytes) voter_public_key = credential[0] for capsule in (c_capsule, p_capsule): capsule.set_correctness_keys(delegating=self.public_key, receiving=voter_public_key, verifying=self.verifying_key) return { "credential": (enc_credential, c_capsule), "private_key": (enc_private_key, p_capsule) }
def create_policy(): """ input: { "label": "",- "alice_privkey": "", "bob_pubkey": "", "policy_expiration": "", "m": "", "n": "" } response: { "success": "", "policy_pubkey": "", "policy_expiration_date": "", "err_msg": "" } """ result = { 'success': False, 'policy_pubkey': None, 'policy_expiration_date': None, 'err_msg': None } try: j = json.loads(request.data.decode('utf-8')) # TODO: Check if the input is valid # Parse the input values label = j['label'].encode('utf-8') alice_privkey = UmbralPrivateKey.from_bytes( j['alice_privkey'], decoder=base64.urlsafe_b64decode) bob_pubkey = UmbralPublicKey.from_bytes( j['bob_pubkey'], decoder=base64.urlsafe_b64decode) policy_expiration = maya.now() + datetime.timedelta( days=int(j['policy_expiration'])) m = int(j['m']) n = int(j['n']) # Create the policy policy = api.create_policy(label, alice_privkey, bob_pubkey, policy_expiration, m, n) # Format the response result['policy_pubkey'] = base64.urlsafe_b64encode( policy.public_key.to_bytes()).decode('utf8') result['policy_expiration_date'] = str(policy_expiration) result['success'] = True except Exception as e: result['success'] = False result['err_msg'] = str(e) # Create response response = jsonify(result) return response
def test_signature_can_verify(): privkey = UmbralPrivateKey.gen_key() message = b"peace at dawn" der_sig_bytes = ecdsa_sign(message, privkey) assert verify_ecdsa(message, der_sig_bytes, privkey.get_pubkey()) signature = Signature.from_bytes(der_sig_bytes, der_encoded=True) assert signature.verify(message, privkey.get_pubkey())
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
def _open_capsule(capsule: Capsule, receiving_privkey: UmbralPrivateKey, check_proof: bool = True) -> bytes: """ Activates the Capsule from the attached CFrags, opens the Capsule and returns what is inside. This will often be a symmetric key. """ receiving_pubkey = receiving_privkey.get_pubkey() if check_proof: offending_cfrags = [] for cfrag in capsule._attached_cfrags: if not cfrag.verify_correctness(capsule): offending_cfrags.append(cfrag) if offending_cfrags: error_msg = "Decryption error: Some CFrags are not correct" raise UmbralCorrectnessError(error_msg, offending_cfrags) capsule._reconstruct_shamirs_secret(receiving_privkey) key = _decapsulate_reencrypted(receiving_privkey, capsule) return key
def __decrypt_keyfile(self, key_path: str) -> UmbralPrivateKey: """Returns plaintext version of decrypting key.""" key_data = _read_keyfile(key_path, deserializer=self._private_key_serializer) wrap_key = _derive_wrapping_key_from_key_material(salt=key_data['wrap_salt'], key_material=self.__derived_key_material) plain_umbral_key = UmbralPrivateKey.from_bytes(key_bytes=key_data['key'], wrapping_key=wrap_key) return plain_umbral_key
def _open_capsule(capsule: Capsule, bob_privkey: UmbralPrivateKey, alice_pubkey: UmbralPublicKey, params: UmbralParameters=None, check_proof=True) -> bytes: """ Activates the Capsule from the attached CFrags, opens the Capsule and returns what is inside. This will often be a symmetric key. """ params = params if params is not None else default_params() priv_b = bob_privkey.bn_key pub_b = bob_privkey.get_pubkey().point_key pub_a = alice_pubkey.point_key # TODO: Change dict for a list if issue #116 goes through if check_proof: offending_cfrags = [] for cfrag in capsule._attached_cfrags: if not _verify_correctness(capsule, cfrag, pub_a, pub_b, params): offending_cfrags.append(cfrag) if offending_cfrags: error_msg = "Decryption error: Some CFrags are not correct" raise UmbralCorrectnessError(error_msg, offending_cfrags) capsule._reconstruct_shamirs_secret(pub_a, priv_b, params=params) key = _decapsulate_reencrypted(pub_b, priv_b, pub_a, capsule, params=params) return key
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
def test_recover_pubkey_from_signature(execution_number): privkey = UmbralPrivateKey.gen_key() pubkey = privkey.get_pubkey() signer = Signer(private_key=privkey) message = b"peace at dawn" signature = signer(message=message) assert signature.verify(message, pubkey) hash_function = hashes.Hash(hashes.SHA256(), backend=backend) hash_function.update(message) prehashed_message = hash_function.finalize() v_value = 27 pubkey_bytes = recover_pubkey_from_signature( prehashed_message=prehashed_message, signature=signature, v_value_to_try=v_value) if not pubkey_bytes == pubkey.to_bytes(): v_value = 28 pubkey_bytes = recover_pubkey_from_signature( prehashed_message=prehashed_message, signature=signature, v_value_to_try=v_value) assert pubkey_bytes == pubkey.to_bytes()
def test_gen_key(): # Pass in the parameters to test that manual param selection works umbral_priv_key = UmbralPrivateKey.gen_key() assert type(umbral_priv_key) == UmbralPrivateKey umbral_pub_key = umbral_priv_key.get_pubkey() assert type(umbral_pub_key) == UmbralPublicKey