コード例 #1
0
ファイル: tests.py プロジェクト: GroupBank/global-server
    def test_new_user_to_existing_group(self):
        user_priv, user_pub = example_keys.C1_priv, example_keys.C1_pub
        group_priv, group_pub = example_keys.G1_priv, example_keys.G1_pub

        payload = json.dumps({
            'user_key': user_pub,
            'group_uuid': str(self.group.uuid)
        })
        signature = crypto.sign(group_priv, payload)

        response = self.client.post(reverse('rest:group:register-user'), {
            'author': group_pub,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 201
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['group_uuid'] == str(self.group.uuid)
        assert payload['user'] == user_pub
コード例 #2
0
ファイル: decorators.py プロジェクト: GroupBank/global-server
    def wrapper(request):
        # https://docs.djangoproject.com/en/1.11/topics/http/middleware/#process-view
        # verify the JSON B64 string. return None if it's fine,
        # return an HTTPResponse with an error if not

        try:
            author, signature, payload = request.POST['author'], request.POST[
                'signature'], request.POST['payload']
        except KeyError:
            logger.info('Request with missing author, signature or payload')
            return HttpResponseBadRequest()

        # get user pubkey
        # what if the author CAN'T already be registered? i.e.: group key
        # maybe check view_func and ignore a few?
        # or let the view itself verify if the author is registered...

        # NOTE: This does not verify if the signer is authorized for the operation.
        #       It only verifies if the signature matches the given pub key

        try:
            crypto.verify(author, signature, payload)
            return view(request)
        except (crypto.InvalidSignature, crypto.InvalidKey):
            logger.info('Request with invalid author key or signature')
            return HttpResponseForbidden()
コード例 #3
0
    def test_get_totals_one_confirmed_uome(self):
        uome = UserDebt.objects.create(group=self.group,
                                       lender=self.user2,
                                       borrower=self.user1,
                                       value=1000)

        self.user2.balance = +uome.value
        self.user2.save()
        self.user1.balance = -uome.value
        self.user1.save()

        response = self.client.post(
            reverse('rest:uome:get-totals'), {
                'author': self.key,
                'signature': self.signature,
                'payload': self.payload
            })

        assert response.status_code == 200
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['user_balance'] == -uome.value
        assert payload['suggested_transactions'] == {
            self.user2.key: uome.value
        }
コード例 #4
0
    def test_SigningSomeTextWithKey1AndVerifyingWithPubkey1_DoesNotRaiseInvalidSignature(
            self):
        plain_text = "some text"
        key, pubkey = ec_secp256k1.generate_keys()

        valid_signature = ec_secp256k1.sign(key, plain_text)
        ec_secp256k1.verify(pubkey, valid_signature, plain_text)
コード例 #5
0
    def test_SigningSomeTextWithKey1AndVerifyingWithPubkey1_RaisesInvalidSignature(
            self):
        plain_text = "some text"
        key_1, pubkey_1 = ec_secp256k1.generate_keys()
        key_2, pubkey_2 = ec_secp256k1.generate_keys()

        with raises(ec_secp256k1.InvalidSignature):
            valid_signature = ec_secp256k1.sign(key_1, plain_text)
            ec_secp256k1.verify(pubkey_2, valid_signature, plain_text)
コード例 #6
0
    def test_cancel_unconfirmed_uome(self):
        uome = UOMe.objects.create(group=self.group,
                                   lender=self.user,
                                   borrower=self.borrower,
                                   value=10,
                                   description='test')

        issuer_payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'issuer': self.user.key,
            'borrower': self.borrower.key,
            'value': 10,
            'description': 'test',
            'uome_uuid': str(uome.uuid),
        })

        issuer_signature = crypto.sign(self.private_key, issuer_payload)

        uome.issuer_signature = issuer_signature
        uome.save()

        payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'user': self.user.key,
            'uome_uuid': str(uome.uuid),
        })
        signature = crypto.sign(self.private_key, payload)

        response = self.client.post(reverse('rest:uome:cancel'), {
            'author': self.user.key,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 200
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['group_uuid'] == str(self.group.uuid)
        assert payload['user'] == self.user.key
        assert payload['uome_uuid'] == str(uome.uuid)

        assert UOMe.objects.filter(uuid=uome.uuid).first() is None
コード例 #7
0
    def test_get_totals_no_uome(self):
        response = self.client.post(
            reverse('rest:uome:get-totals'), {
                'author': self.key,
                'signature': self.signature,
                'payload': self.payload
            })

        assert response.status_code == 200
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['user_balance'] == 0
        assert payload['suggested_transactions'] == {}
コード例 #8
0
ファイル: tests.py プロジェクト: GroupBank/global-server
    def test_invalid_message(self):
        group_name = 'test_name'
        priv_key, pub_key = example_keys.G1_priv, example_keys.G1_pub

        payload = json.dumps({'group_name':
                              group_name})  # missing 'group_key' field
        signature = crypto.sign(priv_key, payload)

        response = self.client.post(reverse('rest:group:register'), {
            'author': pub_key,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 400
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())
コード例 #9
0
    def test_add_first_uome(self):

        auth_payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'user': self.user.key
        })

        auth_signature = crypto.sign(self.private_key, auth_payload)

        payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'user': self.user.key,
            'borrower': self.borrower.key,
            'value': 1000,
            'description': 'my description',
            'user_signature': auth_signature
        })

        # todo: recheck if this is a security issue (might count as accepting the uome)
        signature = crypto.sign(self.private_key, payload)

        response = self.client.post(reverse('rest:uome:issue'), {
            'author': self.user.key,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 201
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['group_uuid'] == str(self.group.uuid)
        assert payload['user'] == self.user.key
        assert payload['borrower'] == self.borrower.key
        assert payload['value'] == 1000
        assert payload['description'] == 'my description'

        uome = UOMe.objects.get(pk=payload['uome_uuid'])
        assert uome.issuer_signature == ''
コード例 #10
0
ファイル: tests.py プロジェクト: GroupBank/global-server
    def test_new_user_invalid_group_uuid(self):
        user_priv, user_pub = example_keys.C1_priv, example_keys.C1_pub
        group_priv, group_pub = example_keys.G1_priv, example_keys.G1_pub

        payload = json.dumps({
            'user_key': user_pub,
            'group_uuid': 'random_uuid'
        })
        signature = crypto.sign(group_priv, payload)

        response = self.client.post(reverse('rest:group:register-user'), {
            'author': group_pub,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 400

        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())
コード例 #11
0
ファイル: tests.py プロジェクト: GroupBank/global-server
    def test_correct_inputs(self):
        group_name = 'test_name'
        priv_key, pub_key = example_keys.G1_priv, example_keys.G1_pub
        id = pub_key

        payload = json.dumps({'group_name': group_name, 'group_key': pub_key})
        signature = crypto.sign(priv_key, payload)

        response = self.client.post(reverse('rest:group:register'), {
            'author': id,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 201
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['group_name'] == group_name
        assert payload['group_key'] == pub_key
        UUID(payload['group_uuid'])
コード例 #12
0
    def test_get_totals_one_unconfirmed_uome(self):
        UOMe.objects.create(group=self.group,
                            lender=self.user2,
                            borrower=self.user1,
                            value=10,
                            description="test",
                            issuer_signature='meh')

        response = self.client.post(
            reverse('rest:uome:get-totals'), {
                'author': self.key,
                'signature': self.signature,
                'payload': self.payload
            })

        assert response.status_code == 200
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['user_balance'] == 0
        assert payload['suggested_transactions'] == {}
コード例 #13
0
    def test_VerifyingACompletelyBrokenSignature_RaisesInvalidSignature(self):
        key, pubkey = ec_secp256k1.generate_keys()

        with raises(ec_secp256k1.InvalidSignature):
            ec_secp256k1.verify(pubkey, "completelyBogûsÇigna_!ture",
                                "not a chance!")
コード例 #14
0
def get_totals(request):
    """
    Used by a user to check the totals of users in the group
    """
    try:
        payload = json.loads(request.POST['payload'])
    except json.JSONDecodeError:
        logger.info('Malformed request')
        return HttpResponseBadRequest()

    try:
        group_uuid = payload['group_uuid']
        user_id = payload['user']
        user_signature = payload['user_signature']
    except KeyError:
        logger.info('Request with missing attributes')
        return HttpResponseBadRequest()

    try:  # check that the group exists and get it
        group = Group.objects.get(pk=group_uuid)
        user = User.objects.get(group=group, key=user_id)
    except (ValidationError,
            ObjectDoesNotExist):  # ValidationError if the key is invalid
        logger.info('Request tried to get the totals for non-existent group %s'
                    'or user %s' % (group_uuid, user_id))
        return HttpResponseBadRequest()

    user_payload = json.dumps({
        'group_uuid': str(group.uuid),
        'user': user.key,
    })

    # todo: probably unnecessary because of the verify author decorator
    try:  # verify the signatures
        crypto.verify(user.key, user_signature, user_payload)
    except (crypto.InvalidKey, crypto.InvalidSignature):
        logger.info('Request with invalid signature or key by author %s' %
                    user_id)
        return HttpResponseForbidden()

    # example: {'user1': val1, 'user2': val2}
    suggested_transactions = {}

    # todo: send the actual totals along with the suggested transactions
    if user.balance < 0:  # filter by borrower
        for debt in UserDebt.objects.filter(group=group, borrower=user):
            suggested_transactions[debt.lender.key] = debt.value

    elif user.balance > 0:  # filter by lender
        for debt in UserDebt.objects.filter(group=group, lender=user):
            suggested_transactions[debt.borrower.key] = debt.value

    response = json.dumps({
        'group_uuid': str(group.uuid),
        'user': user.key,
        'user_balance': user.balance,
        'suggested_transactions': suggested_transactions,
    })

    logger.info('Totals sent to user %s' % user_id)
    return HttpResponse(response, status=200)
コード例 #15
0
def issue(request):
    """
    Used by a user to issue an unconfirmed UOMe to another user
    """
    try:
        payload = json.loads(request.POST['payload'])
    except json.JSONDecodeError:
        logger.info('Malformed request')
        return HttpResponseBadRequest()

    try:
        group_uuid = payload['group_uuid']
        user_id = payload['user']
        borrower_id = payload['borrower']
        value = payload['value']
        description = payload['description']
        auth_signature = payload['user_signature']
    except KeyError:
        logger.info('Request with missing attributes')
        return HttpResponseBadRequest()

    if request.POST['author'] != user_id:
        logger.info('Request made by unauthorized author %s' %
                    request.POST['author'])
        return HttpResponse('401 Unauthorized', status=401)

    auth_payload = json.dumps({'group_uuid': str(group_uuid), 'user': user_id})

    try:
        crypto.verify(user_id, auth_signature, auth_payload)
    except (crypto.InvalidKey, crypto.InvalidSignature):
        logger.info('Request with invalid signature or key by author %s' %
                    user_id)
        return HttpResponseForbidden()

    try:  # check that the group exists and get it
        group = Group.objects.get(pk=group_uuid)
        user = User.objects.get(group=group, key=user_id)
        borrower = User.objects.get(group=group, key=borrower_id)
    except (ValidationError,
            ObjectDoesNotExist):  # ValidationError if key is not valid
        logger.info('Request tried to issue uome for non-existent group %s'
                    ', user %s or borrower %s' %
                    (group_uuid, user_id, borrower_id))
        return HttpResponseBadRequest()

    if value <= 0:  # So it's not possible to invert the direction of the UOMe
        logger.info(
            'Request tried to issue a uome with negative value (user %s)',
            user)
        return HttpResponseBadRequest()

    if len(description) > UOME_DESCRIPTION_MAX_LENGTH:
        logger.info(
            'Request tried to issue a uome with invalid description (user %s)',
            user)
        return HttpResponseBadRequest()

    if user == borrower:  # That would just be weird...
        logger.info(
            'Request tried to issue a uome from a user (%s) to themselves',
            user)
        return HttpResponseBadRequest()

    # TODO: the description can leak information, maybe it should be encrypted
    uome = UOMe.objects.create(group=group,
                               lender=user,
                               borrower=borrower,
                               value=value,
                               description=description)

    response = json.dumps({
        'group_uuid': str(group.uuid),
        'user': user.key,
        'borrower': borrower.key,
        'value': value,
        'description': description,
        'uome_uuid': str(uome.uuid)
    })

    logger.info('New uome %s issued in group %s by user %s' %
                (uome.uuid, group_uuid, user_id))
    return HttpResponse(response, status=201)
コード例 #16
0
def confirm(request):
    """
    Used by a user to confirm an unconfirmed UOMe after the server assigns it an uuid
    """
    try:
        payload = json.loads(request.POST['payload'])
    except json.JSONDecodeError:
        logger.info('Malformed request')
        return HttpResponseBadRequest()

    try:
        group_uuid = payload['group_uuid']
        user_id = payload['user']
        uome_uuid = payload['uome_uuid']
        user_signature = payload['user_signature']
    except KeyError:
        logger.info('Request with missing attributes')
        return HttpResponseBadRequest()

    if request.POST['author'] != user_id:
        logger.info('Request made by unauthorized author %s' %
                    request.POST['author'])
        return HttpResponse('401 Unauthorized', status=401)

    try:  # check that the group exists and get it
        group = Group.objects.get(pk=group_uuid)
        user = User.objects.get(group=group, key=user_id)
        uome = UOMe.objects.get(pk=uome_uuid)
    except (ValidationError,
            ObjectDoesNotExist):  # ValidationError if key not valid
        logger.info(
            'Request tried to confirm uome %s for non-existent group %s'
            ', user %s' % (uome_uuid, group_uuid, user_id))
        return HttpResponseBadRequest()

    uome_payload = json.dumps({
        'group_uuid': str(uome.group.uuid),
        'user': uome.lender.key,
        'borrower': uome.borrower.key,
        'value': uome.value,
        'description': uome.description,
        'uome_uuid': str(uome.uuid),
    })

    try:
        crypto.verify(user_id, user_signature, uome_payload)
    except (crypto.InvalidKey, crypto.InvalidSignature):
        logger.info('Request with invalid signature or key by author %s' %
                    user_id)
        return HttpResponseForbidden()

    # TODO: the description can leak information, maybe it should be encrypted
    uome.issuer_signature = payload['user_signature']
    uome.save()

    # user created, create the response object
    response = json.dumps({'group_uuid': str(group.uuid), 'user': user.key})

    logger.info('New uome %s confirmed in group %s by user %s' %
                (uome.uuid, group_uuid, user_id))
    return HttpResponse(response, status=200)
コード例 #17
0
    def test_confirm_first_uome(self):

        uome = UOMe.objects.create(
            group=self.group,
            lender=self.lender,
            borrower=self.user,
            value=10,
            description='test',
        )

        issuer_payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'issuer': self.lender.key,
            'borrower': self.user.key,
            'value': 10,
            'description': 'test',
            'uome_uuid': str(uome.uuid),
        })
        issuer_signature = crypto.sign(example_keys.C2_priv, issuer_payload)

        uome.issuer_signature = issuer_signature
        uome.save()

        assert uome.borrower_signature == ''

        borrower_payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'issuer': self.lender.key,
            'borrower': self.user.key,
            'value': 10,
            'description': 'test',
            'uome_uuid': str(uome.uuid),
        })
        borrower_signature = crypto.sign(self.private_key, borrower_payload)

        payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'user': self.user.key,
            'uome_uuid': str(uome.uuid),
            'user_signature': borrower_signature,
        })
        signature = crypto.sign(self.private_key, payload)

        response = self.client.post(reverse('rest:uome:accept'), {
            'author': self.user.key,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 200
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['group_uuid'] == str(self.group.uuid)
        assert payload['user'] == self.user.key

        uome = UOMe.objects.filter(group=self.group, uuid=uome.uuid).first()
        assert uome.borrower_signature == borrower_signature

        # Confirm totals
        totals = {}
        for user in User.objects.filter(group=self.group):
            totals[user] = user.balance

        assert totals == {self.user: -uome.value, self.lender: uome.value}

        # Confirm simplified debt
        simplified_debt = defaultdict(dict)
        for user_debt in UserDebt.objects.filter(group=self.group):
            simplified_debt[user_debt.borrower][
                user_debt.lender] = user_debt.value

        assert simplified_debt == {self.user: {self.lender: uome.value}}
コード例 #18
0
def accept(request):
    """
       Used by a user to accept a pending UOMe issued to them
       """
    try:
        payload = json.loads(request.POST['payload'])
    except json.JSONDecodeError:
        logger.info('Malformed request')
        return HttpResponseBadRequest()

    try:
        group_uuid = payload['group_uuid']
        user_id = payload['user']
        uome_uuid = payload['uome_uuid']
        uome_signature = payload['user_signature']
    except KeyError:
        logger.info('Request with missing attributes')
        return HttpResponseBadRequest()

    try:  # check that the group exists and get it
        group = Group.objects.get(pk=group_uuid)
        user = User.objects.get(group=group, key=user_id)
        uome = UOMe.objects.get(group=group, uuid=uome_uuid)
    except (ValidationError,
            ObjectDoesNotExist):  # ValidationError if the key is invalid
        logger.info('Request tried accepting a uomes for non-existent group %s'
                    ', user %s or uome %s' % (group_uuid, user_id, uome_uuid))
        return HttpResponseBadRequest()

    if request.POST['author'] != user_id or request.POST[
            'author'] != uome.borrower.key:
        logger.info('Request made by unauthorized author %s' %
                    request.POST['author'])
        return HttpResponse('401 Unauthorized', status=401)

    uome_payload = json.dumps({
        'group_uuid': str(uome.group.uuid),
        'issuer': uome.lender.key,
        'borrower': uome.borrower.key,
        'value': uome.value,
        'description': uome.description,
        'uome_uuid': str(uome.uuid),
    })

    try:  # verify the signatures
        crypto.verify(user.key, uome_signature, uome_payload)
    except (crypto.InvalidKey, crypto.InvalidSignature):
        logger.info('Request with invalid signature or key by author %s' %
                    user_id)
        return HttpResponseForbidden()

    uome.borrower_signature = uome_signature
    uome.save()

    # update the balances and suggestions of users
    group_users = User.objects.filter(group=group)

    totals = defaultdict(int)
    for group_user in group_users:
        totals[group_user.key] = group_user.balance

    new_uome = [uome.borrower.key, uome.lender.key, uome.value]
    new_totals, new_simplified_debt = simplify_debt.update_total_debt(
        totals, [new_uome])

    for group_user in group_users:
        group_user.balance = new_totals[group_user.key]
        group_user.save()

    # drop the previous user debt for this group, since it's now useless
    UserDebt.objects.filter(group=group).delete()

    for borrower, user_debts in new_simplified_debt.items():
        # debts is a dict of users this borrower owes to, like {'user1': 3, 'user2':8}
        for lender, value in user_debts.items():
            UserDebt.objects.create(group=group,
                                    value=value,
                                    borrower=User.objects.get(key=borrower),
                                    lender=User.objects.get(key=lender))

    response = json.dumps({
        'group_uuid': str(uome.group.uuid),
        'user': user.key,
        'uome_uuid': str(uome.uuid),
    })

    logger.info('UOMe %s was accepted by user %s' % (str(uome_uuid), user_id))
    return HttpResponse(response, status=200)
コード例 #19
0
def get_pending(request):
    """
    Used by a user to request a list of pending (not yet accepted) UOMes issued to/by them
    """
    try:
        payload = json.loads(request.POST['payload'])
    except json.JSONDecodeError:
        logger.info('Malformed request')
        return HttpResponseBadRequest()

    try:
        group_uuid = payload['group_uuid']
        user_id = payload['user']
        auth_signature = payload['user_signature']
    except KeyError:
        logger.info('Request with missing attributes')
        return HttpResponseBadRequest()

    if request.POST['author'] != user_id:
        logger.info('Request made by unauthorized author %s' %
                    request.POST['author'])
        return HttpResponse('401 Unauthorized', status=401)

    try:  # check that the group exists and get it
        group = Group.objects.get(pk=group_uuid)
        user = User.objects.get(group=group, key=user_id)
    except (ValidationError,
            ObjectDoesNotExist):  # ValidationError if the key is invalid
        logger.info(
            'Request tried accessing pending uomes for non-existent group %s'
            ', user %s' % (group_uuid, user_id))
        return HttpResponseBadRequest()

    auth_payload = json.dumps({
        'group_uuid': str(group.uuid),
        'user': user.key,
    })

    try:  # verify the signatures
        crypto.verify(user.key, auth_signature, auth_payload)
    except (crypto.InvalidKey, crypto.InvalidSignature):
        logger.info('Request with invalid signature or key by author %s' %
                    user_id)
        return HttpResponseForbidden()

    # TODO: add a test for uome's without issuer signatures
    uomes_by_user = UOMe.objects.filter(
        group=group, borrower_signature='',
        lender=user).exclude(issuer_signature='')
    uomes_for_user = UOMe.objects.filter(
        group=group, borrower_signature='',
        borrower=user).exclude(issuer_signature='')
    issued_by_user = []
    for uome in uomes_by_user:
        issued_by_user.append(uome.to_dict_unconfirmed())
    waiting_for_user = []
    for uome in uomes_for_user:
        waiting_for_user.append(uome.to_dict_unconfirmed())

    response = json.dumps({
        'group_uuid': str(group.uuid),
        'user': user.key,
        'issued_by_user': json.dumps(issued_by_user),
        'waiting_for_user': json.dumps(waiting_for_user),
    })

    logger.info('Sent pending uome list to user %s' % user_id)
    return HttpResponse(response, status=200)
コード例 #20
0
    def test_one_by_user_uome_and_one_for_user_uome(self):

        uome_by_user = UOMe.objects.create(group=self.group,
                                           lender=self.user,
                                           borrower=self.other_user,
                                           value=30,
                                           description="by user")

        uome_by_user_payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'issuer': self.user.key,
            'borrower': self.other_user.key,
            'value': 30,
            'description': 'by user',
            'uome_uuid': str(uome_by_user.uuid),
        })
        uome_by_user_signature = crypto.sign(self.private_key,
                                             uome_by_user_payload)

        uome_by_user.issuer_signature = uome_by_user_signature
        uome_by_user.save()

        uome_for_user = UOMe.objects.create(group=self.group,
                                            lender=self.other_user,
                                            borrower=self.user,
                                            value=20,
                                            description="for user")

        uome_for_user_payload = json.dumps({
            'group_uuid':
            str(self.group.uuid),
            'issuer':
            self.other_user.key,
            'borrower':
            self.user.key,
            'value':
            20,
            'description':
            'for user',
            'uome_uuid':
            str(uome_for_user.uuid),
        })
        uome_for_user_signature = crypto.sign(self.private_key,
                                              uome_for_user_payload)

        uome_for_user.issuer_signature = uome_for_user_signature
        uome_for_user.save()

        assert uome_by_user.borrower_signature == ''
        assert uome_by_user.issuer_signature != ''

        assert uome_for_user.borrower_signature == ''
        assert uome_for_user.issuer_signature != ''

        auth_payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'user': self.user.key
        })
        auth_signature = crypto.sign(self.private_key, auth_payload)

        payload = json.dumps({
            'group_uuid': str(self.group.uuid),
            'user': self.user.key,
            'user_signature': auth_signature
        })
        signature = crypto.sign(self.private_key, payload)

        response = self.client.post(reverse('rest:uome:get-pending'), {
            'author': self.user.key,
            'signature': signature,
            'payload': payload
        })

        assert response.status_code == 200
        assert response['author'] == server_key
        crypto.verify(server_key, response['signature'],
                      response.content.decode())

        payload = json.loads(response.content.decode())

        assert payload['group_uuid'] == str(self.group.uuid)
        assert payload['user'] == self.user.key

        issued_by_user = json.loads(payload['issued_by_user'])
        for uome in issued_by_user:
            assert uome['group_uuid'] == str(uome_by_user.group.uuid)
            assert uome['lender'] == uome_by_user.lender.key
            assert uome['borrower'] == uome_by_user.borrower.key
            assert uome['value'] == uome_by_user.value
            assert uome['description'] == uome_by_user.description
            assert uome['uuid'] == str(uome_by_user.uuid)
            assert uome['issuer_signature'] == uome_by_user_signature

        waiting_for_user = json.loads(payload['waiting_for_user'])
        for uome in waiting_for_user:
            assert uome['group_uuid'] == str(uome_by_user.group.uuid)
            assert uome['lender'] == uome_for_user.lender.key
            assert uome['borrower'] == uome_for_user.borrower.key
            assert uome['value'] == uome_for_user.value
            assert uome['description'] == uome_for_user.description
            assert uome['uuid'] == str(uome_for_user.uuid)
            assert uome['issuer_signature'] == uome_for_user_signature