Beispiel #1
0
    def test_serialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = Ed25519Sha256(public_key=vk_ilp['b58'])

        assert fulfillment.to_dict() == \
            {'bitmask': 32,
             'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
             'signature': None,
             'type': 'fulfillment',
             'type_id': 4}
        assert fulfillment.validate(MESSAGE) == False
def make_ed25519_condition(public_key, *, amount=1):
    ed25519 = Ed25519Sha256(public_key=base58.b58decode(public_key))
    return {
        'amount': str(amount),
        'condition': {
            'details': _fulfillment_to_details(ed25519),
            'uri': ed25519.condition_uri,
        },
        'public_keys': (public_key, ),
    }
Beispiel #3
0
def sign_transaction(transaction, *, public_key, private_key):
    ed25519 = Ed25519Sha256(public_key=base58.b58decode(public_key))
    message = json.dumps(
        transaction,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    )
    ed25519.sign(message.encode(), base58.b58decode(private_key))
    return ed25519.serialize_uri()
Beispiel #4
0
def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv,
                                             asset_definition):
    from cryptoconditions import Ed25519Sha256, ThresholdSha256
    from bigchaindb.common.transaction import Input, Output, Transaction

    threshold = ThresholdSha256(threshold=2)
    threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))
    threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))

    threshold_input = Input(threshold, [user_pub, user_pub])
    threshold_output = Output(threshold, [user_pub, user_pub])

    tx = Transaction(Transaction.CREATE, asset_definition, [threshold_input],
                     [threshold_output])

    tx_dict = tx.to_dict()
    tx_dict['inputs'][0]['fulfillment'] = None
    serialized_tx = json.dumps(tx_dict,
                               sort_keys=True,
                               separators=(',', ':'),
                               ensure_ascii=True)
    message = sha3_256(serialized_tx.encode()).digest()

    expected = deepcopy(threshold_input)
    expected.fulfillment.subconditions[0]['body'].sign(message,
                                                       b58decode(user_priv))
    expected.fulfillment.subconditions[1]['body'].sign(message,
                                                       b58decode(user_priv))

    tx.sign([user_priv, user_priv])

    subconditions = tx.inputs[0].fulfillment.subconditions
    expected_subconditions = expected.fulfillment.subconditions
    assert subconditions[0]['body'].to_dict()['signature'] == \
        expected_subconditions[0]['body'].to_dict()['signature']
    assert subconditions[1]['body'].to_dict()['signature'] == \
        expected_subconditions[1]['body'].to_dict()['signature']

    assert tx.inputs[0].to_dict()['fulfillment'] == \
        expected.fulfillment.serialize_uri()
    assert tx.inputs_valid() is True
Beispiel #5
0
def sign_ed25519(transaction, private_keys):
    from cryptoconditions import Ed25519Sha256
    from cryptoconditions.crypto import Ed25519VerifyingKey

    for index, _input in enumerate(transaction.inputs):
        receiver = _input.owners_before[0]
        transaction.inputs[index].fulfillment = Ed25519Sha256(
            public_key=Ed25519VerifyingKey(receiver).encode('bytes'))

    private_keys = [private_keys
                    ] if not isinstance(private_keys, list) else private_keys
    return transaction.sign(private_keys).to_dict()
    def test_non_create_input_not_found(self, b, user_pk):
        from cryptoconditions import Ed25519Sha256
        from bigchaindb.common.exceptions import InputDoesNotExist
        from bigchaindb.common.transaction import Input, TransactionLink
        from bigchaindb.models import Transaction

        # Create an input for a non existing transaction
        input = Input(Ed25519Sha256(public_key=b58decode(user_pk)), [user_pk],
                      TransactionLink('somethingsomething', 0))
        tx = Transaction.transfer([input], [([user_pk], 1)],
                                  asset_id='mock_asset_link')
        with pytest.raises(InputDoesNotExist):
            tx.validate(b)
