Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/signify/core/authing.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def rotate(self, nbran, aids):
for nxt in nxts:
nnxts.append(self.recrypt(nxt, decrypter, encrypter))

keys[pre] = dict(prxs=nprxs, nxts=nxts)
keys[pre] = dict(prxs=nprxs, nxts=nnxts)

data["keys"] = keys
return data
Expand Down
4 changes: 2 additions & 2 deletions src/signify/core/keeping.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,13 @@ def rotate(self, ncodes, transferable, **_):
return verfers, digers

def sign(self, ser, indexed=True, indices=None, ondices=None, **_):
signers = [self.decrypter.decrypt(ser=signing.Cipher(qb64=prx).qb64b, transferable=self.transferable)
signers = [self.decrypter.decrypt(cipher=signing.Cipher(qb64=prx), transferable=self.transferable)
for prx in self.prxs]
return self.__sign__(ser, signers=signers, indexed=indexed, indices=indices, ondices=ondices)

def signers(self):
"""Return signer objects decrypted from the keeper's current key set."""
return [self.decrypter.decrypt(ser=signing.Cipher(qb64=prx).qb64b, transferable=self.transferable)
return [self.decrypter.decrypt(cipher=signing.Cipher(qb64=prx), transferable=self.transferable)
for prx in self.prxs]


Expand Down
101 changes: 101 additions & 0 deletions tests/app/test_aiding.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,54 @@ def test_aiding_create():
unstub()


def test_aiding_create_randy():
from signify.core import keeping
mock_keeper = mock(
{'params': lambda: {'prxs': ['enc current'], 'nxts': ['enc next'], 'transferable': True}},
spec=keeping.RandyKeeper,
strict=True,
)
mock_manager = mock(spec=keeping.Manager, strict=True)

from mockito import kwargs
expect(mock_manager, times=1).new('randy', 0, **kwargs).thenReturn(mock_keeper)

keys = ['a signer verfer qb64']
ndigs = ['next signer digest']

expect(mock_keeper, times=1).incept(transferable=True).thenReturn((keys, ndigs))

from keri.core import serdering
mock_serder = mock({'raw': b'raw bytes', 'ked': {'a': 'key event dictionary'}}, spec=serdering.SerderKERI,
strict=True)

from keri.core import eventing
expect(eventing, times=1).incept(keys=keys, isith='1', nsith='1', ndigs=ndigs, code='E', wits=[], toad='0',
cnfg=[], data=[]).thenReturn(mock_serder)
expect(mock_keeper, times=1).sign(mock_serder.raw).thenReturn(['a signature'])

from signify.app.clienting import SignifyClient
mock_client = mock({'pidx': 0}, spec=SignifyClient, strict=True)
mock_client.manager = mock_manager # type: ignore

from signify.app.aiding import Identifiers
ids = Identifiers(client=mock_client) # type: ignore

from requests import Response
resp = mock({'json': lambda: {'post': 'success'}}, spec=Response, strict=True)
expect(mock_client, times=1).post('/identifiers', json={'name': 'new_aid', 'icp': {'a': 'key event dictionary'},
'sigs': ['a signature'], 'proxy': None,
'randy': {'prxs': ['enc current'], 'nxts': ['enc next'],
'transferable': True}}).thenReturn(resp)

ids.create(name='new_aid', algo='randy')

assert mock_client.pidx == 1

verifyNoUnwantedInteractions()
unstub()


def test_aiding_create_cnfg():
from signify.core import keeping
mock_keeper = mock({'params': lambda: {'keeper': 'params'}}, spec=keeping.SaltyKeeper, strict=True)
Expand Down Expand Up @@ -468,6 +516,59 @@ def test_aiding_rotate():
unstub()


def test_aiding_rotate_randy():
from signify.app.clienting import SignifyClient
mock_client = mock(spec=SignifyClient, strict=True)

from signify.core import keeping
mock_manager = mock(spec=keeping.Manager, strict=True)
mock_client.manager = mock_manager # type: ignore

from signify.app.aiding import Identifiers
ids = Identifiers(client=mock_client) # type: ignore

mock_hab = {'prefix': 'hab prefix', 'name': 'aid1',
'state': {'s': '0', 'd': 'hab digest', 'b': ['wit1', 'wit2', 'wit3'], 'k': ['key1']}}
expect(ids, times=1).get('aid1').thenReturn(mock_hab)

mock_keeper = mock(
{'algo': 'randy', 'params': lambda: {'prxs': ['enc current'], 'nxts': ['enc next'], 'transferable': True}},
spec=keeping.RandyKeeper,
strict=True,
)
expect(mock_manager, times=1).get(mock_hab).thenReturn(mock_keeper)

keys = ['key1']
ndigs = ['ndig1']
expect(mock_keeper, times=1).rotate(ncodes=['A'], transferable=True, states=None, rstates=None).thenReturn(
(keys, ndigs)
)

from keri.core import serdering
mock_serder = mock({'ked': {'a': 'key event dictionary'}, 'raw': b'serder raw bytes'}, spec=serdering.SerderKERI,
strict=True)

from keri.core import eventing
expect(eventing, times=1).rotate(pre='hab prefix', keys=['key1'], dig='hab digest', sn=1, isith='1', nsith='1',
ndigs=['ndig1'], toad=None, wits=['wit1', 'wit2', 'wit3'],
cuts=[], adds=[], data=[]).thenReturn(mock_serder)

expect(mock_keeper, times=1).sign(ser=mock_serder.raw).thenReturn(['a signature'])

from requests import Response
mock_response = mock(spec=Response, strict=True)
expected_data = {'rot': {'a': 'key event dictionary'}, 'sigs': ['a signature'],
'randy': {'prxs': ['enc current'], 'nxts': ['enc next'], 'transferable': True}}
expect(mock_client, times=1).post('/identifiers/aid1/events', json=expected_data).thenReturn(mock_response)
expect(mock_response, times=1).json().thenReturn({'success': 'yay'})

_, _, out = ids.rotate(name='aid1')
assert out['success'] == 'yay'

verifyNoUnwantedInteractions()
unstub()


def test_aiding_add_end_role():
from signify.app.clienting import SignifyClient
mock_client = mock(spec=SignifyClient, strict=True)
Expand Down
85 changes: 41 additions & 44 deletions tests/core/test_authing.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,47 +249,44 @@ def test_controller_rotate_salty():
assert 'sxlt' in out['keys']['ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK'] # type: ignore
assert out['keys']['ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK']['sxlt'] != "1AAH2R_SPhr_5vIBGGtyVamaGVDQAcYlgmwDOkJwM-q6Qw8K5NT7jLzJ0k6_7sa3oyKK33ym8JX1Il4MoUiy8ixYwsVWYhaU3sMT" # type: ignore

# def test_controller_rotate_randy():
# from keri.core.coring import Tiers
# from signify.core.authing import Controller
# ctrl = Controller(bran="abcdefghijklmnop01234", tier=Tiers.low)

# from keri.core.signing import Salter
# mock_salter = mock({'qb64': 'salter qb64'}, spec=Salter, strict=True)
# ctrl.salter = mock_salter

# from signify.core.keeping import SaltyCreator
# mock_creator = mock({'create': lambda ridx, tier : None}, spec=SaltyCreator, strict=True)
# from signify.core import keeping
# when(keeping).SaltyCreator(salt='salter qb64', stem='signify:controller', tier=Tiers.low).thenReturn(mock_creator)

# from keri.core.signing import Signer
# mock_signer = mock(spec=Signer, strict=True)
# ctrl.signer = mock_signer
# mock_nsigner = mock(spec=Signer, strict=True)
# ctrl.nsigner = mock_nsigner
# ctrl.keys = ['a key']
# from keri.core.coring import Diger
# mock_diger = mock(spec=Diger, strict=True)
# ctrl.ndigs = [mock_diger]

# from keri.core.serdering import Serder
# mock_serder = mock(spec=Serder, strict=True)
# ctrl.serder = mock_serder

# # end controller mock setup
# assert ctrl.bran == '0AAabcdefghijklmnop01234'

# # mocks for rotate
# when(mock_salter).signer(transferable=False).thenReturn(mock_nsigner)
# mock_nsalter = mock(spec=Salter, strict=True)
# from keri.core import coring
# when(coring).Salter(qb64='0AA0123456789abcdefghijk').thenReturn(mock_nsalter)

# from signify.core.keeping import SaltyCreator
# mock_ncreator = mock(spec=SaltyCreator, strict=True)

# from signify.core import keeping
# expect(keeping, times=1).SaltyCreator(salt='salter qb64', stem='signify:controller', tier=Tiers.low).thenReturn(mock_ncreator)

# ctrl.rotate(nbran="0123456789abcdefghijk", aids=["aid_one"],)
def test_controller_rotate_randy():
from signify.core.authing import Controller
from signify.core.keeping import RandyKeeper
ctrl = Controller(bran="abcdefghijklmnop01234", tier=Tiers.low)

keeper = RandyKeeper(ctrl.salter, transferable=True)
pubs, digers = keeper.incept(transferable=True)

aid = {
"name": "aid1",
"prefix": "ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK",
"randy": keeper.params(),
"state": {
"k": pubs,
},
}

old_prxs = list(aid["randy"]["prxs"])
old_nxts = list(aid["randy"]["nxts"])

out = ctrl.rotate(nbran="0123456789abcdefghijk", aids=[aid])

rotated = out["keys"]["ELUvZ8aJEHAQE-0nsevyYTP98rBbGJUrTj5an-pCmwrK"]
assert rotated["prxs"] != old_prxs
assert rotated["nxts"] != old_nxts

from keri.core import coring, signing
signer = ctrl.salter.signer(transferable=False)
decrypter = signing.Decrypter(seed=signer.qb64)

signers = [
decrypter.decrypt(cipher=signing.Cipher(qb64=prx), transferable=True)
for prx in rotated["prxs"]
]
assert [signer.verfer.qb64 for signer in signers] == pubs

nsigners = [
decrypter.decrypt(cipher=signing.Cipher(qb64=nxt), transferable=True)
for nxt in rotated["nxts"]
]
assert [coring.Diger(ser=nsigner.verfer.qb64b).qb64 for nsigner in nsigners] == digers
6 changes: 4 additions & 2 deletions tests/core/test_keeping.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,8 @@ def test_randy_keeper_rotate():

assert verfers == ['signer verfer qb64']
assert digers == ['diger qb64']
assert rk.prxs == ['nxt qb64']
assert rk.nxts == ['cipher qb64']

verifyNoUnwantedInteractions()
unstub()
Expand Down Expand Up @@ -709,7 +711,7 @@ def test_randy_keeper_sign():
from keri.core.signing import Signer
mock_verfer = mock({'qb64': 'signer verfer qb64'}, spec=Verfer, strict=True)
mock_signer = mock({'verfer': mock_verfer}, spec=Signer, strict=True)
expect(mock_decrypter, times=1).decrypt(ser=b'cipher qb64b', transferable=False).thenReturn(mock_signer)
expect(mock_decrypter, times=1).decrypt(cipher=mock_prx_cipher, transferable=False).thenReturn(mock_signer)

# test
from signify.core.keeping import RandyKeeper
Expand Down Expand Up @@ -870,4 +872,4 @@ def test_base_keeper_sign_indexed_boom(indexed, indices, ondices, expected):
mock_signer_one = mock(spec=Signer, strict=True)

with pytest.raises(ValueError, match=expected):
BaseKeeper.__sign__(b'ser bytes', [mock_signer_one], indexed=indexed, indices=indices, ondices=ondices)
BaseKeeper.__sign__(b'ser bytes', [mock_signer_one], indexed=indexed, indices=indices, ondices=ondices)
55 changes: 55 additions & 0 deletions tests/integration/test_provisioning_and_identifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from __future__ import annotations

import pytest
from keri.app.keeping import Algos
from keri.core import coring, serdering
from .constants import QVI_SCHEMA_SAID, TEST_WITNESS_AIDS
from .helpers import (
additional_schema_oobis,
Expand Down Expand Up @@ -100,6 +102,59 @@ def test_single_sig_identifier_lifecycle_smoke(client_factory):
assert fetched["prefix"] == hab["prefix"]


def test_randy_identifier_lifecycle_smoke(client_factory):
"""Prove Randy identifiers behave like the maintained SignifyTS lifecycle contract."""
client = client_factory()
name = alias("randy")

_, _, operation = client.identifiers().create(name, algo=Algos.randy, wits=[])
result = wait_for_operation(client, operation)
icp = serdering.SerderKERI(sad=result["response"])

assert len(icp.verfers) == 1
assert len(icp.ked["n"]) == 1
assert icp.ked["kt"] == "1"
assert icp.ked["nt"] == "1"

identifiers = client.identifiers().list()
aid = client.identifiers().get(name)
names = {entry["name"] for entry in identifiers["aids"]}

assert name in names
assert aid["name"] == name
assert aid["prefix"] == icp.pre
assert aid["state"]["s"] == "0"
assert len(aid["randy"]["prxs"]) == 1
assert len(aid["randy"]["nxts"]) == 1

_, _, interact_operation = client.identifiers().interact(name, data=[icp.pre])
interact_result = wait_for_operation(client, interact_operation)
ixn = serdering.SerderKERI(sad=interact_result["response"])

assert ixn.ked["s"] == "1"
assert ixn.ked["a"] == [icp.pre]

events = client.keyEvents().get(aid["prefix"])
assert len(events) == 2

_, _, rotate_operation = client.identifiers().rotate(name)
rotate_result = wait_for_operation(client, rotate_operation)
rot = serdering.SerderKERI(sad=rotate_result["response"])

assert rot.ked["s"] == "2"
assert len(rot.verfers) == 1
assert len(rot.ked["n"]) == 1
assert rot.verfers[0].qb64 != icp.verfers[0].qb64
assert rot.ked["n"][0] != icp.ked["n"][0]
assert coring.Diger(ser=rot.verfers[0].qb64b, code=coring.MtrDex.Blake3_256).qb64 == icp.ked["n"][0]

rotated = client.identifiers().get(name)
assert rotated["state"]["s"] == "2"

events = client.keyEvents().get(aid["prefix"])
assert len(events) == 3


def test_identifier_rename_update_compatibility(client_factory):
"""Prove TS-style identifier rename works without dropping the Python wrappers."""
client = client_factory()
Expand Down
Loading