From ea53e90c52520419315f2423f413bc8e79de72df Mon Sep 17 00:00:00 2001 From: 2byrds <2byrds@gmail.com> Date: Mon, 22 Jul 2024 15:56:50 -0400 Subject: [PATCH] setting formatting to black formatter to improve future PR merges Signed-off-by: 2byrds <2byrds@gmail.com> --- src/dkr/app/cli/commands/did/keri/resolve.py | 62 ++++-- .../cli/commands/did/keri/resolver-service.py | 91 ++++---- src/dkr/app/cli/commands/did/webs/generate.py | 140 ++++++++---- src/dkr/app/cli/commands/did/webs/resolve.py | 48 +++-- .../cli/commands/did/webs/resolver-service.py | 91 ++++---- src/dkr/app/cli/commands/did/webs/service.py | 115 ++++++---- src/dkr/app/cli/dkr.py | 2 +- src/dkr/core/didding.py | 202 ++++++++++-------- src/dkr/didcomm/hello-world.py | 143 +++++++------ src/dkr/didcomm/utils.py | 202 ++++++++++-------- .../app/cli/commands/did/webs/test_resolve.py | 59 ++--- tests/dkr/core/test_webbing.py | 59 ++--- 12 files changed, 710 insertions(+), 504 deletions(-) diff --git a/src/dkr/app/cli/commands/did/keri/resolve.py b/src/dkr/app/cli/commands/did/keri/resolve.py index 6f34541..4fd3fed 100644 --- a/src/dkr/app/cli/commands/did/keri/resolve.py +++ b/src/dkr/app/cli/commands/did/keri/resolve.py @@ -15,27 +15,51 @@ from dkr.core import didding -parser = argparse.ArgumentParser(description='Resolve a did:keri DID') -parser.set_defaults(handler=lambda args: handler(args), - transferable=True) -parser.add_argument('-n', '--name', - action='store', - default="dkr", - help="Name of controller. Default is dkr.") -parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', - required=False, default="") -parser.add_argument('--passcode', help='22 character encryption passcode for keystore (is not saved)', - dest="bran", default=None) # passcode => bran -parser.add_argument("--did", "-d", help="DID to resolve (did:keri method)", required=True) -parser.add_argument("--oobi", "-o", help="OOBI to use for resolving the DID", required=False) -parser.add_argument("--meta", "-m", help="Whether to include metadata (True), or only return the DID document (False)", type=bool, required=False, default=None) +parser = argparse.ArgumentParser(description="Resolve a did:keri DID") +parser.set_defaults(handler=lambda args: handler(args), transferable=True) +parser.add_argument( + "-n", + "--name", + action="store", + default="dkr", + help="Name of controller. Default is dkr.", +) +parser.add_argument( + "--base", + "-b", + help="additional optional prefix to file location of KERI keystore", + required=False, + default="", +) +parser.add_argument( + "--passcode", + help="22 character encryption passcode for keystore (is not saved)", + dest="bran", + default=None, +) # passcode => bran +parser.add_argument( + "--did", "-d", help="DID to resolve (did:keri method)", required=True +) +parser.add_argument( + "--oobi", "-o", help="OOBI to use for resolving the DID", required=False +) +parser.add_argument( + "--meta", + "-m", + help="Whether to include metadata (True), or only return the DID document (False)", + type=bool, + required=False, + default=None, +) def handler(args): hby = existing.setupHby(name=args.name, base=args.base, bran=args.bran) hbyDoer = habbing.HaberyDoer(habery=hby) # setup doer obl = oobiing.Oobiery(hby=hby) - res = KeriResolver(hby=hby, hbyDoer=hbyDoer, obl=obl, did=args.did, oobi=args.oobi, meta=args.meta) + res = KeriResolver( + hby=hby, hbyDoer=hbyDoer, obl=obl, did=args.did, oobi=args.oobi, meta=args.meta + ) return [res] @@ -55,7 +79,7 @@ def __init__(self, hby, hbyDoer, obl, did, oobi, meta): def resolve(self, tymth, tock=0.0, **opts): self.wind(tymth) self.tock = tock - _ = (yield self.tock) + _ = yield self.tock aid = didding.parseDIDKeri(self.did) print(f"From arguments got aid: {aid}", file=sys.stderr) @@ -68,7 +92,9 @@ def resolve(self, tymth, tock=0.0, **opts): while self.hby.db.roobi.get(keys=(self.oobi,)) is None: _ = yield tock - didresult = didding.generateDIDDoc(self.hby, did=self.did, aid=aid, oobi=self.oobi, meta=True) + didresult = didding.generateDIDDoc( + self.hby, did=self.did, aid=aid, oobi=self.oobi, meta=True + ) dd = didresult[didding.DD_FIELD] result = didresult if self.meta else dd data = json.dumps(result, indent=2) @@ -76,5 +102,3 @@ def resolve(self, tymth, tock=0.0, **opts): print(data) self.remove(self.toRemove) return result - - diff --git a/src/dkr/app/cli/commands/did/keri/resolver-service.py b/src/dkr/app/cli/commands/did/keri/resolver-service.py index 96dd9f1..a65d893 100644 --- a/src/dkr/app/cli/commands/did/keri/resolver-service.py +++ b/src/dkr/app/cli/commands/did/keri/resolver-service.py @@ -10,31 +10,51 @@ from dkr.core import resolving -parser = argparse.ArgumentParser(description='Expose did:keri resolver as an HTTP web service') -parser.set_defaults(handler=lambda args: launch(args), - transferable=True) -parser.add_argument('-p', '--http', - action='store', - default=7678, - help="Port on which to listen for did:keri resolution requests. Defaults to 7678") -parser.add_argument('-n', '--name', - action='store', - default="dkr", - help="Name of controller. Default is dkr.") -parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', - required=False, default="") -parser.add_argument('--passcode', help='22 character encryption passcode for keystore (is not saved)', - dest="bran", default=None) # passcode => bran -parser.add_argument("--config-dir", - "-c", - dest="configDir", - help="directory override for configuration data", - default=None) -parser.add_argument('--config-file', - dest="configFile", - action='store', - default=None, - help="configuration filename override") +parser = argparse.ArgumentParser( + description="Expose did:keri resolver as an HTTP web service" +) +parser.set_defaults(handler=lambda args: launch(args), transferable=True) +parser.add_argument( + "-p", + "--http", + action="store", + default=7678, + help="Port on which to listen for did:keri resolution requests. Defaults to 7678", +) +parser.add_argument( + "-n", + "--name", + action="store", + default="dkr", + help="Name of controller. Default is dkr.", +) +parser.add_argument( + "--base", + "-b", + help="additional optional prefix to file location of KERI keystore", + required=False, + default="", +) +parser.add_argument( + "--passcode", + help="22 character encryption passcode for keystore (is not saved)", + dest="bran", + default=None, +) # passcode => bran +parser.add_argument( + "--config-dir", + "-c", + dest="configDir", + help="directory override for configuration data", + default=None, +) +parser.add_argument( + "--config-file", + dest="configFile", + action="store", + default=None, + help="configuration filename override", +) def launch(args, expire=0.0): @@ -46,22 +66,21 @@ def launch(args, expire=0.0): configFile = args.configFile configDir = args.configDir - ks = keeping.Keeper(name=name, - base=base, - temp=False, - reopen=True) + ks = keeping.Keeper(name=name, base=base, temp=False, reopen=True) - aeid = ks.gbls.get('aeid') + aeid = ks.gbls.get("aeid") cf = None if aeid is None: if configFile is not None: - cf = configing.Configer(name=configFile, - base=base, - headDirPath=configDir, - temp=False, - reopen=True, - clear=False) + cf = configing.Configer( + name=configFile, + base=base, + headDirPath=configDir, + temp=False, + reopen=True, + clear=False, + ) hby = habbing.Habery(name=name, base=base, bran=bran, cf=cf) else: diff --git a/src/dkr/app/cli/commands/did/webs/generate.py b/src/dkr/app/cli/commands/did/webs/generate.py index fc5eea5..6b535f5 100644 --- a/src/dkr/app/cli/commands/did/webs/generate.py +++ b/src/dkr/app/cli/commands/did/webs/generate.py @@ -20,29 +20,64 @@ from dkr.core import didding from dkr.core import webbing -parser = argparse.ArgumentParser(description='Generate a did:webs DID document and KEL/TEL file') -parser.set_defaults(handler=lambda args: handler(args), - transferable=True) -parser.add_argument('-n', '--name', - action='store', - default="dkr", - help="Name of controller. Default is dkr.") -parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', - required=False, default="") -parser.add_argument('--passcode', help='22 character encryption passcode for keystore (is not saved)', - dest="bran", default=None) # passcode => bran -parser.add_argument("--did", "-d", help="DID to generate (did:webs method)", required=True) +parser = argparse.ArgumentParser( + description="Generate a did:webs DID document and KEL/TEL file" +) +parser.set_defaults(handler=lambda args: handler(args), transferable=True) +parser.add_argument( + "-n", + "--name", + action="store", + default="dkr", + help="Name of controller. Default is dkr.", +) +parser.add_argument( + "--base", + "-b", + help="additional optional prefix to file location of KERI keystore", + required=False, + default="", +) +parser.add_argument( + "--passcode", + help="22 character encryption passcode for keystore (is not saved)", + dest="bran", + default=None, +) # passcode => bran +parser.add_argument( + "--did", "-d", help="DID to generate (did:webs method)", required=True +) # parser.add_argument("--oobi", "-o", help="OOBI to use for resolving the AID", required=False) -parser.add_argument('-da', '--da_reg', - required=False, - default=None, - help="Name of regery to find designated aliases attestation. Default is None.") -parser.add_argument("--meta", "-m", help="Whether to include metadata (True), or only return the DID document (False)", type=bool, required=False, default=False) +parser.add_argument( + "-da", + "--da_reg", + required=False, + default=None, + help="Name of regery to find designated aliases attestation. Default is None.", +) +parser.add_argument( + "--meta", + "-m", + help="Whether to include metadata (True), or only return the DID document (False)", + type=bool, + required=False, + default=False, +) + def handler(args): - gen = Generator(name=args.name, base=args.base, bran=args.bran, did=args.did, oobi=None, da_reg=args.da_reg, meta=args.meta) + gen = Generator( + name=args.name, + base=args.base, + bran=args.bran, + did=args.did, + oobi=None, + da_reg=args.da_reg, + meta=args.meta, + ) return [gen] + class Generator(doing.DoDoer): def __init__(self, name, base, bran, did, oobi, da_reg, meta=False): @@ -57,7 +92,16 @@ def __init__(self, name, base, bran, did, oobi, da_reg, meta=False): # self.oobi = oobi self.da_reg = da_reg self.meta = meta - print("Generate DID document command", did, "using oobi", oobi, "and metadata", meta, "registry name for creds", da_reg) + print( + "Generate DID document command", + did, + "using oobi", + oobi, + "and metadata", + meta, + "registry name for creds", + da_reg, + ) self.toRemove = [hbyDoer] + obl.doers doers = list(self.toRemove) + [doing.doify(self.generate)] @@ -66,11 +110,11 @@ def __init__(self, name, base, bran, did, oobi, da_reg, meta=False): def generate(self, tymth, tock=0.0, **opts): self.wind(tymth) self.tock = tock - _ = (yield self.tock) + _ = yield self.tock domain, port, path, aid = didding.parseDIDWebs(self.did) - msgs = bytearray() + msgs = bytearray() # if self.oobi is not None or self.oobi == "": # print(f"Using oobi {self.oobi} to get CESR event stream") # obr = basing.OobiRecord(date=helping.nowIso8601()) @@ -83,18 +127,18 @@ def generate(self, tymth, tock=0.0, **opts): # roobi = self.hby.db.roobi.get(keys=(self.oobi,)) # _ = yield tock # print(f"OOBI {self.oobi} resolved {roobi}") - + # oobiHab = self.hby.habs[aid] # print(f"Loading hab for OOBI {self.oobi}:\n {oobiHab}") # msgs = oobiHab.replyToOobi(aid=aid, role="controller", eids=None) # print(f"OOBI {self.oobi} CESR event stream {msgs.decode('utf-8')}") - + print(f"Generating CESR event stream data from hab") - #add KEL + # add KEL self.genKelCesr(aid, msgs) - #add designated aliases TELs and ACDCs + # add designated aliases TELs and ACDCs self.genCredCesr(aid, didding.DES_ALIASES_SCHEMA, msgs) - + # Create the directory (and any intermediate directories in the given path) if it doesn't already exist kc_dir_path = f"{aid}" if not os.path.exists(kc_dir_path): @@ -107,23 +151,30 @@ def generate(self, tymth, tock=0.0, **opts): print(f"Writing CESR events to {kc_file_path}: \n{tmsg}") kcf.write(tmsg) - #generate did doc - result = didding.generateDIDDoc(self.hby, did=self.did, aid=aid, oobi=None, reg_name=self.da_reg, meta=self.meta) - + # generate did doc + result = didding.generateDIDDoc( + self.hby, + did=self.did, + aid=aid, + oobi=None, + reg_name=self.da_reg, + meta=self.meta, + ) + diddoc = result - if(self.meta): + if self.meta: diddoc = result["didDocument"] print("Generated metadata for DID document", result["didDocumentMetadata"]) - + # Create the directory (and any intermediate directories in the given path) if it doesn't already exist dd_dir_path = f"{aid}" if not os.path.exists(dd_dir_path): os.makedirs(dd_dir_path) - + dd_file_path = os.path.join(dd_dir_path, f"{webbing.DID_JSON}") ddf = open(dd_file_path, "w") json.dump(didding.toDidWeb(diddoc), ddf) - + kever = self.hby.kevers[aid] # construct the KEL @@ -157,12 +208,7 @@ def generate(self, tymth, tock=0.0, **opts): except ValueError as e: raise e state = kever.state()._asdict() - result = dict( - didDocument=diddoc, - pre=pre, - state=state, - kel=kel - ) + result = dict(didDocument=diddoc, pre=pre, state=state, kel=kel) didData = json.dumps(result, indent=2) print(didData) @@ -173,28 +219,32 @@ def genKelCesr(self, pre: str, msgs: bytearray): print(f"Generating {pre} KEL CESR events") for msg in self.hby.db.clonePreIter(pre=pre): msgs.extend(msg) - + def genTelCesr(self, reger: viring.Reger, regk: str, msgs: bytearray): print(f"Generating {regk} TEL CESR events") for msg in reger.clonePreIter(pre=regk): msgs.extend(msg) - + def genAcdcCesr(self, aid, creder, msgs: bytearray): # print(f"Generating {creder.crd['d']} ACDC CESR events, issued by {creder.crd['i']}") cmsg = self.hby.habs[aid].endorse(creder) msgs.extend(cmsg) - + def genCredCesr(self, aid: str, schema: str, msgs: bytearray): rgy = credentialing.Regery(hby=self.hby, name=self.hby.name, base=self.hby.base) saids = rgy.reger.issus.get(keys=aid) scads = rgy.reger.schms.get(keys=schema.encode("utf-8")) # self-attested, there is no issuee, and schema is designated aliases - saiders = [saider for saider in saids if saider.qb64 in [saider.qb64 for saider in scads]] + saiders = [ + saider + for saider in saids + if saider.qb64 in [saider.qb64 for saider in scads] + ] for saider in saiders: - + creder, *_ = rgy.reger.cloneCred(said=saider.qb64) - + if creder.regi is not None: self.genTelCesr(rgy.reger, creder.regi, msgs) self.genTelCesr(rgy.reger, creder.said, msgs) diff --git a/src/dkr/app/cli/commands/did/webs/resolve.py b/src/dkr/app/cli/commands/did/webs/resolve.py index 4f6ad5a..c9f6a39 100644 --- a/src/dkr/app/cli/commands/did/webs/resolve.py +++ b/src/dkr/app/cli/commands/did/webs/resolve.py @@ -11,19 +11,37 @@ from dkr.core import resolving -parser = argparse.ArgumentParser(description='Resolve a did:webs DID') -parser.set_defaults(handler=lambda args: handler(args), - transferable=True) -parser.add_argument('-n', '--name', - action='store', - default="dkr", - help="Name of controller. Default is dkr.") -parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', - required=False, default="") -parser.add_argument('--passcode', help='22 character encryption passcode for keystore (is not saved)', - dest="bran", default=None) # passcode => bran +parser = argparse.ArgumentParser(description="Resolve a did:webs DID") +parser.set_defaults(handler=lambda args: handler(args), transferable=True) +parser.add_argument( + "-n", + "--name", + action="store", + default="dkr", + help="Name of controller. Default is dkr.", +) +parser.add_argument( + "--base", + "-b", + help="additional optional prefix to file location of KERI keystore", + required=False, + default="", +) +parser.add_argument( + "--passcode", + help="22 character encryption passcode for keystore (is not saved)", + dest="bran", + default=None, +) # passcode => bran parser.add_argument("--did", "-d", help="DID to resolve", required=True) -parser.add_argument("--meta", "-m", help="Whether to include metadata (True), or only return the DID document (False)", type=bool, required=False, default=None) +parser.add_argument( + "--meta", + "-m", + help="Whether to include metadata (True), or only return the DID document (False)", + type=bool, + required=False, + default=None, +) def handler(args): @@ -49,8 +67,8 @@ def __init__(self, hby, hbyDoer, obl, did, meta): def resolve(self, tymth, tock=0.125, **opts): self.wind(tymth) self.tock = tock - _ = (yield self.tock) + _ = yield self.tock resolving.resolve(hby=self.hby, did=self.did, meta=self.meta) - - self.remove(self.toRemove) \ No newline at end of file + + self.remove(self.toRemove) diff --git a/src/dkr/app/cli/commands/did/webs/resolver-service.py b/src/dkr/app/cli/commands/did/webs/resolver-service.py index 9da3c03..ce3acf1 100644 --- a/src/dkr/app/cli/commands/did/webs/resolver-service.py +++ b/src/dkr/app/cli/commands/did/webs/resolver-service.py @@ -10,31 +10,51 @@ from dkr.core import resolving -parser = argparse.ArgumentParser(description='Expose did:webs resolver as an HTTP web service') -parser.set_defaults(handler=lambda args: launch(args), - transferable=True) -parser.add_argument('-p', '--http', - action='store', - default=7677, - help="Port on which to listen for did:webs resolution requests. Defaults to 7677") -parser.add_argument('-n', '--name', - action='store', - default="dkr", - help="Name of controller. Default is dkr.") -parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', - required=False, default="") -parser.add_argument('--passcode', help='22 character encryption passcode for keystore (is not saved)', - dest="bran", default=None) # passcode => bran -parser.add_argument("--config-dir", - "-c", - dest="configDir", - help="directory override for configuration data", - default=None) -parser.add_argument('--config-file', - dest="configFile", - action='store', - default=None, - help="configuration filename override") +parser = argparse.ArgumentParser( + description="Expose did:webs resolver as an HTTP web service" +) +parser.set_defaults(handler=lambda args: launch(args), transferable=True) +parser.add_argument( + "-p", + "--http", + action="store", + default=7677, + help="Port on which to listen for did:webs resolution requests. Defaults to 7677", +) +parser.add_argument( + "-n", + "--name", + action="store", + default="dkr", + help="Name of controller. Default is dkr.", +) +parser.add_argument( + "--base", + "-b", + help="additional optional prefix to file location of KERI keystore", + required=False, + default="", +) +parser.add_argument( + "--passcode", + help="22 character encryption passcode for keystore (is not saved)", + dest="bran", + default=None, +) # passcode => bran +parser.add_argument( + "--config-dir", + "-c", + dest="configDir", + help="directory override for configuration data", + default=None, +) +parser.add_argument( + "--config-file", + dest="configFile", + action="store", + default=None, + help="configuration filename override", +) def launch(args, expire=0.0): @@ -46,22 +66,21 @@ def launch(args, expire=0.0): configFile = args.configFile configDir = args.configDir - ks = keeping.Keeper(name=name, - base=base, - temp=False, - reopen=True) + ks = keeping.Keeper(name=name, base=base, temp=False, reopen=True) - aeid = ks.gbls.get('aeid') + aeid = ks.gbls.get("aeid") cf = None if aeid is None: if configFile is not None: - cf = configing.Configer(name=configFile, - base=base, - headDirPath=configDir, - temp=False, - reopen=True, - clear=False) + cf = configing.Configer( + name=configFile, + base=base, + headDirPath=configDir, + temp=False, + reopen=True, + clear=False, + ) hby = habbing.Habery(name=name, base=base, bran=bran, cf=cf) else: diff --git a/src/dkr/app/cli/commands/did/webs/service.py b/src/dkr/app/cli/commands/did/webs/service.py index 660789d..13fc899 100644 --- a/src/dkr/app/cli/commands/did/webs/service.py +++ b/src/dkr/app/cli/commands/did/webs/service.py @@ -14,31 +14,51 @@ from dkr.core import webbing -parser = argparse.ArgumentParser(description='Launch web server capable of serving KERI AIDs as did:webs and did:web DIDs') -parser.set_defaults(handler=lambda args: launch(args), - transferable=True) -parser.add_argument('-p', '--http', - action='store', - default=7676, - help="Port on which to listen for did:webs requests") -parser.add_argument('-n', '--name', - action='store', - default="dkr", - help="Name of controller. Default is dkr.") -parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', - required=False, default="") -parser.add_argument('--passcode', help='22 character encryption passcode for keystore (is not saved)', - dest="bran", default=None) # passcode => bran -parser.add_argument("--config-dir", - "-c", - dest="configDir", - help="directory override for configuration data", - default=None) -parser.add_argument('--config-file', - dest="configFile", - action='store', - default="dkr", - help="configuration filename override") +parser = argparse.ArgumentParser( + description="Launch web server capable of serving KERI AIDs as did:webs and did:web DIDs" +) +parser.set_defaults(handler=lambda args: launch(args), transferable=True) +parser.add_argument( + "-p", + "--http", + action="store", + default=7676, + help="Port on which to listen for did:webs requests", +) +parser.add_argument( + "-n", + "--name", + action="store", + default="dkr", + help="Name of controller. Default is dkr.", +) +parser.add_argument( + "--base", + "-b", + help="additional optional prefix to file location of KERI keystore", + required=False, + default="", +) +parser.add_argument( + "--passcode", + help="22 character encryption passcode for keystore (is not saved)", + dest="bran", + default=None, +) # passcode => bran +parser.add_argument( + "--config-dir", + "-c", + dest="configDir", + help="directory override for configuration data", + default=None, +) +parser.add_argument( + "--config-file", + dest="configFile", + action="store", + default="dkr", + help="configuration filename override", +) parser.add_argument("--keypath", action="store", required=False, default=None) parser.add_argument("--certpath", action="store", required=False, default=None) parser.add_argument("--cafilepath", action="store", required=False, default=None) @@ -56,19 +76,18 @@ def launch(args): configFile = args.configFile configDir = args.configDir - ks = keeping.Keeper(name=name, - base=base, - temp=False, - reopen=True) + ks = keeping.Keeper(name=name, base=base, temp=False, reopen=True) - aeid = ks.gbls.get('aeid') + aeid = ks.gbls.get("aeid") - cf = configing.Configer(name=configFile, - base=base, - headDirPath=configDir, - temp=False, - reopen=True, - clear=False) + cf = configing.Configer( + name=configFile, + base=base, + headDirPath=configDir, + temp=False, + reopen=True, + clear=False, + ) if aeid is None: print(f"Creating new habery {name} {base} {bran} {cf}") @@ -82,16 +101,20 @@ def launch(args): app = falcon.App( middleware=falcon.CORSMiddleware( - allow_origins='*', - allow_credentials='*', - expose_headers=['cesr-attachment', 'cesr-date', 'content-type'])) + allow_origins="*", + allow_credentials="*", + expose_headers=["cesr-attachment", "cesr-date", "content-type"], + ) + ) if keypath is not None: - servant = hio.core.tcp.ServerTls(certify=False, - keypath=keypath, - certpath=certpath, - cafilepath=cafilepath, - port=httpPort) + servant = hio.core.tcp.ServerTls( + certify=False, + keypath=keypath, + certpath=certpath, + cafilepath=cafilepath, + port=httpPort, + ) else: servant = None @@ -102,5 +125,7 @@ def launch(args): webbing.setup(app, hby=hby, cf=cf) - print(f"Launched web server capable of serving KERI AIDs as did:webs DIDs on: {httpPort}") + print( + f"Launched web server capable of serving KERI AIDs as did:webs DIDs on: {httpPort}" + ) return doers diff --git a/src/dkr/app/cli/dkr.py b/src/dkr/app/cli/dkr.py index 52dd90d..4f2cd10 100644 --- a/src/dkr/app/cli/dkr.py +++ b/src/dkr/app/cli/dkr.py @@ -20,7 +20,7 @@ def main(): parser = multicommand.create_parser(commands) args = parser.parse_args() - if not hasattr(args, 'handler'): + if not hasattr(args, "handler"): parser.print_help() return diff --git a/src/dkr/core/didding.py b/src/dkr/core/didding.py index dace1a2..619e50f 100644 --- a/src/dkr/core/didding.py +++ b/src/dkr/core/didding.py @@ -14,22 +14,26 @@ from keri import kering from keri.app import oobiing, habbing from keri.app.cli.common import terming -from keri.core import coring,scheming +from keri.core import coring, scheming from keri.help import helping from keri.vdr import credentialing, verifying -DID_KERI_RE = re.compile(r'\Adid:keri:(?P[^:]+)\Z', re.IGNORECASE) -DID_WEBS_RE = re.compile(r'\Adid:web(s)?:(?P[^%:]+)(?:%3a(?P\d+))?(?::(?P.+?))?(?::(?P[^:]+))\Z', re.IGNORECASE) +DID_KERI_RE = re.compile(r"\Adid:keri:(?P[^:]+)\Z", re.IGNORECASE) +DID_WEBS_RE = re.compile( + r"\Adid:web(s)?:(?P[^%:]+)(?:%3a(?P\d+))?(?::(?P.+?))?(?::(?P[^:]+))\Z", + re.IGNORECASE, +) DID_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" DID_TIME_PATTERN = re.compile(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z") -DES_ALIASES_SCHEMA="EN6Oh5XSD5_q2Hgu-aqpdfbVepdpYpFlgz6zvJL5b_r5" +DES_ALIASES_SCHEMA = "EN6Oh5XSD5_q2Hgu-aqpdfbVepdpYpFlgz6zvJL5b_r5" + +DID_RES_META_FIELD = "didResolutionMetadata" +DD_META_FIELD = "didDocumentMetadata" +DD_FIELD = "didDocument" +VMETH_FIELD = "verificationMethod" -DID_RES_META_FIELD='didResolutionMetadata' -DD_META_FIELD='didDocumentMetadata' -DD_FIELD='didDocument' -VMETH_FIELD='verificationMethod' def parseDIDKeri(did): match = DID_KERI_RE.match(did) @@ -45,6 +49,7 @@ def parseDIDKeri(did): return aid + def parseDIDWebs(did): match = DID_WEBS_RE.match(did) if match is None: @@ -63,12 +68,23 @@ def parseDIDWebs(did): def generateDIDDoc(hby: habbing.Habery, did, aid, oobi=None, meta=False, reg_name=None): if (did and aid) and not did.endswith(aid): raise ValueError(f"{did} does not end with {aid}") - print("Generating DID document for", did, "with aid", aid, "using oobi", oobi, "and metadata", meta, "registry name for creds", reg_name) - + print( + "Generating DID document for", + did, + "with aid", + aid, + "using oobi", + oobi, + "and metadata", + meta, + "registry name for creds", + reg_name, + ) + hab = None if aid in hby.habs: hab = hby.habs[aid] - + if oobi is not None: obr = hby.db.roobi.get(keys=(oobi,)) if obr is None or obr.state == oobiing.Result.failed: @@ -80,76 +96,77 @@ def generateDIDDoc(hby: habbing.Habery, did, aid, oobi=None, meta=False, reg_nam if aid in hby.kevers: kever = hby.kevers[aid] else: - print(f"Habery does not have a kever for {did}. Did you parse the keri.cesr file?") + print( + f"Habery does not have a kever for {did}. Did you parse the keri.cesr file?" + ) for kev in hby.kevers: print("Known kevers: ", kev) hby.kevers[aid] - + vms = [] for idx, verfer in enumerate(kever.verfers): kid = verfer.qb64 - x = urlsafe_b64encode(verfer.raw).rstrip(b'=').decode('utf-8') - vms.append(dict( - id=f"#{verfer.qb64}", - type="JsonWebKey", - controller=did, - publicKeyJwk=dict( - kid=f"{kid}", - kty="OKP", - crv="Ed25519", - x=f"{x}" + x = urlsafe_b64encode(verfer.raw).rstrip(b"=").decode("utf-8") + vms.append( + dict( + id=f"#{verfer.qb64}", + type="JsonWebKey", + controller=did, + publicKeyJwk=dict(kid=f"{kid}", kty="OKP", crv="Ed25519", x=f"{x}"), ) - )) + ) if isinstance(kever.tholder.thold, int): if kever.tholder.thold > 1: conditions = [vm.get("id") for vm in vms] - vms.append(dict( - id=f"#{aid}", - type="ConditionalProof2022", - controller=did, - threshold=kever.tholder.thold, - conditionThreshold=conditions - )) + vms.append( + dict( + id=f"#{aid}", + type="ConditionalProof2022", + controller=did, + threshold=kever.tholder.thold, + conditionThreshold=conditions, + ) + ) elif isinstance(kever.tholder.thold, list): lcd = int(math.lcm(*[fr.denominator for fr in kever.tholder.thold[0]])) - threshold = float(lcd/2) - numerators = [int(fr.numerator * lcd / fr.denominator) for fr in kever.tholder.thold[0]] + threshold = float(lcd / 2) + numerators = [ + int(fr.numerator * lcd / fr.denominator) for fr in kever.tholder.thold[0] + ] conditions = [] for idx, verfer in enumerate(kever.verfers): - conditions.append(dict( - condition=vms[idx]['id'], - weight=numerators[idx] - )) - vms.append(dict( - id=f"#{aid}", - type="ConditionalProof2022", - controller=did, - threshold=threshold, - conditionWeightedThreshold=conditions - )) - - x = [(keys[1], loc.url) for keys, loc in - hby.db.locs.getItemIter(keys=(aid,)) if loc.url] + conditions.append(dict(condition=vms[idx]["id"], weight=numerators[idx])) + vms.append( + dict( + id=f"#{aid}", + type="ConditionalProof2022", + controller=did, + threshold=threshold, + conditionWeightedThreshold=conditions, + ) + ) + + x = [ + (keys[1], loc.url) + for keys, loc in hby.db.locs.getItemIter(keys=(aid,)) + if loc.url + ] witnesses = [] for idx, eid in enumerate(kever.wits): keys = (eid,) for (tid, scheme), loc in hby.db.locs.getItemIter(keys): - witnesses.append(dict( - idx=idx, - scheme=scheme, - url=loc.url - )) - - sEnds=[] + witnesses.append(dict(idx=idx, scheme=scheme, url=loc.url)) + + sEnds = [] # hab.fetchRoleUrls(hab.pre).get("controller").get("EGadHcyW9IfVIPrFUAa_I0z4dF8QzQAvUvfaUTJk8Jre").get("http") == "http://127.0.0.1:7777" - if hab and hasattr(hab, 'fetchRoleUrls'): + if hab and hasattr(hab, "fetchRoleUrls"): ends = hab.fetchRoleUrls(aid) sEnds.extend(addEnds(ends)) ends = hab.fetchWitnessUrls(aid) sEnds.extend(addEnds(ends)) - + # similar to kli vc list --name "$alias" --alias "$alias" --issued --said --schema "${d_alias_schema}") eq_ids = [] aka_ids = [] @@ -158,49 +175,51 @@ def generateDIDDoc(hby: habbing.Habery, did, aid, oobi=None, meta=False, reg_nam dws_pre = "did:webs" eq_ids = [s for s in da_ids if s.startswith(dws_pre)] print(f"Equivalent DIDs: {eq_ids}") - + aka_ids = [s for s in da_ids] print(f"Also Known As DIDs: {aka_ids}") - + didResolutionMetadata = dict( contentType="application/did+json", - retrieved=datetime.datetime.now(datetime.UTC).strftime(DID_TIME_FORMAT) + retrieved=datetime.datetime.now(datetime.UTC).strftime(DID_TIME_FORMAT), ) didDocumentMetadata = dict( witnesses=witnesses, versionId=f"{kever.sner.num}", equivalentId=eq_ids, ) - diddoc = dict( - id=did, - verificationMethod=vms, - service=sEnds, - alsoKnownAs=aka_ids - ) + diddoc = dict(id=did, verificationMethod=vms, service=sEnds, alsoKnownAs=aka_ids) if meta is True: resolutionResult = dict( didDocument=diddoc, didResolutionMetadata=didResolutionMetadata, - didDocumentMetadata=didDocumentMetadata + didDocumentMetadata=didDocumentMetadata, ) return resolutionResult else: return diddoc + def toDidWeb(diddoc): - diddoc['id'] = diddoc['id'].replace('did:webs', 'did:web') + diddoc["id"] = diddoc["id"].replace("did:webs", "did:web") for verificationMethod in diddoc[VMETH_FIELD]: - verificationMethod['controller'] = verificationMethod['controller'].replace('did:webs', 'did:web') + verificationMethod["controller"] = verificationMethod["controller"].replace( + "did:webs", "did:web" + ) return diddoc + def fromDidWeb(diddoc): - diddoc['id'] = diddoc['id'].replace('did:web', 'did:webs') + diddoc["id"] = diddoc["id"].replace("did:web", "did:webs") for verificationMethod in diddoc[VMETH_FIELD]: - verificationMethod['controller'] = verificationMethod['controller'].replace('did:web', 'did:webs') + verificationMethod["controller"] = verificationMethod["controller"].replace( + "did:web", "did:webs" + ) return diddoc -def desAliases(hby: habbing.Habery, aid: str, reg_name: str=None): + +def desAliases(hby: habbing.Habery, aid: str, reg_name: str = None): """ Returns the credentialer for the des-aliases schema, or None if it doesn't exist. """ @@ -210,28 +229,36 @@ def desAliases(hby: habbing.Habery, aid: str, reg_name: str=None): reg_name = hby.habs[aid].name rgy = credentialing.Regery(hby=hby, name=reg_name) vry = verifying.Verifier(hby=hby, reger=rgy.reger) - + saids = rgy.reger.issus.get(keys=aid) scads = rgy.reger.schms.get(keys=DES_ALIASES_SCHEMA.encode("utf-8")) # self-attested, there is no issuee, and schmea is designated aliases - saids = [saider for saider in saids if saider.qb64 in [saider.qb64 for saider in scads]] + saids = [ + saider + for saider in saids + if saider.qb64 in [saider.qb64 for saider in scads] + ] # for saider in saiders: - creds = rgy.reger.cloneCreds(saids,hby.habs[aid].db) + creds = rgy.reger.cloneCreds(saids, hby.habs[aid].db) for idx, cred in enumerate(creds): - sad = cred['sad'] + sad = cred["sad"] status = cred["status"] - schema = sad['s'] + schema = sad["s"] scraw = vry.resolver.resolve(schema) schemer = scheming.Schemer(raw=scraw) print(f"Credential #{idx+1}: {sad['d']}") print(f" Type: {schemer.sed['title']}") - if status['et'] == 'iss' or status['et'] == 'bis': - print(f" Status: Issued {terming.Colors.OKGREEN}{terming.Symbols.CHECKMARK}{terming.Colors.ENDC}") - da_ids = sad['a']['ids'] - elif status['et'] == 'rev' or status['et'] == 'brv': - print(f" Status: Revoked {terming.Colors.FAIL}{terming.Symbols.FAILED}{terming.Colors.ENDC}") + if status["et"] == "iss" or status["et"] == "bis": + print( + f" Status: Issued {terming.Colors.OKGREEN}{terming.Symbols.CHECKMARK}{terming.Colors.ENDC}" + ) + da_ids = sad["a"]["ids"] + elif status["et"] == "rev" or status["et"] == "brv": + print( + f" Status: Revoked {terming.Colors.FAIL}{terming.Symbols.FAILED}{terming.Colors.ENDC}" + ) else: print(f" Status: Unknown") print(f" Issued by {sad['i']}") @@ -239,6 +266,7 @@ def desAliases(hby: habbing.Habery, aid: str, reg_name: str=None): return da_ids + def addEnds(ends): # wurls = hab.fetchWitnessUrls(hab.pre) # wwits = wurls.getall("witness") @@ -247,8 +275,8 @@ def addEnds(ends): # wwit2 = wwits[1] # wse2 = wwit2.get("BAjTuhnzPDB0oU0qHXACnvzachJpYjUAtH1N9Tsb_MdE") # assert wse2.get("http") == "http://127.0.0.1:9999" - - sEnds=list() + + sEnds = list() for role in ends: rList = ends.getall(role) for eList in rList: @@ -257,12 +285,8 @@ def addEnds(ends): sDict = dict() for proto in val: host = val[proto] - sDict[proto]=f"{host}" - v = dict( - id=f"#{eid}/{role}", - type=role, - serviceEndpoint=sDict - ) + sDict[proto] = f"{host}" + v = dict(id=f"#{eid}/{role}", type=role, serviceEndpoint=sDict) if v not in sEnds: sEnds.append(v) return sEnds diff --git a/src/dkr/didcomm/hello-world.py b/src/dkr/didcomm/hello-world.py index 915137a..2328278 100644 --- a/src/dkr/didcomm/hello-world.py +++ b/src/dkr/didcomm/hello-world.py @@ -1,4 +1,9 @@ -from utils import createKeriDid, SecretsResolverInMemory, DidKeriResolver, validateLongDid +from utils import ( + createKeriDid, + SecretsResolverInMemory, + DidKeriResolver, + validateLongDid, +) from didcomm.message import Message from didcomm.unpack import unpack from didcomm.common.resolvers import ResolversConfig @@ -7,90 +12,98 @@ import json alice = createKeriDid() -print("Alice's DID:", alice['did']) -print("Alice's Long DID:", alice['long_did'],"\n") +print("Alice's DID:", alice["did"]) +print("Alice's Long DID:", alice["long_did"], "\n") bob = createKeriDid() -print("Bob's DID:", bob['did']) -print("Bob's Long DID:", bob['long_did'],"\n") +print("Bob's DID:", bob["did"]) +print("Bob's Long DID:", bob["long_did"], "\n") -print("Compare length with Peer DID: did:peer:2.Vz6MkfiT7uT2EQnuNhGP2xxNsh2v7seoV3fzZWRpydJnF3K6z.Ez6LSfpsWUKP7g4LGTpXFPWZzThQtG1VuQqxtToKYtkXdRdc8.SeyJpZCI6IiNzZXJ2aWNlLTEiLCJ0IjoiZG0iLCJzIjoiZGlkOnBlZXI6Mi5FejZMU2U3U3FCUmJmWEdFNXJpVEZYYU5zZ2dWUFB6YThtNXdyR21ON0dRY0d5dHI2LlZ6Nk1ra3dmNWhWcUJVYXhFU3YxVHhra0pIQWNKRldnTXROY1g2Q1pyRkZpZllNQTkuU2V5SnBaQ0k2SW01bGR5MXBaQ0lzSW5RaU9pSmtiU0lzSW5NaU9pSm9kSFJ3Y3pvdkwyMWxaR2xoZEc5eUxuSnZiM1J6YVdRdVkyeHZkV1FpTENKaElqcGJJbVJwWkdOdmJXMHZkaklpWFgwIn","\n") +print( + "Compare length with Peer DID: did:peer:2.Vz6MkfiT7uT2EQnuNhGP2xxNsh2v7seoV3fzZWRpydJnF3K6z.Ez6LSfpsWUKP7g4LGTpXFPWZzThQtG1VuQqxtToKYtkXdRdc8.SeyJpZCI6IiNzZXJ2aWNlLTEiLCJ0IjoiZG0iLCJzIjoiZGlkOnBlZXI6Mi5FejZMU2U3U3FCUmJmWEdFNXJpVEZYYU5zZ2dWUFB6YThtNXdyR21ON0dRY0d5dHI2LlZ6Nk1ra3dmNWhWcUJVYXhFU3YxVHhra0pIQWNKRldnTXROY1g2Q1pyRkZpZllNQTkuU2V5SnBaQ0k2SW01bGR5MXBaQ0lzSW5RaU9pSmtiU0lzSW5NaU9pSm9kSFJ3Y3pvdkwyMWxaR2xoZEc5eUxuSnZiM1J6YVdRdVkyeHZkV1FpTENKaElqcGJJbVJwWkdOdmJXMHZkaklpWFgwIn", + "\n", +) -print("Alice's long DID validation:", validateLongDid(alice['long_did'])) -print("Bob's long DID validation:", validateLongDid(bob['long_did']),"\n") +print("Alice's long DID validation:", validateLongDid(alice["long_did"])) +print("Bob's long DID validation:", validateLongDid(bob["long_did"]), "\n") -store = { - alice['did']: alice, - bob['did']: bob -} +store = {alice["did"]: alice, bob["did"]: bob} secrets_resolver = SecretsResolverInMemory(store) did_resolver = DidKeriResolver(store) # Alice creates a basic message -alice_message = Message( - id = "123", - type = "https://didcomm.org/basicmessage/2.0/message", - body = {'content': 'Hello Bob!'}, +alice_message = Message( + id="123", + type="https://didcomm.org/basicmessage/2.0/message", + body={"content": "Hello Bob!"}, ) -print('1-Alice creates a basic message:',alice_message.body,"\n") +print("1-Alice creates a basic message:", alice_message.body, "\n") # Alice encrypts the message for Bob -alice_message_packed = asyncio.run( pack_encrypted( - resolvers_config = ResolversConfig( - secrets_resolver = secrets_resolver, - did_resolver = did_resolver - ), - message = alice_message, - frm = alice['long_did'], - to = bob['long_did'], - sign_frm = None, - pack_config = PackEncryptedConfig(protect_sender_id=False) -)) -print('2-Alice encrypts the message for Bob:') -print(alice_message_packed.packed_msg,"\n") +alice_message_packed = asyncio.run( + pack_encrypted( + resolvers_config=ResolversConfig( + secrets_resolver=secrets_resolver, did_resolver=did_resolver + ), + message=alice_message, + frm=alice["long_did"], + to=bob["long_did"], + sign_frm=None, + pack_config=PackEncryptedConfig(protect_sender_id=False), + ) +) +print("2-Alice encrypts the message for Bob:") +print(alice_message_packed.packed_msg, "\n") # Bob decrypts the message -bob_message_unpacked = asyncio.run( unpack( - resolvers_config=ResolversConfig( - secrets_resolver=secrets_resolver, - did_resolver=did_resolver - ), - packed_msg= alice_message_packed.packed_msg -)) -print('3-Bob decrypts the message:', bob_message_unpacked.message.body,"\n") +bob_message_unpacked = asyncio.run( + unpack( + resolvers_config=ResolversConfig( + secrets_resolver=secrets_resolver, did_resolver=did_resolver + ), + packed_msg=alice_message_packed.packed_msg, + ) +) +print("3-Bob decrypts the message:", bob_message_unpacked.message.body, "\n") # Bob creates a basic message response -bob_message = Message( - id = "124", - type = "https://didcomm.org/basicmessage/2.0/message", - body = {'content': 'Hello Alice!'}, +bob_message = Message( + id="124", + type="https://didcomm.org/basicmessage/2.0/message", + body={"content": "Hello Alice!"}, ) -print('4-Bob creates a response using short DIDs:',bob_message.body,"\n") +print("4-Bob creates a response using short DIDs:", bob_message.body, "\n") # Bob encrypts the message for Alice -bob_message_packed = asyncio.run( pack_encrypted( - resolvers_config = ResolversConfig( - secrets_resolver = secrets_resolver, - did_resolver = did_resolver - ), - message = bob_message, - frm = bob['did'], - to = alice['did'], - sign_frm = bob['did'], - pack_config = PackEncryptedConfig(protect_sender_id=False) -)) -print('5-Bob encrypts and sign the message for Alice:') -print(bob_message_packed.packed_msg,"\n") +bob_message_packed = asyncio.run( + pack_encrypted( + resolvers_config=ResolversConfig( + secrets_resolver=secrets_resolver, did_resolver=did_resolver + ), + message=bob_message, + frm=bob["did"], + to=alice["did"], + sign_frm=bob["did"], + pack_config=PackEncryptedConfig(protect_sender_id=False), + ) +) +print("5-Bob encrypts and sign the message for Alice:") +print(bob_message_packed.packed_msg, "\n") # Alice decrypts the message -alice_message_unpacked = asyncio.run( unpack( - resolvers_config=ResolversConfig( - secrets_resolver=secrets_resolver, - did_resolver=did_resolver - ), - packed_msg= bob_message_packed.packed_msg -)) -print('6-Alice decrypts the message with short DIDs:', alice_message_unpacked.message.body,"\n") +alice_message_unpacked = asyncio.run( + unpack( + resolvers_config=ResolversConfig( + secrets_resolver=secrets_resolver, did_resolver=did_resolver + ), + packed_msg=bob_message_packed.packed_msg, + ) +) +print( + "6-Alice decrypts the message with short DIDs:", + alice_message_unpacked.message.body, + "\n", +) -print(asyncio.run(did_resolver.resolve(alice['did']))) +print(asyncio.run(did_resolver.resolve(alice["did"]))) diff --git a/src/dkr/didcomm/utils.py b/src/dkr/didcomm/utils.py index d456728..2f25e07 100644 --- a/src/dkr/didcomm/utils.py +++ b/src/dkr/didcomm/utils.py @@ -1,10 +1,15 @@ from keri.core import eventing, coring -from didcomm.common.types import DID, VerificationMethodType, VerificationMaterial, VerificationMaterialFormat +from didcomm.common.types import ( + DID, + VerificationMethodType, + VerificationMaterial, + VerificationMaterialFormat, +) from didcomm.common.resolvers import SecretsResolver from didcomm.did_doc.did_doc import DIDDoc, VerificationMethod, DIDCommService from didcomm.did_doc.did_resolver import DIDResolver -from didcomm.secrets.secrets_resolver_demo import Secret +from didcomm.secrets.secrets_resolver_demo import Secret from typing import Optional, List @@ -14,13 +19,14 @@ from pprint import pp -''' +""" Utilities for DIDComm packing and unpacking using did:keri as alternative to Peer DID - Use SICPA didcomm-python library - Authcryypt message only - AID is Ed25519 and derive X25519 key pair from same private key - Transferable AID but with no next key that makes it non transferable (no key rotations) -''' +""" + def createKeriDid(): salt = coring.Salter() @@ -28,148 +34,154 @@ def createKeriDid(): X25519_pubkey = pysodium.crypto_sign_pk_to_box_pk(signerEd25519.verfer.raw) # Manual CESR coding - X25519_pubkey_qb64 = 'C'+ (base64.urlsafe_b64encode(bytes([0]) + X25519_pubkey).decode('utf-8'))[1:] + X25519_pubkey_qb64 = ( + "C" + (base64.urlsafe_b64encode(bytes([0]) + X25519_pubkey).decode("utf-8"))[1:] + ) # Or using karipy - X25519_pubkey_qb64 = coring.Matter(raw = X25519_pubkey, code=coring.MtrDex.X25519).qb64 + X25519_pubkey_qb64 = coring.Matter( + raw=X25519_pubkey, code=coring.MtrDex.X25519 + ).qb64 serder = eventing.incept( - keys=[signerEd25519.verfer.qb64], - data=[ - {"e":X25519_pubkey_qb64}, - {"se": "https://example.coom/"} - ], - code=coring.MtrDex.Blake3_256 # code is for self-addressing + keys=[signerEd25519.verfer.qb64], + data=[{"e": X25519_pubkey_qb64}, {"se": "https://example.coom/"}], + code=coring.MtrDex.Blake3_256, # code is for self-addressing ) - did = 'did:keri:'+serder.ked['i'] - kelb64 = base64.urlsafe_b64encode(bytes(json.dumps(serder.ked), 'utf-8')).decode('utf-8') - long_did = did+'?icp='+kelb64 + did = "did:keri:" + serder.ked["i"] + kelb64 = base64.urlsafe_b64encode(bytes(json.dumps(serder.ked), "utf-8")).decode( + "utf-8" + ) + long_did = did + "?icp=" + kelb64 # pp(serder.ked) - return { - 'did': did, - 'long_did': long_did, - 'signer': signerEd25519 - } + return {"did": did, "long_did": long_did, "signer": signerEd25519} + def validateLongDid(long_did): # TODO validate URL and make parsing safer - did = long_did.split('?')[0] - kelb64 = long_did.split('=')[1]+"==" + did = long_did.split("?")[0] + kelb64 = long_did.split("=")[1] + "==" kel_decoded = json.loads(base64.urlsafe_b64decode(kelb64)) prefixer = coring.Prefixer(ked=kel_decoded) - return prefixer.qb64b.decode("utf-8") == did.split(':')[2] + return prefixer.qb64b.decode("utf-8") == did.split(":")[2] + class SecretsResolverInMemory(SecretsResolver): def __init__(self, store: dict): self._store = store async def get_key(self, kid: str) -> Optional[Secret]: - - did, kident = kid.split('#') - signer = self._store[did]['signer'] + did, kident = kid.split("#") + + signer = self._store[did]["signer"] X25519_pubkey = pysodium.crypto_sign_pk_to_box_pk(signer.verfer.raw) - X25519_pubkey_b64 = base64.urlsafe_b64encode(X25519_pubkey).decode('utf-8') - X25519_prikey = pysodium.crypto_sign_sk_to_box_sk(signer.raw + signer.verfer.raw) - X25519_prikey_b64 = base64.urlsafe_b64encode(X25519_prikey).decode('utf-8') + X25519_pubkey_b64 = base64.urlsafe_b64encode(X25519_pubkey).decode("utf-8") + X25519_prikey = pysodium.crypto_sign_sk_to_box_sk( + signer.raw + signer.verfer.raw + ) + X25519_prikey_b64 = base64.urlsafe_b64encode(X25519_prikey).decode("utf-8") Ed25519_pubkey_raw = signer.verfer.raw - Ed25519_pubkey_b64 = base64.urlsafe_b64encode(Ed25519_pubkey_raw).decode('utf-8') - + Ed25519_pubkey_b64 = base64.urlsafe_b64encode(Ed25519_pubkey_raw).decode( + "utf-8" + ) + Ed25519_prikey_raw = signer.raw - Ed25519_prikey_b64 = base64.urlsafe_b64encode(Ed25519_prikey_raw).decode('utf-8') + Ed25519_prikey_b64 = base64.urlsafe_b64encode(Ed25519_prikey_raw).decode( + "utf-8" + ) secret = Secret( - kid= kid, - type= VerificationMethodType.JSON_WEB_KEY_2020, - verification_material= VerificationMaterial( - format=VerificationMaterialFormat.JWK, - value= json.dumps( - { - 'kty': 'OKP', - 'crv': 'X25519', - 'd': X25519_prikey_b64, - 'x': X25519_pubkey_b64, - 'kid': kid - } if kident == "key-1" else - { - 'kty': 'OKP', - 'crv': 'Ed25519', - 'd': Ed25519_prikey_b64, - 'x': Ed25519_pubkey_b64, - 'kid': kid - } - ) - ) - ) + kid=kid, + type=VerificationMethodType.JSON_WEB_KEY_2020, + verification_material=VerificationMaterial( + format=VerificationMaterialFormat.JWK, + value=json.dumps( + { + "kty": "OKP", + "crv": "X25519", + "d": X25519_prikey_b64, + "x": X25519_pubkey_b64, + "kid": kid, + } + if kident == "key-1" + else { + "kty": "OKP", + "crv": "Ed25519", + "d": Ed25519_prikey_b64, + "x": Ed25519_pubkey_b64, + "kid": kid, + } + ), + ), + ) return secret async def get_keys(self, kids: List[str]) -> List[str]: return kids + class DidKeriResolver(DIDResolver): def __init__(self, store: dict): self._store = store + async def resolve(self, did: DID) -> DIDDoc: # TODO validate URL and make parsing safer - short_did = did.split('?')[0] - if len(did.split('=')) > 1: - kelb64 = did.split('=')[1]+"==" + short_did = did.split("?")[0] + if len(did.split("=")) > 1: + kelb64 = did.split("=")[1] + "==" ked = json.loads(base64.urlsafe_b64decode(kelb64)) - self._store[short_did]['ked'] = ked + self._store[short_did]["ked"] = ked else: - ked = self._store[short_did]['ked'] + ked = self._store[short_did]["ked"] # Manual CESR Decoding - ed25519_pubkey_qb64 = ked['k'][0] + ed25519_pubkey_qb64 = ked["k"][0] ed25519_pubkey_b64 = "A" + ed25519_pubkey_qb64[1:] ed25519_pubkey_raw = base64.urlsafe_b64decode(ed25519_pubkey_b64)[1:] - x1 = base64.urlsafe_b64encode(ed25519_pubkey_raw).decode('utf-8') + x1 = base64.urlsafe_b64encode(ed25519_pubkey_raw).decode("utf-8") # Or using keripy: - x1 = base64.urlsafe_b64encode(coring.Matter(qb64=ked['k'][0]).raw).decode('utf-8') + x1 = base64.urlsafe_b64encode(coring.Matter(qb64=ked["k"][0]).raw).decode( + "utf-8" + ) - x2 = base64.urlsafe_b64encode(coring.Matter(qb64=ked['a'][0]['e']).raw).decode('utf-8') + x2 = base64.urlsafe_b64encode(coring.Matter(qb64=ked["a"][0]["e"]).raw).decode( + "utf-8" + ) return DIDDoc( did=did, - key_agreement_kids = [short_did+'#key-1'], - authentication_kids = [short_did+'#key-2'], - verification_methods = [ + key_agreement_kids=[short_did + "#key-1"], + authentication_kids=[short_did + "#key-2"], + verification_methods=[ VerificationMethod( - id = short_did+'#key-1', - type = VerificationMethodType.JSON_WEB_KEY_2020, - controller = did, - verification_material = VerificationMaterial( - format = VerificationMaterialFormat.JWK, - value = json.dumps({ - 'kty': 'OKP', - 'crv': 'X25519', - 'x': x2 - }) - ) + id=short_did + "#key-1", + type=VerificationMethodType.JSON_WEB_KEY_2020, + controller=did, + verification_material=VerificationMaterial( + format=VerificationMaterialFormat.JWK, + value=json.dumps({"kty": "OKP", "crv": "X25519", "x": x2}), + ), ), VerificationMethod( - id = short_did+'#key-2', - type = VerificationMethodType.JSON_WEB_KEY_2020, - controller = did, - verification_material = VerificationMaterial( - format = VerificationMaterialFormat.JWK, - value = json.dumps({ - 'kty': 'OKP', - 'crv': 'Ed25519', - 'x': x1 - }) - ) - ) + id=short_did + "#key-2", + type=VerificationMethodType.JSON_WEB_KEY_2020, + controller=did, + verification_material=VerificationMaterial( + format=VerificationMaterialFormat.JWK, + value=json.dumps({"kty": "OKP", "crv": "Ed25519", "x": x1}), + ), + ), ], - didcomm_services = [ + didcomm_services=[ DIDCommService( - id='endpoint-1', - service_endpoint=ked['a'][1]['se'], + id="endpoint-1", + service_endpoint=ked["a"][1]["se"], routing_keys=[], - accept=["didcomm/v2"] + accept=["didcomm/v2"], ) - ] - ) \ No newline at end of file + ], + ) diff --git a/tests/dkr/app/cli/commands/did/webs/test_resolve.py b/tests/dkr/app/cli/commands/did/webs/test_resolve.py index d43ca36..179418d 100644 --- a/tests/dkr/app/cli/commands/did/webs/test_resolve.py +++ b/tests/dkr/app/cli/commands/did/webs/test_resolve.py @@ -16,15 +16,15 @@ import queue import threading import time - + + class PingResource: - def on_get(self, req, resp): - """Handles GET requests""" - resp.status = falcon.HTTP_200 - resp.content_type = falcon.MEDIA_TEXT - resp.text = ( - 'Pong' - ) + def on_get(self, req, resp): + """Handles GET requests""" + resp.status = falcon.HTTP_200 + resp.content_type = falcon.MEDIA_TEXT + resp.text = "Pong" + # @pytest.mark.timeout(60) # def test_resolver(): @@ -78,7 +78,7 @@ def on_get(self, req, resp): # ptres = queue.Queue() # pt = threading.Thread(target=resolving.loadUrl, args=(purl,ptres)) # pt.start() - + # ddstat = None # ddtres = queue.Queue() # ddt = threading.Thread(target=resolving.loadUrl, args=(ddurl,ddtres)) @@ -86,12 +86,12 @@ def on_get(self, req, resp): # time.sleep(1) # doist.recur() - + # kcstat = None # kctres = queue.Queue() # kct = threading.Thread(target=resolving.loadUrl, args=(kcurl,kctres)) # kct.start() - + # time.sleep(2) # doist.recur() @@ -99,12 +99,12 @@ def on_get(self, req, resp): # pstat = resp.status_code # assert pstat == 200 # print("Got example response content", resp.content) - + # resp = ddtres.get() # ddstat = resp.status_code # assert ddstat == 200 # print("Got dd response content", resp.content) - + # resp = kctres.get() # kcstat = resp.status_code # assert kcstat == 200 @@ -122,28 +122,28 @@ def on_get(self, req, resp): # time.sleep(2) # doist.recur() - + # mid_dd = rtres.get() # print("\nGot resolve dd response",mid_dd) # time.sleep(2) # doist.recur() - + # mid_kc = rtres.get() # print("\nGot resolve kc response",mid_kc) # time.sleep(2) # doist.recur() - + # raid = rtres.get() # print("\nGot resolve aid response",raid) # assert raid == aid - + # did_web_dd = resolving.loadJsonFile(f"./volume/dkr/pages/{aid}/did.json") # rdd = rtres.get() # print("\nGot resolve dd response",rdd) # assert json.loads(rdd.content) == did_web_dd - + # rkc_expected = resolving.loadFile(f"./volume/dkr/pages/{aid}/keri.cesr") # rkc_expected, sig_exp = resolving.splitCesr(rkc_expected.decode(), '}') # rkc_exp_json = json.loads(rkc_expected) @@ -153,15 +153,15 @@ def on_get(self, req, resp): # # double the json.loads calls to compensate for the quote escaping? # json_no_sig = json.loads(str_no_sig) # assert json_no_sig == rkc_exp_json - + # if not rtres.empty(): # assert False, "Expected no more responses" - + # assert aid not in vhby.kevers # resolving.saveCesr(hby=vhby,kc_res=rkc, aid=aid) # assert aid in vhby.kevers -# dd, dd_actual = resolving.getComp(hby=vhby, did=did_webs, aid=aid, dd_res=rdd, kc_res=rkc) +# dd, dd_actual = resolving.getComp(hby=vhby, did=did_webs, aid=aid, dd_res=rdd, kc_res=rkc) # assert dd[didding.DD_FIELD][didding.VMETH_FIELD] != did_web_dd[didding.VMETH_FIELD] # assert dd[didding.DD_FIELD][didding.VMETH_FIELD] == dd_actual[didding.VMETH_FIELD] @@ -179,7 +179,7 @@ def on_get(self, req, resp): # dd_actual_bad[didding.VMETH_FIELD][0]["id"] = dd_actual_bad[didding.VMETH_FIELD][0]["id"][:-1] # vresult = resolving.verify(dd, dd_actual_bad, meta=True) # assert vresult[didding.DID_RES_META_FIELD]['error'] == 'notVerified' - + # # TODO test services, alsoKnownAs, etc. # # TODO test a resolution failure @@ -190,12 +190,13 @@ def on_get(self, req, resp): # doist.exit() # """Done Test""" - + + class HandleCORS(object): def process_request(self, req, resp): - resp.set_header('Access-Control-Allow-Origin', '*') - resp.set_header('Access-Control-Allow-Methods', '*') - resp.set_header('Access-Control-Allow-Headers', '*') - resp.set_header('Access-Control-Max-Age', 1728000) # 20 days - if req.method == 'OPTIONS': - raise http_status.HTTPStatus(falcon.HTTP_200, text='\n') \ No newline at end of file + resp.set_header("Access-Control-Allow-Origin", "*") + resp.set_header("Access-Control-Allow-Methods", "*") + resp.set_header("Access-Control-Allow-Headers", "*") + resp.set_header("Access-Control-Max-Age", 1728000) # 20 days + if req.method == "OPTIONS": + raise http_status.HTTPStatus(falcon.HTTP_200, text="\n") diff --git a/tests/dkr/core/test_webbing.py b/tests/dkr/core/test_webbing.py index 8f6ee91..042d326 100644 --- a/tests/dkr/core/test_webbing.py +++ b/tests/dkr/core/test_webbing.py @@ -1,6 +1,7 @@ import json import os import sys + sys.path.append(os.path.join(os.path.dirname(__file__))) from common import setup_habs from dkr.core import didding, resolving, webbing @@ -18,25 +19,25 @@ import queue import threading import time - + + class PingResource: - def on_get(self, req, resp): - """Handles GET requests""" - resp.status = falcon.HTTP_200 - resp.content_type = falcon.MEDIA_TEXT - resp.text = ( - 'Pong' - ) - + def on_get(self, req, resp): + """Handles GET requests""" + resp.status = falcon.HTTP_200 + resp.content_type = falcon.MEDIA_TEXT + resp.text = "Pong" + + # @pytest.mark.timeout(60) # def test_service(setup_habs): # port = 7676 - + # with habbing.openHby(name="service") as shby: # hab = shby.makeHab(name="service") # aid = "ELCUOZXs-0xn3jOihm0AJ-L8XTFVT8SnIpmEDhFF9Kz_" # did = f"did:web:127.0.0.1%3a{port}:{aid}" - + # print("Current working dir", os.getcwd()) # cf = configing.Configer(name="config-test", # headDirPath="./volume/dkr/examples/my-scripts", @@ -79,17 +80,17 @@ def on_get(self, req, resp): # ptres = queue.Queue() # pt = threading.Thread(target=resolving.loadUrl, args=(purl,ptres)) # pt.start() - + # ddstat = None # ddtres = queue.Queue() # ddt = threading.Thread(target=resolving.loadUrl, args=(ddurl,ddtres)) # ddt.start() - + # kcstat = None # kctres = queue.Queue() # kct = threading.Thread(target=resolving.loadUrl, args=(kcurl,kctres)) # kct.start() - + # while pstat == None or ddtres == None or kctres == None: # time.sleep(2) # doist.recur() @@ -98,17 +99,17 @@ def on_get(self, req, resp): # pstat = resp.status_code # assert pstat == 200 # print("Got ping response content", resp.content) - + # resp = ddtres.get() # ddstat = resp.status_code # assert ddstat == 200 # print("Got dd response content", resp.content) - + # resp = kctres.get() # kcstat = resp.status_code # assert kcstat == 200 # print("Got kc response content", resp.content) - + # ohby, ohab, wesHby, wesHab = setup_habs # odid = f"did:web:127.0.0.1%3a{port}:{ohab.pre}" # didDoc = didding.generateDIDDoc(ohby, odid, ohab.pre, oobi=None, metadata=False) @@ -122,32 +123,32 @@ def on_get(self, req, resp): # print(f"Writing test did:webs for {webbing.DID_JSON} to file {apath}") # fpath = os.path.join(apath, webbing.DID_JSON) # json.dump(didDoc, open(f"{fpath}", "w")) - + # ddnew = queue.Queue() # ddnurl = f'http://127.0.0.1:{port}/{ohab.pre}/did.json' # ddnt = threading.Thread(target=resolving.loadUrl, args=(ddnurl,ddnew)) # ddnt.start() - + # while ddnew == None: # time.sleep(2) # doist.recur() - + # resp = ddtres.get() # ddstat = resp.status_code # assert ddstat == 200 # print("Got dd new response content", resp.content) - + # doist.exit() - # """Done Test""" - + + class HandleCORS(object): def process_request(self, req, resp): - resp.set_header('Access-Control-Allow-Origin', '*') - resp.set_header('Access-Control-Allow-Methods', '*') - resp.set_header('Access-Control-Allow-Headers', '*') - resp.set_header('Access-Control-Max-Age', 1728000) # 20 days - if req.method == 'OPTIONS': - raise http_status.HTTPStatus(falcon.HTTP_200, text='\n') \ No newline at end of file + resp.set_header("Access-Control-Allow-Origin", "*") + resp.set_header("Access-Control-Allow-Methods", "*") + resp.set_header("Access-Control-Allow-Headers", "*") + resp.set_header("Access-Control-Max-Age", 1728000) # 20 days + if req.method == "OPTIONS": + raise http_status.HTTPStatus(falcon.HTTP_200, text="\n")