Beispiel #7
0
def generate_service(service_key,
                     owner_keys,
                     auth_keys=[],
                     owners_authorize=True):
    """
    create a an unsigned service msg
    Args:
        service_keys ([str])- service denoted by base58 encoded keys
        owner_keys ([str]) - public keys recognizing ownership of the services and therefore administrators
        auth_keys ([str])- those who can give access to a resource. Generally owners must also be authorizers

        returns:
            a message without any signature or identity resolution
    """
    message = MessageShell.messageForType(MSGTYPE.REGISTER)
    message['data']['service'] = service_key
    message['data']['owners'] = owner_keys
    if owners_authorize:
        message['data']['authorities'] = owner_keys + auth_keys
    else:
        message['data']['authorities'] = auth_keys

    condition = None

    if len(owner_keys) != 1:
        condition = ThresholdSha256(threshold=len(owner_keys))
        for key in owner_keys:
            condition.add_subfulfillment(
                Ed25519Sha256(public_key=base58.b58decode(key)))
    else:
        condition = Ed25519Sha256(public_key=base58.b58decode(owner_keys[0]))

    message['data']['condition'] = condition.to_dict()
    message['data']['condition_uri'] = condition.condition_uri
    message['data']['fulfillment'] = None
    message['id'] = None

    return message
 def test_fulfill(self, driver, alice_keypair, unsigned_transaction):
     signed_transaction = driver.transactions.fulfill(
         unsigned_transaction, private_keys=alice_keypair.sk)
     unsigned_transaction['inputs'][0]['fulfillment'] = None
     message = json.dumps(
         unsigned_transaction,
         sort_keys=True,
         separators=(',', ':'),
         ensure_ascii=False,
     )
     message = sha3_256(message.encode())
     ed25519 = Ed25519Sha256(public_key=base58.b58decode(alice_keypair.vk))
     ed25519.sign(message.digest(), base58.b58decode(alice_keypair.sk))
     fulfillment_uri = ed25519.serialize_uri()
     assert signed_transaction['inputs'][0]['fulfillment'] == fulfillment_uri   # noqa
Beispiel #9
0
    def test_serialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = ThresholdSha256(threshold=1)
        fulfillment.add_subfulfillment(
            Ed25519Sha256(public_key=VerifyingKey(vk_ilp['b58'])))
        fulfillment.add_subfulfillment(
            Ed25519Sha256(public_key=VerifyingKey(vk_ilp['b58'])))

        assert fulfillment.to_dict() == \
            {'bitmask': 41,
             'subfulfillments': [{'bitmask': 32,
                                  'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
                                  'signature': None,
                                  'type': 'fulfillment',
                                  'type_id': 4,
                                  'weight': 1},
                                 {'bitmask': 32,
                                  'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
                                  'signature': None,
                                  'type': 'fulfillment',
                                  'type_id': 4,
                                  'weight': 1}],
             'threshold': 1,
             'type': 'fulfillment',
             'type_id': 2}
Beispiel #10
0
    def generate(cls, public_keys, amount):
        """Generates a Output from a specifically formed tuple or list.

            Note:
                If a ThresholdCondition has to be generated where the threshold
                is always the number of subconditions it is split between, a
                list of the following structure is sufficient:

                [(address|condition)*, [(address|condition)*, ...], ...]

            Args:
                public_keys (:obj:`list` of :obj:`str`): The public key of
                    the users that should be able to fulfill the Condition
                    that is being created.
                amount (:obj:`int`): The amount locked by the Output.

            Returns:
                An Output that can be used in a Transaction.

            Raises:
                TypeError: If `public_keys` is not an instance of `list`.
                ValueError: If `public_keys` is an empty list.
        """
        threshold = len(public_keys)
        if not isinstance(amount, int):
            raise TypeError('`amount` must be a int')
        if amount < 1:
            raise AmountError('`amount` needs to be greater than zero')
        if not isinstance(public_keys, list):
            raise TypeError('`public_keys` must be an instance of list')
        if len(public_keys) == 0:
            raise ValueError('`public_keys` needs to contain at least one'
                             'owner')
        elif len(public_keys) == 1 and not isinstance(public_keys[0], list):
            if isinstance(public_keys[0], Fulfillment):
                ffill = public_keys[0]
            else:
                ffill = Ed25519Sha256(
                    public_key=base58.b58decode(public_keys[0]))
            return cls(ffill, public_keys, amount=amount)
        else:
            initial_cond = ThresholdSha256(threshold=threshold)
            threshold_cond = reduce(cls._gen_condition, public_keys,
                                    initial_cond)
            return cls(threshold_cond, public_keys, amount=amount)
Beispiel #11
0
    def _gen_condition(cls, initial, new_public_keys):
        """Generates ThresholdSha256 conditions from a list of new owners.

            Note:
                This method is intended only to be used with a reduce function.
                For a description on how to use this method, see
                :meth:`~.Output.generate`.

            Args:
                initial (:class:`cryptoconditions.ThresholdSha256`):
                    A Condition representing the overall root.
                new_public_keys (:obj:`list` of :obj:`str`|str): A list of new
                    owners or a single new owner.

            Returns:
                :class:`cryptoconditions.ThresholdSha256`:
        """
        try:
            threshold = len(new_public_keys)
        except TypeError:
            threshold = None

        if isinstance(new_public_keys, list) and len(new_public_keys) > 1:
            ffill = ThresholdSha256(threshold=threshold)
            reduce(cls._gen_condition, new_public_keys, ffill)
        elif isinstance(new_public_keys, list) and len(new_public_keys) <= 1:
            raise ValueError('Sublist cannot contain single owner')
        else:
            try:
                new_public_keys = new_public_keys.pop()
            except AttributeError:
                pass
            # NOTE: Instead of submitting base58 encoded addresses, a user
            #       of this class can also submit fully instantiated
            #       Cryptoconditions. In the case of casting
            #       `new_public_keys` to a Ed25519Fulfillment with the
            #       result of a `TypeError`, we're assuming that
            #       `new_public_keys` is a Cryptocondition then.
            if isinstance(new_public_keys, Fulfillment):
                ffill = new_public_keys
            else:
                ffill = Ed25519Sha256(
                    public_key=base58.b58decode(new_public_keys))
        initial.add_subfulfillment(ffill)
        return initial
Beispiel #12
0
def prepare_transfer_ed25519_simple(transaction, receiver, metadata=None):
    from cryptoconditions import Ed25519Sha256
    from cryptoconditions.crypto import Ed25519VerifyingKey

    return prepare_transfer(
        inputs=[{
            'tx': transaction,
            'output': 0
        }],
        outputs=[{
            'condition':
            Ed25519Sha256(
                public_key=Ed25519VerifyingKey(receiver).encode('bytes')),
            'public_keys': [receiver],
            'amount':
            1
        }],
        metadata=metadata)
Beispiel #13
0
def test_validate_inputs_of_transfer_tx_with_invalid_params(
        transfer_tx, cond_uri, utx, user2_pub, user_priv, ffill_uri):
    from bigchaindb.common.transaction import Output
    from cryptoconditions import Ed25519Sha256

    invalid_out = Output(Ed25519Sha256.from_uri(ffill_uri), ['invalid'])
    assert transfer_tx.inputs_valid([invalid_out]) is False
    invalid_out = utx.outputs[0]
    invalid_out.public_key = 'invalid'
    assert transfer_tx.inputs_valid([invalid_out]) is True

    with raises(TypeError):
        assert transfer_tx.inputs_valid(None) is False
    with raises(AttributeError):
        transfer_tx.inputs_valid('not a list')
    with raises(ValueError):
        transfer_tx.inputs_valid([])
    with raises(TypeError):
        transfer_tx.operation = "Operation that doesn't exist"
        transfer_tx.inputs_valid([utx.outputs[0]])
Beispiel #14
0
def _fulfillment_from_details(data, _depth=0):
    """Load a fulfillment for a signing spec dictionary

    Args:
        data: tx.output[].condition.details dictionary
    """
    if _depth == 100:
        raise ThresholdTooDeep()

    if data['type'] == 'ed25519-sha-256':
        public_key = base58.b58decode(data['public_key'])
        return Ed25519Sha256(public_key=public_key)

    if data['type'] == 'threshold-sha-256':
        threshold = ThresholdSha256(data['threshold'])
        for cond in data['subconditions']:
            cond = _fulfillment_from_details(cond, _depth+1)
            threshold.add_subfulfillment(cond)
        return threshold

    raise UnsupportedTypeError(data.get('type'))
Beispiel #15
0
def test_post_create_transaction_with_invalid_schema(mock_logger, client):
    from bigchaindb.models import Transaction
    user_priv, user_pub = crypto.generate_key_pair()
    tx = Transaction.create([user_pub], [([user_pub], 1)]).to_dict()
    del tx['version']
    ed25519 = Ed25519Sha256(public_key=base58.b58decode(user_pub))
    message = json.dumps(
        tx,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    ).encode()
    ed25519.sign(message, base58.b58decode(user_priv))
    tx['inputs'][0]['fulfillment'] = ed25519.serialize_uri()
    tx['id'] = sha3_256(
        json.dumps(
            tx,
            sort_keys=True,
            separators=(',', ':'),
            ensure_ascii=False,
        ).encode(),
    ).hexdigest()
    res = client.post(TX_ENDPOINT, data=json.dumps(tx))
    expected_status_code = 400
    expected_error_message = (
        "Invalid transaction schema: 'version' is a required property")
    assert res.status_code == expected_status_code
    assert res.json['message'] == expected_error_message
    assert mock_logger.error.called
    assert (
        'HTTP API error: %(status)s - %(method)s:%(path)s - %(message)s' in
        mock_logger.error.call_args[0]
    )
    assert (
        {
            'message': expected_error_message, 'status': expected_status_code,
            'method': 'POST', 'path': TX_ENDPOINT
        } in mock_logger.error.call_args[0]
    )
Beispiel #16
0
    def test_fulfillment_didnt_reach_threshold(self, vk_ilp,
                                               fulfillment_ed25519):
        ilp_fulfillment = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])
        threshold = 10

        # Create a threshold condition
        fulfillment = ThresholdSha256(threshold=threshold)

        for i in range(threshold - 1):
            fulfillment.add_subfulfillment(ilp_fulfillment)

        with pytest.raises(KeyError):
            fulfillment.serialize_uri()

        assert fulfillment.validate(MESSAGE) is False

        fulfillment.add_subfulfillment(ilp_fulfillment)

        fulfillment_uri = fulfillment.serialize_uri()
        assert fulfillment.validate(MESSAGE)

        deserialized_fulfillment = Fulfillment.from_uri(fulfillment_uri)

        assert isinstance(deserialized_fulfillment, ThresholdSha256)
        assert deserialized_fulfillment.threshold == threshold
        assert len([
            f for f in deserialized_fulfillment.subconditions
            if f['type'] == 'fulfillment'
        ]) == threshold
        assert len(deserialized_fulfillment.subconditions) == threshold
        assert deserialized_fulfillment.serialize_uri() == fulfillment_uri
        assert deserialized_fulfillment.validate(MESSAGE)

        fulfillment.add_subfulfillment(
            Ed25519Sha256(public_key=VerifyingKey(vk_ilp['b58'])))

        assert fulfillment.validate(MESSAGE) == True
Beispiel #17
0
operation = 'CREATE'

version = '2.0'

asset = {
    'data': {
        'bicycle': {
            'manufacturer': 'bkfab',
            'serial_number': 'abcd1234',
        },
    },
}

metadata = {'planet': 'earth'}

ed25519 = Ed25519Sha256(public_key=base58.b58decode(alice.public_key))

output = {
    'amount': '1',
    'condition': {
        'details': {
            'type': ed25519.TYPE_NAME,
            'public_key': base58.b58encode(ed25519.public_key).decode(),
        },
        'uri': ed25519.condition_uri,
    },
    'public_keys': (alice.public_key, ),
}
outputs = (output, )

input_ = {
metadata = {'Units': 2400, 'Type': 'g'}

# IPDB transaction schema version
version = '2.0'

# Policies written in Zencode - see https://github.com/DECODEproject/Zenroom
# To apply it it has to be given as a parameter in line 95.
script = """Scenario 'coconut': "To run over the mobile wallet the first time and store the output as keypair.keys"
Given that I am known as 'identifier'
When I create my new keypair
Then print all data
"""

# CRYPTO-CONDITIONS: instantiate an Ed25519 crypto-condition for buyer
ed25519 = Ed25519Sha256(public_key=base58.b58decode(producer.public_key))

# CRYPTO-CONDITIONS: generate the condition uri
condition_uri = ed25519.condition.serialize_uri()

# CRYPTO-CONDITIONS: construct an unsigned fulfillment dictionary
unsigned_fulfillment_dict = {
    'type': ed25519.TYPE_NAME,
    'public_key': base58.b58encode(ed25519.public_key).decode(),
}

output = {
    'amount': '2400',
    'condition': {
        'details': unsigned_fulfillment_dict,
        'uri': condition_uri,
Beispiel #19
0
def user2_Ed25519(user2_pub):
    from cryptoconditions import Ed25519Sha256
    return Ed25519Sha256(public_key=b58decode(user2_pub))
Beispiel #20
0
def test_permission_add_role(b):
    from .utils import create_simple_tx, post_tx, transfer_simple_tx, prepare_transfer, get_message_to_sign
    from bigchaindb.models import Transaction
    from cryptoconditions import ThresholdSha256, Ed25519Sha256, PreimageSha256
    from cryptoconditions.crypto import Ed25519VerifyingKey, Ed25519SigningKey

    # admin, albi, bruce
    admin_priv, admin_pub = crypto.generate_key_pair()
    albi_priv, albi_pub = crypto.generate_key_pair()
    bruce_priv, bruce_pub = crypto.generate_key_pair()

    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 0
    assert len(b.get_owned_ids(bruce_pub)) == 0

    # admin CREATES role: tx_create_role, 202
    tx_create_role = Transaction.create(
        [admin_pub], [([admin_pub], 1)],
        asset={
            "policy": [
                {
                    "condition":
                    "transaction.operation == 'TRANSFER'",
                    "rule":
                    "transaction.inputs[0].owners_before[0] == '{}'".format(
                        admin_pub)
                },
            ]
        })
    # trick to not include in balance part 1
    tx_create_role.outputs[0].public_keys = []
    tx_create_role = tx_create_role.sign([admin_priv])
    response = post_tx(b, None, tx_create_role)
    tx_create_role_retrieved = b.get_transaction(tx_create_role.id)

    assert response.status_code == 202
    assert tx_create_role_retrieved.id == tx_create_role.id

    #  admin.unspents = [] # admin doesnt have role, only created it
    #  user_a.unspents = [] # user_a has no role
    #  user_b.unspents = [] # user_b has no role

    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 0
    assert len(b.get_owned_ids(bruce_pub)) == 0

    # admin TRANSFERS tx_create_role TO user_a: tx_transfer_role_a, 202

    # tx_transfer_role_a = Transaction.transfer(
    #     [
    #         Input(
    #             fulfillment=Ed25519Sha256(
    #                 public_key=b58decode(admin_pub)),
    #             owners_before=[admin_pub], # trick to not include in balance part 2
    #             fulfills=TransactionLink(
    #                 txid=tx_create_role.id,
    #                 output=0)
    #             )
    #     ],
    #     [([albi_pub], 1)],
    #     tx_create_role.id)
    # tx_transfer_role_a = tx_transfer_role_a.sign([admin_priv])

    output_condition = ThresholdSha256(threshold=1)
    output_condition.add_subfulfillment(
        Ed25519Sha256(public_key=b58decode(admin_pub)))

    output_condition.add_subfulfillment(
        Ed25519Sha256(public_key=b58decode(albi_pub)))

    tx_transfer_role_a = prepare_transfer(inputs=[{
        'tx':
        tx_create_role.to_dict(),
        'output':
        0
    }],
                                          outputs=[
                                              {
                                                  'condition':
                                                  output_condition,
                                                  'public_keys': [albi_pub]
                                              },
                                          ])

    input_fulfillment = Ed25519Sha256(public_key=b58decode(admin_pub))
    tx_transfer_role_a.inputs[0].owners_before = [admin_pub]
    message_to_sign = get_message_to_sign(tx_transfer_role_a)
    input_fulfillment.sign(message_to_sign, b58decode(admin_priv))
    tx_transfer_role_a.inputs[0].fulfillment = input_fulfillment

    tx_transfer_role_a.validate(b)

    response = post_tx(b, None, tx_transfer_role_a)
    # tx_create_role_retrieved = b.get_transaction(tx_create_role.id)

    assert response.status_code == 202

    #  user_a.unspents = [tx_transfer_role_a] # user_a has role
    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 1
    assert len(b.get_owned_ids(bruce_pub)) == 0

    # user TRANSFERS tx_transfer_role_a TO user_b: -, 400 # only admin can assign role
    tx_transfer_role_b = prepare_transfer(
        inputs=[{
            'tx': tx_transfer_role_a.to_dict(),
            'output': 0
        }],
        outputs=[
            {
                'condition': Ed25519Sha256(public_key=b58decode(bruce_pub)),
            },
        ])

    tx_transfer_role_b.inputs[0].owners_before = [albi_pub]

    message_to_sign = get_message_to_sign(tx_transfer_role_b)
    input_fulfillment = ThresholdSha256(threshold=1)
    albi_fulfillment = Ed25519Sha256(public_key=b58decode(albi_pub))
    albi_fulfillment.sign(message_to_sign, b58decode(albi_priv))

    input_fulfillment.add_subfulfillment(albi_fulfillment)
    input_fulfillment.add_subcondition(
        Ed25519Sha256(public_key=b58decode(admin_pub)).condition_uri)
    tx_transfer_role_b.inputs[0].fulfillment = input_fulfillment
    input_fulfillment.serialize_uri()
    tx_transfer_role_b.validate(b)

    response = post_tx(b, None, tx_transfer_role_b)

    assert response.status_code == 202

    #  user_a.unspents = [tx_transfer_role_a] # user_a has role
    #  user_b.unspents = [] # user_b has no role
    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 0
    assert len(b.get_owned_ids(bruce_pub)) == 0