def test_getOfferExpires(): """ Test get entries in did2offer database getOfferExpires(did, lastOnly=True, dbn='did2offer', env=None) """ print("Testing getOfferExpires in DB Env") dbEnv = dbing.setupTestDbEnv() dt = datetime.datetime(2000, 1, 1, minute=30, tzinfo=datetime.timezone.utc) #stamp = dt.timestamp() # make time.time value #ouid = timing.tuuid(stamp=stamp, prefix="o") ouid = "o_00035d2976e6a000_26ace93" did = "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=" expire = timing.iso8601(dt=dt, aware=True) assert expire == "2000-01-01T00:30:00+00:00" offer = "{}/offer/{}".format(did, ouid) assert offer == "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=/offer/o_00035d2976e6a000_26ace93" # no offer expire entries yet entries = dbing.getOfferExpires(did, lastOnly=False) assert entries == [] # write entry result = dbing.putDidOfferExpire(did, ouid, expire) assert result == { 'offer': 'did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=/offer/o_00035d2976e6a000_26ace93', 'expire': '2000-01-01T00:30:00+00:00' } # write another one td = datetime.timedelta(seconds=360) expire1 = timing.iso8601(dt=dt + td, aware=True) assert expire1 == "2000-01-01T00:36:00+00:00" result = dbing.putDidOfferExpire(did, ouid, expire1) assert result == { 'offer': 'did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=/offer/o_00035d2976e6a000_26ace93', 'expire': '2000-01-01T00:36:00+00:00' } entries = dbing.getOfferExpires(did, lastOnly=False) assert len(entries) == 2 assert entries[0]["expire"] == expire assert entries[0]["offer"] == offer assert entries[1]["expire"] == expire1 assert entries[1]["offer"] == offer entries = dbing.getOfferExpires(did) # lastOnly=True assert len(entries) == 1 assert entries[0]["expire"] == expire1 assert entries[0]["offer"] == offer cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def testIso8601(self): """ Test iso8601 generation """ console.terse("{0}\n".format(self.testIso8601.__doc__)) stamp = timing.iso8601() self.assertEqual(len(stamp), 26) dt = datetime.datetime(2000, 1, 1) stamp = timing.iso8601(dt) self.assertEqual(stamp, "2000-01-01T00:00:00") stamp = timing.iso8601(aware=True) if hasattr(datetime, 'timezone'): # only aware in python3.2+ self.assertEqual(len(stamp), 32) # '2017-02-07T23:47:16.498821+00:00' else: self.assertEqual(len(stamp), 26) # '2017-08-14T16:19:36.070661' if hasattr(datetime, "timezone"): # python3.2+ dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) self.assertEqual(stamp, "2000-01-01T00:00:00+00:00") else: dt = datetime.datetime(2000, 1, 1) stamp = timing.iso8601(dt) self.assertEqual(stamp, "2000-01-01T00:00:00")
def setupTest(): """ Setup environments using test values """ dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) seed = ( b'\x0c\xaa\xc9\xc6G\x11\xf6nn\xd7\x1b7\xdc^i\xc5\x12O\xe9>\xe1$F\xe1' b'\xa4z\xd4\xb6P\xdd\x86\x1d') prikey = ( b'\xd9\xc8<$\x03\xb9%\x03c\xb3*6g\xa7m\xd8\x8d\x08j\xd4^4\x88\xcac\xba\xd1\xe9' b'\xd9\xe6\x99%') baseDirPath = setupTmpBaseDir() keepDirPath = os.path.join(baseDirPath, "bluepea/keep") os.makedirs(keepDirPath) dbDirPath = os.path.join(baseDirPath, "bluepea/db") os.makedirs(dbDirPath) setup(keepDirPath=keepDirPath, seed=seed, prikey=prikey, dbDirPath=dbDirPath, changed=stamp)
def bluepeaAnonStaleClear(self, **kwa): """ Delete Expired/Stale Anon Msgs Assumes that the database has already been setup Ioinit attributes test is Flag if True use test configuration if any Parameters: Context: recur Example: do bluepea anon stale clear """ if dbing.gDbEnv: # database is setup dt = datetime.datetime.now(tz=datetime.timezone.utc) stamp = int(dt.timestamp() * 1000000) date = timing.iso8601(dt, aware=True) console.verbose("Clearing Stale Anon Msgs at '{}'\n".format(date)) try: result = dbing.clearStaleAnonMsgs(key=stamp) except dbing.DatabaseError as ex: console.terse("Error clearing stale anon msgs. {}".format(ex)) if result: console.verbose("Cleared Stale Anon Msgs at '{}'\n".format(date))
def testEventize(self): """ Test eventize function """ console.terse("{0}\n".format(self.testEventize.__doc__)) console.reinit(verbosity=console.Wordage.profuse) stamp = iso8601() # "YYYY-MM-DDTHH:MM:SS.mmmmmm" tuid = tuuid() # "0000014ddf1f2f9c_5e36738" time.sleep(0.1) event = eventing.eventize('hello') self.assertEqual(event['tag'], 'hello') self.assertFalse('data' in event) self.assertFalse('stamp' in event) self.assertFalse('uid' in event) self.assertFalse('route' in event) event = eventing.eventize(tag=eventing.tagify(head='exchange', tail='started'), stamp=True, uid=True, data=True, route=odict([("src", (None, None, None)), ("dst", (None, None, None))])) self.assertEqual(event['tag'], 'exchange.started') self.assertTrue('data' in event) self.assertIsInstance(event["data"], odict) self.assertEqual(event['data'], odict([])) self.assertTrue('stamp' in event) self.assertIsInstance(event["stamp"], str) self.assertGreater(event['stamp'], stamp) self.assertTrue('uid' in event) self.assertIsInstance(event["uid"], str) self.assertGreater(event['uid'], tuid) self.assertTrue('route' in event) self.assertEqual(event['route'] ,odict([("src", (None, None, None)), ("dst", (None, None, None))])) event = eventing.eventize(tag=eventing.tagify(head='exchange', tail='started'), stamp=stamp, uid=tuid, data=odict(name="John"), route=odict([("src", (None, None, None)), ("dst", (None, None, None))])) self.assertEqual(event['tag'], 'exchange.started') self.assertEqual(event['data'], odict(name="John")) self.assertEqual(event['stamp'], stamp) self.assertEqual(event['uid'], tuid) self.assertEqual(event['route'] ,odict([("src", (None, None, None)), ("dst", (None, None, None))])) console.reinit(verbosity=console.Wordage.concise)
def testIso8601(self): """ Test iso8601 generation """ console.terse("{0}\n".format(self.testIso8601.__doc__)) stamp = timing.iso8601() self.assertEqual(len(stamp), 26) dt = datetime.datetime(2000, 1, 1) stamp = timing.iso8601(dt) self.assertEqual(stamp, "2000-01-01T00:00:00") stamp = timing.iso8601(aware=True) self.assertEqual(len(stamp), 32) # '2017-02-07T23:47:16.498821+00:00' dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) self.assertEqual(stamp, "2000-01-01T00:00:00+00:00")
def test_putSigned_getSelfSigned(): """ Test putSigned and getSelfSigned """ print("Testing putSigned and getSelfSigned") dbEnv = dbing.setupTestDbEnv() # Create self signed resource # random seed used to generate private signing key #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) seed = ( b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`') # creates signing/verification key pair vk, sk = libnacl.crypto_sign_seed_keypair(seed) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) assert stamp == "2000-01-01T00:00:00+00:00" sig, ser = makeSignedAgentReg(vk, sk, changed=stamp) assert len(sig) == 88 assert sig == ('AeYbsHot0pmdWAcgTo5sD8iAuSQAfnH5U6wiIGpVNJQQoYKBYrPP' 'xAoIc1i5SHCIDS8KFFgf8i0tDq8XGizaCg==') assert len(ser) == 291 assert SEPARATOR not in ser # separator assert ser == ( '{\n' ' "did": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "signer": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "keys": [\n' ' {\n' ' "key": "Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ]\n' '}') dat = json.loads(ser, object_pairs_hook=ODict) did = dat['did'] assert did == "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=" dbing.putSigned(key=did, ser=ser, sig=sig, clobber=False) gdat, gser, gsig = dbing.getSelfSigned(did) assert gdat == dat assert gser == ser assert gsig == sig cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def reputationProcessReputation(self, **kwa): if dbing.gDbEnv: dt = datetime.datetime.now(tz=datetime.timezone.utc) stamp = int(dt.timestamp() * 1000000) date = timing.iso8601(dt, aware=True) console.verbose("Updating reputation at '{}'\n".format(date)) try: entries = dbing.getEntries(dbn='unprocessed') except dbing.DatabaseError as exception: console.terse("Error processing reputation. {}".format(exception)) if len(entries) > 0: for entry in entries: result = helping.getAll(entry['reputee'], dbing.getEntries()) ser = json.dumps({ "reputee": entry['reputee'], "clout": { "score": result[0][0], "confidence": result[0][1] }, "reach": { "score": result[1][0], "confidence": result[1][1] }, "clarity": { "score": result[2][0], "confidence": result[2][1] } }) try: success = dbing.putEntry(entry['reputee'], ser, dbn='reputation') except dbing.DatabaseError as exception: console.terse( "Error processing reputation. {}".format(exception)) if not success: console.terse("Error processing reputation.") success = dbing.deleteEntries() console.terse("Unprocessed database cleared: {}".format( str(success))) console.verbose("Updated reputation at '{}'\n".format(date)) else: console.verbose("Updated reputation at '{}'\n".format(date)) # ================================================== # # EOF # # ================================================== #
def setupTest(): dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) baseDirPath = setupTmpBaseDir() dbDirPath = os.path.join(baseDirPath, "reputation/db") os.makedirs(dbDirPath) setup(dbDirPath=dbDirPath) # ================================================== # # EOF # # ================================================== #
def test_setupPrime(): """ Test prime setup """ print("Testing setup") dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) assert stamp == "2000-01-01T00:00:00+00:00" baseDirPath = setupTmpBaseDir() assert baseDirPath.startswith("/tmp/bluepea") assert baseDirPath.endswith("test") keepDirPath = os.path.join(baseDirPath, "bluepea/keep") os.makedirs(keepDirPath) assert os.path.exists(keepDirPath) seed = (b'\x0c\xaa\xc9\xc6G\x11\xf6nn\xd7\x1b7\xdc^i\xc5\x12O\xe9>\xe1$F\xe1' b'\xa4z\xd4\xb6P\xdd\x86\x1d') prikey = (b'\xd9\xc8<$\x03\xb9%\x03c\xb3*6g\xa7m\xd8\x8d\x08j\xd4^4\x88\xcac\xba\xd1\xe9' b'\xd9\xe6\x99%') dbDirPath = os.path.join(baseDirPath, "bluepea/db") os.makedirs(dbDirPath) assert os.path.exists(dbDirPath) priming.setup(keepDirPath=keepDirPath, seed=seed, prikey=prikey, dbDirPath=dbDirPath, changed=stamp) assert keeping.gKeepDirPath == keepDirPath assert dbing.gDbDirPath == dbDirPath keeper = keeping.gKeeper dat, ser, sig = dbing.getSelfSigned(keeper.did) assert dat assert dat['did'] == keeper.did assert dat['changed'] == stamp cleanupTmpBaseDir(baseDirPath) assert not os.path.exists(baseDirPath) print("Done Test")
def test_signedAgentRegistration(): """ Test helper function """ print("Testing makeSignedAgentRegistration") # random seed used to generate private signing key #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) seed = (b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`') # creates signing/verification key pair vk, sk = libnacl.crypto_sign_seed_keypair(seed) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) assert stamp == "2000-01-01T00:00:00+00:00" signature, registration = makeSignedAgentReg(vk, sk, changed=stamp) assert len(signature) == 88 assert signature == ('AeYbsHot0pmdWAcgTo5sD8iAuSQAfnH5U6wiIGpVNJQQoYKBYrPP' 'xAoIc1i5SHCIDS8KFFgf8i0tDq8XGizaCg==') assert len(registration) == 291 assert SEPARATOR not in registration # separator assert registration == ( '{\n' ' "did": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "signer": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "keys": [\n' ' {\n' ' "key": "Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ]\n' '}') # validate reg = validateSignedAgentReg(signature, registration) assert reg is not None assert vk == key64uToKey(reg["keys"][0]["key"]) print("Done Test")
def makeSignedAgentReg(vk, sk, changed=None, **kwa): """ Return duple of (signature,registration) of minimal self-signing agent registration record for keypair vk, sk registration is json encoded unicode string of registration record signature is base64 url-file safe unicode string signature generated by signing bytes version of registration Parameters: vk is bytes that is the public verification key sk is bytes that is the private signing key changed is ISO8601 date time stamp string if not provided then uses current datetime **kwa are optional fields to be added to data resource. Each keyword is the associated field name and the argument parameter is the value of that field in the data resource. Keywords in ("did", "signer", "changed", "keys") will be overidden. Common use case is "issuants". """ reg = ODict(did="", signer="", changed="", keys=None) # create registration record as dict if kwa: reg.update(kwa.items()) if not changed: changed = timing.iso8601(aware=True) did = makeDid(vk) # create the did index = 0 signer = "{}#{}".format(did, index) # signer field value key at index key64u = keyToKey64u(vk) # make key index field value kind = "EdDSA" reg["did"] = did reg["signer"] = signer reg["changed"] = changed reg["keys"] = [ODict(key=key64u, kind=kind)] registration = json.dumps(reg, indent=2) sig = libnacl.crypto_sign(registration.encode("utf-8"), sk)[:libnacl.crypto_sign_BYTES] signature = keyToKey64u(sig) return (signature, registration)
def makeUserReg(vk, sk, changed=None, username=None, **kwa): """ Return duple of (signature,registration) of minimal self-signing agent registration record for keypair vk, sk registration is json encoded unicode string of registration record signature is base64 url-file safe unicode string signature generated by signing bytes version of registration Parameters: vk is bytes that is the public verification key sk is bytes that is the private signing key changed is ISO8601 date time stamp string if not provided then uses current datetime **kwa are optional fields to be added to data resource. Each keyword is the associated field name and the argument parameter is the value of that field in the data resource. Keywords in ("did", "signer", "changed", "keys") will be overidden. Common use case is "issuants". """ if not username: raise MicroserviceError('Invalid username') vk64u = base64.urlsafe_b64encode(vk).decode("utf-8") reg = ODict(username=username, key="{}".format(vk64u), changed="") # create registration record as dict if kwa: reg.update(kwa.items()) if not changed: changed = timing.iso8601(aware=True) registration = json.dumps(reg, indent=2) sig = libnacl.crypto_sign(registration.encode("utf-8"), sk)[:libnacl.crypto_sign_BYTES] signature = keyToKey64u(sig) return (signature, registration)
def reputationProcessReputation(self, **kwa): """ Checks if there are any entries in unprocessed table of database. If entry is found, reputation is recalculated for reputee associated with that entry. Assumes database has already been setup. Ioinit Attributes: test - Flag; If True, uses a test configuration if any is available Parameters: N/A Context: recur Example Usage: do reputation process reputation """ if dbing.gDbEnv: dt = datetime.datetime.now(tz=datetime.timezone.utc) date = timing.iso8601(dt, aware=True) console.verbose("Updating reputation at '{}'\n".format(date)) try: entries = dbing.getEntries(dbn='unprocessed') except dbing.DatabaseError as exception: console.terse("Error processing reputation. {}".format(exception)) if len(entries) > 0: for entry in entries: try: preprocessed = dbing.getEntry(entry['reputee'], dbn='preprocessed') result = helping.getAll( entry['reputee'], reachNum=preprocessed['reachSum'], reachDenom=preprocessed['reachLength'], clarityNum=preprocessed['claritySum'], clarityDenom=preprocessed['clarityLength']) except dbing.DatabaseError: result = helping.getAll(entry['reputee'], entries=dbing.getEntries()) ser = json.dumps({ "reputee": entry['reputee'], "clout": { "score": result[0][0], "confidence": result[0][1] }, "reach": { "score": result[1][0], "confidence": result[1][1] }, "clarity": { "score": result[2][0], "confidence": result[2][1] } }) try: success = dbing.putEntry(entry['reputee'], ser, dbn='reputation') except dbing.DatabaseError as exception: console.terse( "Error processing reputation. {}".format(exception)) if not success: console.terse("Error processing reputation.") success = dbing.deleteEntries() console.terse("Unprocessed database cleared: {}".format( str(success))) console.verbose("Updated reputation at '{}'\n".format(date)) else: console.verbose("Updated reputation at '{}'\n".format(date)) # ================================================== # # EOF # # ================================================== #
def test_clearStaleAnons(): """ Test clearStaleAnonMsgs(key, adbn='anon', edbn='expire2uid', env=None) where key is timestamp in int microseconds since epoch """ print("Testing Clear Stale Anon Msg in DB Env") dbEnv = dbing.setupTestDbEnv() dt = datetime.datetime(2000, 1, 3, minute=30, tzinfo=datetime.timezone.utc) # local time td = datetime.timedelta(seconds=5) date = timing.iso8601(dt=dt + td, aware=True) assert date == '2000-01-03T00:30:05+00:00' content = "12341234123=" create0 = int(dt.timestamp() * 1000000) expire0 = create0 + int(360 * 1000000) create1 = create0 + int(10 * 1000000) expire1 = create1 + int(360 * 1000000) uids0 = ["00000000000=", "10000000000=", "20000000000="] for uid in uids0: anon = ODict() anon['uid'] = uid anon['content'] = content anon['date'] = date data = ODict() data['create'] = create0 data['expire'] = expire0 data['track'] = anon # write entry result = dbing.putAnonMsg(key=uid, data=data) assert result result = dbing.putExpireUid(key=expire0, uid=uid) assert result # read entries for uid in uids0: entries = dbing.getAnonMsgs(key=uid) assert entries entries = dbing.getExpireUid(key=expire0) assert len(entries) == 3 uids1 = ["30000000000=", "40000000000=", "50000000000="] for uid in uids1: anon = ODict() anon['uid'] = uid anon['content'] = content anon['date'] = date data = ODict() data['create'] = create1 data['expire'] = expire1 data['anon'] = anon # write entry result = dbing.putAnonMsg(key=uid, data=data) assert result result = dbing.putExpireUid(key=expire1, uid=uid) assert result # read entries for uid in uids1: entries = dbing.getAnonMsgs(key=uid) assert entries entries = dbing.getExpireUid(key=expire0) assert len(entries) == 3 expire = expire0 - 1 # none expired result = dbing.clearStaleAnonMsgs(key=expire) assert not result expire = expire1 # all expired result = dbing.clearStaleAnonMsgs(key=expire) assert result # verify databases are empty uids = uids0 + uids1 for uid in uids: entries = dbing.getAnonMsgs(key=uid) assert not entries expires = [expire0, expire1] for expire in expires: entries = dbing.getExpireUid(key=expire) assert not entries cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def makeSignedThingReg(dvk, dsk, ssk, signer, changed=None, hid=None, **kwa): """ Return triple of (dsignature, ssignature, registration) of minimal self-signing thing registration record for did keypair (dvk, dsk) and signer key ssk as well as signer key indexed did signer and hid dsignature is base64 url-file safe unicode string signature generated by signing bytes version of registration with dsk ssignature is base64 url-file safe unicode string signature generated by signing bytes version of registration with ssk registration is json encoded unicode string of registration record { "did": "did:igo:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR", "hid": "hid:dns:canon.com#01, "signer": "did:igo:abcdefghijklmnopqrABCDEFGHIJKLMNOPQRSTUVWXYZ#1", "changed": "2000-01-01T00:00:00+00:00", "data": { "keywords": ["Canon", "EOS Rebel T6", "251440"], "message": "If found call this number", } } Parameters: dvk is bytes that is the public verification key for the thing did dsk is bytes that is the private signing key for dvk ssk is bytes that is the private signing key indicated by the signer key indexed did signer is key indexed did to the key of the signer Agent that controls the thing svk, ssk, and signer are for the same keypair changed is optional ISO8601 date time stamp string if not provided then uses current datetime hid is optional HID for the thing that is controlled by signer/issuer Agent if provided hid must validate as being controlled by signer/issuer Agent **kwa are optional fields to be added to data resource. Each keyword is the associated field name and the argument parameter is the value of that field in the data resource. Keywords in ("did", "signer", "changed", "keys", "hid") will be overidden. Common use case is data. """ reg = ODict(did="", hid="", signer="", changed="") # create registration record as dict if kwa: reg.update(kwa.items()) if not changed: changed = timing.iso8601(aware=True) tdid = makeDid(dvk) # create the thing did reg["did"] = tdid if hid is not None: reg["hid"] = hid reg["signer"] = signer reg["changed"] = changed registration = json.dumps(reg, indent=2) dsig = libnacl.crypto_sign(registration.encode("utf-8"), dsk)[:libnacl.crypto_sign_BYTES] dsignature = keyToKey64u(dsig) ssig = libnacl.crypto_sign(registration.encode("utf-8"), ssk)[:libnacl.crypto_sign_BYTES] ssignature = keyToKey64u(ssig) return (dsignature, ssignature, registration)
def validateIssuerDomainGen(store, idat, issuant, timeout=0.5): """ Validate issuer HID namespace for web (DNS) domain """ try: did = idat["did"] issuer = issuant['issuer'] if bluepeaing.fakeHidKind and issuant['kind'] == 'fake': return # fake kind always validates when enabled by fakeHidKind flag if issuant['kind'] != 'dns': # only support dns for now raise ValidationError( 'Invalid issuant kind for issuer {}'.format(issuer)) # validate that issuer belongs to validationURL vurl = issuant["validationURL"] splits = urlsplit( vurl ) # (scheme, netloc, path, host, query, fragment, hostname, port) if not splits.netloc.startswith(issuer): raise ValidationError('Issuer not part of validationURL') dt = datetime.datetime.now(tz=datetime.timezone.utc) date = timing.iso8601(dt, aware=True) check = "{}|{}|{}".format(did, issuer, date) qargs = ODict(did=did, check=check) rep = yield from backendRequest(method='GET', path=vurl, qargs=qargs, store=store, timeout=timeout) if rep is None: # timed out waiting for authorization server raise ValidationError( 'Timeout backend validation request for issuer {}'.format( issuer)) if rep['status'] != 200: if rep['errored']: emsg = rep['error'] else: emsg = "unknown" raise ValidationError( 'Error backend validation for issuer {} error {}'.format( issuer, emsg)) rdata = rep['data'] rcheck = rdata['check'] rsigner = rdata['signer'] if rcheck != check: raise ValidationError( 'Validation check response bad for issuer {}'.format(issuer)) sigs = parseSignatureHeader(rep['headers'].get("Signature", "")) sig = sigs.get('signer') # str not bytes if not sig: raise ValidationError( 'Invalid or missing Signature header for issuer {}'.format( issuer)) sdid, sindex, keystr = extractDidSignerParts(rsigner) if sdid != did: raise ValidationError( 'Bad validation signer for issuer {}'.format(issuer)) if len(idat['keys']) < sindex: raise ValidationError( 'Bad validation signer key for issuer {}'.format(issuer)) key = idat['keys'][sindex]["key"] if not verify64u(sig, rcheck, key): raise ValidationError( 'Unverifiable signature for issuer {}'.format(issuer)) except ValidationError: raise except Exception as ex: raise ValidationError("Unexpected error {}".format(ex))
def preloadTestDbs(dbn="core", clobber=False): """ Assumes lmdb database environment has been setup already Put test agents and things in db """ global gDbEnv #priming.setupTest() assumes this already called agents, things = setupTestDbAgentsThings(dbn=dbn, clobber=clobber) keeper = keeping.gKeeper agents['sam'] = (keeper.did, keeper.verkey, keeper.sigkey ) # sam the server # load messages drops annDid, annVk, annSk = agents['ann'] ivyDid, ivyVk, ivySk = agents['ivy'] thingDid, thingVk, thingSk = things['cam'] # create message from Ann to Ivy dt = datetime.datetime(2000, 1, 3, tzinfo=datetime.timezone.utc) changed = timing.iso8601(dt, aware=True) stamp = dt.timestamp() # make time.time value muid = "m_00035d2976e6a000_26ace93" signer = "{}#0".format(annDid) msg = ODict() msg['uid'] = muid msg['kind'] = "found" msg['signer'] = signer msg['date'] = changed msg['to'] = ivyDid msg['from'] = annDid msg['thing'] = thingDid msg['subject'] = "Lose something?" msg['content'] = "Look what I found" mser = json.dumps(msg, indent=2) msig = keyToKey64u( libnacl.crypto_sign(mser.encode("utf-8"), annSk)[:libnacl.crypto_sign_BYTES]) key = "{}/drop/{}/{}".format(ivyDid, annDid, muid) putSigned(key=key, ser=mser, sig=msig, clobber=False) # no clobber so error # create another message from Ann to Ivy dt = datetime.datetime(2000, 1, 4, tzinfo=datetime.timezone.utc) changed = timing.iso8601(dt, aware=True) stamp = dt.timestamp() # make time.time value muid = "m_00035d3d94be0000_15aabb5" signer = "{}#0".format(annDid) msg = ODict() msg['uid'] = muid msg['kind'] = "found" msg['signer'] = signer msg['date'] = changed msg['to'] = ivyDid msg['from'] = annDid msg['thing'] = thingDid msg['subject'] = "Lose something?" msg['content'] = "Look what I found again" mser = json.dumps(msg, indent=2) msig = keyToKey64u( libnacl.crypto_sign(mser.encode("utf-8"), annSk)[:libnacl.crypto_sign_BYTES]) key = "{}/drop/{}/{}".format(ivyDid, annDid, muid) putSigned(key=key, ser=mser, sig=msig, clobber=False) # no clobber so error # create message from Ivy to Ann dt = datetime.datetime(2000, 1, 4, tzinfo=datetime.timezone.utc) changed = timing.iso8601(dt, aware=True) stamp = dt.timestamp() # make time.time value muid = "m_00035d3d94be0000_15aabb5" # use duplicate muid to test no collision signer = "{}#0".format(ivyDid) msg = ODict() msg['uid'] = muid msg['kind'] = "found" msg['signer'] = signer msg['date'] = changed msg['to'] = annDid msg['from'] = ivyDid msg['thing'] = thingDid msg['subject'] = "Lose something?" msg['content'] = "I am so happy your found it." mser = json.dumps(msg, indent=2) msig = keyToKey64u( libnacl.crypto_sign(mser.encode("utf-8"), ivySk)[:libnacl.crypto_sign_BYTES]) key = "{}/drop/{}/{}".format(annDid, ivyDid, muid) putSigned(key=key, ser=mser, sig=msig, clobber=False) # no clobber so error # load offers # post offer Ivy to Ann sDid, sVk, sSk = agents['sam'] # server keys hDid, hVk, hSk = agents['ivy'] aDid, aVk, aSk = agents['ann'] tDid, tVk, tSk = things['cam'] ouid = "o_00035d2976e6a000_26ace93" duration = PROPAGATION_DELAY * 2.0 offerer = "{}#0".format(hDid) # ivy is offerer poffer = ODict() poffer['uid'] = ouid poffer['thing'] = tDid poffer['aspirant'] = aDid poffer['duration'] = duration poser = json.dumps(poffer, indent=2) # now build offer in database odat = ODict() odat['uid'] = ouid odat['thing'] = tDid odat['aspirant'] = aDid odat['duration'] = duration dt = datetime.datetime(2000, 1, 1, minute=30, tzinfo=datetime.timezone.utc) td = datetime.timedelta(seconds=10 * 60) # go back 10 minutes odt = dt - td td = datetime.timedelta(seconds=duration) expiration = timing.iso8601(odt + td, aware=True) odat["expiration"] = expiration signer = "{}#0".format(sDid) # server sam signs odat["signer"] = signer odat["offerer"] = offerer odat["offer"] = keyToKey64u(poser.encode("utf-8")) oser = json.dumps(odat, indent=2) osig = keyToKey64u( libnacl.crypto_sign(oser.encode("utf-8"), sSk)[:libnacl.crypto_sign_BYTES]) key = "{}/offer/{}".format(tDid, ouid) putSigned(key=key, ser=oser, sig=osig, clobber=False) # no clobber so error putDidOfferExpire(tDid, ouid, expiration) # not expired yet ouid = "o_00035d2976e6a001_26ace99" dt = datetime.datetime.now(tz=datetime.timezone.utc) td = datetime.timedelta(seconds=3600) # go ahead 1 hour odt = dt + td td = datetime.timedelta(seconds=duration) expiration = timing.iso8601(odt + td, aware=True) odat["expiration"] = expiration poffer['uid'] = ouid poser = json.dumps(poffer, indent=2) odat['uid'] = ouid odat["offer"] = keyToKey64u(poser.encode("utf-8")) odat['uid'] = ouid oser = json.dumps(odat, indent=2) osig = keyToKey64u( libnacl.crypto_sign(oser.encode("utf-8"), sSk)[:libnacl.crypto_sign_BYTES]) key = "{}/offer/{}".format(tDid, ouid) putSigned(key=key, ser=oser, sig=osig, clobber=False) # no clobber so error putDidOfferExpire(tDid, ouid, expiration) # load anon db dt = datetime.datetime.now(tz=datetime.timezone.utc) create = int(dt.timestamp() * 1000000) # timestamp in microseconds since epoch expire = create + int(ANON_EXPIRATION_DELAY * 1000000) td = datetime.timedelta(seconds=5) date = timing.iso8601(dt=dt + td, aware=True) uid = "AQIDBAoLDA0=" content = "EjRWeBI0Vng=" anon = ODict() anon['uid'] = uid anon['content'] = content anon['date'] = date sdat = ODict() sdat["create"] = create sdat["expire"] = expire sdat["anon"] = anon putAnonMsg(key=uid, data=sdat) putExpireUid(key=expire, uid=uid) dt = datetime.datetime.now(tz=datetime.timezone.utc) create = int(dt.timestamp() * 1000000) # timestamp in microseconds since epoch expire = create + int(ANON_EXPIRATION_DELAY * 1000000) td = datetime.timedelta(seconds=5) date = timing.iso8601(dt=dt + td, aware=True) uid = "AQIDBAoLDA0=" content = "EjRWeBI0Vng=" anon = ODict() anon['uid'] = uid anon['content'] = content anon['date'] = date sdat = ODict() sdat["create"] = create sdat["expire"] = expire sdat["anon"] = anon putAnonMsg(key=uid, data=sdat) putExpireUid(key=expire, uid=uid) anon2 = anon.copy() anon2['content'] = "ABRWeBI0VAA=" data2 = ODict() data2['create'] = create + 1 data2['expire'] = expire + 1 data2['anon'] = anon2 putAnonMsg(key=uid, data=data2) putExpireUid(key=expire, uid=uid) uid2 = "BBIDBAoLCCC=" anon3 = anon.copy() anon3["uid"] = uid2 data3 = ODict() data3['create'] = create data3['expire'] = expire data3['anon'] = anon3 putAnonMsg(key=uid2, data=data3) putExpireUid(key=expire, uid=uid2)
def test_signedThingRegistrationWithData(): """ Test helper function """ print("Testing makeSignedThingRegistration") # random seed used to generate private signing key #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) # Ivy's seed seed = (b"\xb2PK\xad\x9b\x92\xa4\x07\xc6\xfa\x0f\x13\xd7\xe4\x08\xaf\xc7'~\x86" b'\xd2\x92\x93rA|&9\x16Bdi') # creates signing/verification key pair svk, ssk = libnacl.crypto_sign_seed_keypair(seed) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) date = timing.iso8601(dt, aware=True) assert date == "2000-01-01T00:00:00+00:00" sdid = makeDid(svk) # create the did index = 0 signer = "{}#{}".format(sdid, index) # signer field value key at index # cam's seed seed = (b'\xba^\xe4\xdd\x81\xeb\x8b\xfa\xb1k\xe2\xfd6~^\x86tC\x9c\xa7\xe3\x1d2\x9d' b'P\xdd&R <\x97\x01') dvk, dsk = libnacl.crypto_sign_seed_keypair(seed) assert dvk == (b'\xe0\x90\x8c\xf1\xd2V\xc3\xf3\xb9\xee\xf38\x90\x0bS\xb7L\x96\xa9(' b'\x01\xbb\x08\x87\xa5X\x1d\xe7\x90b\xa0#') assert dsk == (b'\xba^\xe4\xdd\x81\xeb\x8b\xfa\xb1k\xe2\xfd6~^\x86tC\x9c\xa7\xe3\x1d2\x9d' b'P\xdd&R <\x97\x01\xe0\x90\x8c\xf1\xd2V\xc3\xf3\xb9\xee\xf38\x90\x0bS\xb7' b'L\x96\xa9(\x01\xbb\x08\x87\xa5X\x1d\xe7\x90b\xa0#') hid = "hid:dns:localhost#02" data = ODict(keywords=["Canon", "EOS Rebel T6", "251440"], message="If found please return.") dsig, ssig, ser = makeSignedThingReg(dvk, dsk, ssk, signer=signer, changed=date, hid=hid, data=data) assert ser == ( '{\n' ' "did": "did:igo:4JCM8dJWw_O57vM4kAtTt0yWqSgBuwiHpVgd55BioCM=",\n' ' "hid": "hid:dns:localhost#02",\n' ' "signer": "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "data": {\n' ' "keywords": [\n' ' "Canon",\n' ' "EOS Rebel T6",\n' ' "251440"\n' ' ],\n' ' "message": "If found please return."\n' ' }\n' '}') assert dsig == 'bzJDEvEprraZc9aOLYS7WaPi5UB_px0EH9wu76rFPrbRgjAUO9JJ4roMpQrD31v3WlbHHTG8WzB5L8PE6v3BCg==' assert ssig == 'FGRHzSNS70LIjwcSTAxHx5RahDwAet090fYSnsReMco_WvpTVpvfEygWDXslCBh0TqBoEOMLQ78-kN8fj6NFAg==' # validate dat = validateSignedThingReg(dsig, ser) assert dat is not None sverkey = keyToKey64u(svk) rsrc = validateSignedResource(ssig, resource=ser, verkey=sverkey) assert rsrc # make copy ndat = copy.copy(dat) # change signer # make new key another key for someone seed = (b'Z\xda?\x93M\xf8|\xe2!d\x16{s\x9d\x07\xd2\x98\xf2!\xff\xb8\xb6\xf9Z' b'\xe5I\xbc\x97}IFV') # creates signing/verification key pair nvk, nsk = libnacl.crypto_sign_seed_keypair(seed) signer = "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=#1" ndat['signer'] = signer ndt = datetime.datetime(2000, 1, 2, tzinfo=datetime.timezone.utc) ndate = timing.iso8601(ndt, aware=True) ndat['changed'] = ndate ser = json.dumps(ndat, indent=2) assert ser == ( '{\n' ' "did": "did:igo:4JCM8dJWw_O57vM4kAtTt0yWqSgBuwiHpVgd55BioCM=",\n' ' "hid": "hid:dns:localhost#02",\n' ' "signer": "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=#1",\n' ' "changed": "2000-01-02T00:00:00+00:00",\n' ' "data": {\n' ' "keywords": [\n' ' "Canon",\n' ' "EOS Rebel T6",\n' ' "251440"\n' ' ],\n' ' "message": "If found please return."\n' ' }\n' '}') # sign new record with old key sig = keyToKey64u(libnacl.crypto_sign(ser.encode("utf-8"), ssk)[:libnacl.crypto_sign_BYTES]) assert sig == 'fuSvUsNtFDzaYm5bX65SAgrZpNKEek2EJFqf-j-_QRWNXhSWpTFGIeg4AHOVaD7MHuIj6QsnjPg-jyBDiUAmCw==' # sign new record with new key nsig = keyToKey64u(libnacl.crypto_sign(ser.encode("utf-8"), nsk)[:libnacl.crypto_sign_BYTES]) assert nsig == '4IMop_e8vDbsot2kqJaZin8_xPsayWKbpsXL2qJZc3NrB6254UNi9x5VRwk-OgYn0zQPvKwtTE8GjtYZAHaKAQ==' sverkey = keyToKey64u(nvk) rsrc = validateSignedResource(nsig, resource=ser, verkey=sverkey) assert rsrc # make copy ndat = copy.copy(dat) # change signer to ann # make new key with Ann's seed seed = (b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`') # creates signing/verification key pair nvk, nsk = libnacl.crypto_sign_seed_keypair(seed) signer = "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0" ndat['signer'] = signer # remove hid del ndat['hid'] ser = json.dumps(ndat, indent=2) assert ser == ( '{\n' ' "did": "did:igo:4JCM8dJWw_O57vM4kAtTt0yWqSgBuwiHpVgd55BioCM=",\n' ' "signer": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "data": {\n' ' "keywords": [\n' ' "Canon",\n' ' "EOS Rebel T6",\n' ' "251440"\n' ' ],\n' ' "message": "If found please return."\n' ' }\n' '}') # sign new record with new key nsig = keyToKey64u(libnacl.crypto_sign(ser.encode("utf-8"), nsk)[:libnacl.crypto_sign_BYTES]) assert nsig == 'c04xu10KP_O8gfWoVvHRw8sO7ww9WrQ91BT_HXNGtSEMTf_BsKikxSUyQz0ASxjscEJVvV6E7yaldQ0dECQgAQ==' sverkey = keyToKey64u(nvk) rsrc = validateSignedResource(nsig, resource=ser, verkey=sverkey) assert rsrc print("Done Test")
def test_getAllAnonUids(): """ Test getAllAnonUids(dbn="anon", env=None) Gets list of Anon Uids no dups The key for the entry is just the uid uid is up 32 bytes if anon ephemeral ID in base64 url safe """ print("Testing put get delete Track in DB Env") dbEnv = dbing.setupTestDbEnv() dt = datetime.datetime(2000, 1, 1, minute=30, tzinfo=datetime.timezone.utc) #stamp = dt.timestamp() # make time.time value #create = timing.iso8601(dt=dt, aware=True) #assert create == '2000-01-01T00:30:00+00:00' create = int(dt.timestamp() * 1000000) assert create == 946686600000000 #td = datetime.timedelta(seconds=360) #expire = timing.iso8601(dt=dt+td, aware=True) #assert expire == '2000-01-01T00:36:00+00:00' expire = create + (360 * 1000000) assert expire == 946686960000000 # local time td = datetime.timedelta(seconds=5) date = timing.iso8601(dt=dt + td, aware=True) assert date == '2000-01-01T00:30:05+00:00' uid1 = "AQIDBAoLDA0=" content = "EjRWeBI0Vng=" anon1 = ODict() anon1['uid'] = uid1 anon1['content'] = content anon1['date'] = date assert anon1 == { "uid": "AQIDBAoLDA0=", "content": "EjRWeBI0Vng=", "date": "2000-01-01T00:30:05+00:00", } data1 = ODict() data1['create'] = create data1['expire'] = expire data1['anon'] = anon1 assert data1 == { "create": 946686600000000, "expire": 946686960000000, "anon": { "uid": "AQIDBAoLDA0=", "content": "EjRWeBI0Vng=", "date": "2000-01-01T00:30:05+00:00" } } # write entry result = dbing.putAnonMsg(key=uid1, data=data1) assert result anon2 = anon1.copy() anon2['content'] = "ABRWeBI0VAA=" data2 = ODict() data2['create'] = create + 1 data2['expire'] = expire + 1 data2['anon'] = anon2 result = dbing.putAnonMsg(key=uid1, data=data2) assert result uid2 = "BBIDBAoLCCC=" anon3 = anon1.copy() anon3["uid"] = uid2 data3 = ODict() data3['create'] = create data3['expire'] = expire data3['anon'] = anon3 result = dbing.putAnonMsg(key=uid2, data=data3) assert result anon4 = anon1.copy() anon4["uid"] = uid2 data4 = ODict() data4['create'] = create data4['expire'] = expire data4['anon'] = anon4 result = dbing.putAnonMsg(key=uid2, data=data4) assert result entries = dbing.getAllAnonUids() assert len(entries) == 2 assert uid1 in entries assert uid2 in entries cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def test_putSigned_getSigned(): """ Test putSigned and getSigned """ print("Testing putSigned and getSigned") dbEnv = dbing.setupTestDbEnv() # Create self signed resource # random seed used to generate private signing key #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) seed = ( b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`') # creates signing/verification key pair svk, ssk = libnacl.crypto_sign_seed_keypair(seed) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) stamp = timing.iso8601(dt, aware=True) assert stamp == "2000-01-01T00:00:00+00:00" issuant = ODict(kind="dns", issuer="generic.com", registered=stamp, validationURL="https://generic.com/indigo") issuants = [issuant] # list of issuants of hid name spaces ssig, sser = makeSignedAgentReg(svk, ssk, changed=stamp, issuants=issuants) assert len(ssig) == 88 assert ssig == ( 'Fgn0uNoZ4OqJrqiKv03HotWztrrM2ZPapf-977nZEtlpk6JPywuFFem6f4UZOZkNcvAbfUalwAr29nkX5P6ADg==' ) assert len(sser) == 477 assert SEPARATOR not in sser # separator assert sser == ( '{\n' ' "did": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "signer": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "keys": [\n' ' {\n' ' "key": "Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ],\n' ' "issuants": [\n' ' {\n' ' "kind": "dns",\n' ' "issuer": "generic.com",\n' ' "registered": "2000-01-01T00:00:00+00:00",\n' ' "validationURL": "https://generic.com/indigo"\n' ' }\n' ' ]\n' '}') sdat = json.loads(sser, object_pairs_hook=ODict) sdid = sdat['did'] assert sdid == "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=" dbing.putSigned(key=sdid, ser=sser, sig=ssig, clobber=False) # creates signing/verification key pair thing DID #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) seed = ( b'\xba^\xe4\xdd\x81\xeb\x8b\xfa\xb1k\xe2\xfd6~^\x86tC\x9c\xa7\xe3\x1d2\x9d' b'P\xdd&R <\x97\x01') dvk, dsk = libnacl.crypto_sign_seed_keypair(seed) assert dvk == ( b'\xe0\x90\x8c\xf1\xd2V\xc3\xf3\xb9\xee\xf38\x90\x0bS\xb7L\x96\xa9(' b'\x01\xbb\x08\x87\xa5X\x1d\xe7\x90b\xa0#') assert dsk == ( b'\xba^\xe4\xdd\x81\xeb\x8b\xfa\xb1k\xe2\xfd6~^\x86tC\x9c\xa7\xe3\x1d2\x9d' b'P\xdd&R <\x97\x01\xe0\x90\x8c\xf1\xd2V\xc3\xf3\xb9\xee\xf38\x90\x0bS\xb7' b'L\x96\xa9(\x01\xbb\x08\x87\xa5X\x1d\xe7\x90b\xa0#') signer = sdat['signer'] assert signer == 'did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0' hid = "hid:dns:generic.com#02" data = ODict(keywords=["Canon", "EOS Rebel T6", "251440"], message="If found please return.") dsig, tsig, tser = makeSignedThingReg(dvk, dsk, ssk, signer, changed=stamp, hid=hid, data=data) assert tser == ( '{\n' ' "did": "did:igo:4JCM8dJWw_O57vM4kAtTt0yWqSgBuwiHpVgd55BioCM=",\n' ' "hid": "hid:dns:generic.com#02",\n' ' "signer": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "data": {\n' ' "keywords": [\n' ' "Canon",\n' ' "EOS Rebel T6",\n' ' "251440"\n' ' ],\n' ' "message": "If found please return."\n' ' }\n' '}') assert dsig == ('kWZwPfepoAV9zyt9B9vPlPNGeb_POHlP9LL3H-PH71WWZzVJT1Ce' '64IKj1GmOXkNo2JaXrnIpQyfm2vynn7mCg==') assert tsig == ('RtlBu9sZgqhfc0QbGe7IHqwsHOARrGNjy4BKJG7gNfNP4GfKDQ8F' 'Gdjyv-EzN1OIHYlnMBFB2Kf05KZAj-g2Cg==') tdat = json.loads(tser, object_pairs_hook=ODict) tdid = tdat['did'] assert tdid == "did:igo:4JCM8dJWw_O57vM4kAtTt0yWqSgBuwiHpVgd55BioCM=" dbing.putSigned(key=tdid, ser=tser, sig=tsig, clobber=False) gdat, gser, gsig = dbing.getSigned(tdid) assert gdat == tdat assert gser == tser assert gsig == tsig dbing.putHid(hid, tdid) # verify hid table entry dbHid2Did = dbEnv.open_db( b'hid2did') # open named sub db named 'hid2did' within env with dbEnv.begin(db=dbHid2Did) as txn: # txn is a Transaction object tdidb = txn.get(hid.encode("utf-8")) # keys are bytes assert tdidb.decode("utf-8") == tdid cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def test_putGetDeleteAnon(): """ Test putAnonMsg(key, data, dbn="anon", env=None) getAnonMsgs(key, dbn='anon', env=None) deleteAnonMsgs(key, dbn='anon', env=None) where key is ephemeral ID 16 byte hex data is anon data The key for the entry is just the uid uid is up 32 bytes if anon ephemeral ID in base64 url safe content is message up to 256 bytes if location string in base 64 url safe date is iso8601 datetime This is augmented with server time stamp and stored in database { create: 1501774813367861, # creation in server time microseconds since epoch expire: 1501818013367861, # expiration in server time microseconds since epoch anon: { uid: "AQIDBAoLDA0=", # base64 url safe of 8 byte eid content: "EjRWeBI0Vng=", # base64 url safe of 8 byte location date: "2000-01-01T00:36:00+00:00", # ISO-8601 creation date of anon gateway time } } """ print("Testing put get delete Track in DB Env") dbEnv = dbing.setupTestDbEnv() dt = datetime.datetime(2000, 1, 1, minute=30, tzinfo=datetime.timezone.utc) #stamp = dt.timestamp() # make time.time value #create = timing.iso8601(dt=dt, aware=True) #assert create == '2000-01-01T00:30:00+00:00' create = int(dt.timestamp() * 1000000) assert create == 946686600000000 #td = datetime.timedelta(seconds=360) #expire = timing.iso8601(dt=dt+td, aware=True) #assert expire == '2000-01-01T00:36:00+00:00' expire = create + (360 * 1000000) assert expire == 946686960000000 # local time td = datetime.timedelta(seconds=5) date = timing.iso8601(dt=dt + td, aware=True) assert date == '2000-01-01T00:30:05+00:00' uid = "AQIDBAoLDA0=" content = "EjRWeBI0Vng=" anon = ODict() anon['uid'] = uid anon['content'] = content anon['date'] = date assert anon == { "uid": "AQIDBAoLDA0=", "content": "EjRWeBI0Vng=", "date": "2000-01-01T00:30:05+00:00", } data = ODict() data['create'] = create data['expire'] = expire data['anon'] = anon assert data == { "create": 946686600000000, "expire": 946686960000000, "anon": { "uid": "AQIDBAoLDA0=", "content": "EjRWeBI0Vng=", "date": "2000-01-01T00:30:05+00:00" } } # write entry result = dbing.putAnonMsg(key=uid, data=data) assert result # read entries entries = dbing.getAnonMsgs(key=uid) assert len(entries) == 1 assert entries[0] == data anon2 = anon.copy() anon2['content'] = "ABRWeBI0VAA=" data2 = ODict() data2['create'] = create + 1 data2['expire'] = expire + 1 data2['anon'] = anon2 result = dbing.putAnonMsg(key=uid, data=data2) assert result # read entries entries = dbing.getAnonMsgs(key=uid) assert len(entries) == 2 assert entries[0] == data assert entries[1] == data2 uid2 = "BBIDBAoLCCC=" anon3 = anon.copy() anon3["uid"] = uid2 data3 = ODict() data3['create'] = create data3['expire'] = expire data3['anon'] = anon3 result = dbing.putAnonMsg(key=uid2, data=data3) assert result # read entries entries = dbing.getAnonMsgs(key=uid2) assert len(entries) == 1 assert entries[0] == data3 # remove entries at uid result = dbing.deleteAnonMsgs(key=uid) assert result # read deleted entries entries = dbing.getAnonMsgs(key=uid) assert not entries cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def test_getDrops(): """ Test get essage drop entries in core database for a given did getDrops(did, dbn='core', env=None) """ print("Testing getDrops in DB Env") priming.setupTest() dbEnv = dbing.gDbEnv keeper = keeping.gKeeper kdid = keeper.did agents, things = dbing.setupTestDbAgentsThings() agents['sam'] = (kdid, keeper.verkey, keeper.sigkey) # sam the server for did, vk, sk in agents.values(): dat, ser, sig = dbing.getSelfSigned(did) assert dat is not None assert dat['did'] == did for did, vk, sk in things.values(): dat, ser, sig = dbing.getSigned(did) assert dat is not None assert dat['did'] == did annDid, annVk, annSk = agents['ann'] ivyDid, ivyVk, ivySk = agents['ivy'] thingDid, thingVk, thingSk = things['cam'] assert annDid == "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=" assert ivyDid == "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=" # test empty inbox for ivy messages = dbing.getDrops(ivyDid) assert not messages # test empty inbox for ann messages = dbing.getDrops(annDid) assert not messages # create message from Ann to Ivy dt = datetime.datetime(2000, 1, 3, tzinfo=datetime.timezone.utc) changed = timing.iso8601(dt, aware=True) assert changed == "2000-01-03T00:00:00+00:00" stamp = dt.timestamp() # make time.time value #muid = timing.tuuid(stamp=stamp, prefix="m") muid = "m_00035d2976e6a000_26ace93" assert muid == "m_00035d2976e6a000_26ace93" signer = "{}#0".format(annDid) assert signer == "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0" msg = ODict() msg['uid'] = muid msg['kind'] = "found" msg['signer'] = signer msg['date'] = changed msg['to'] = ivyDid msg['from'] = annDid msg['thing'] = thingDid msg['subject'] = "Lose something?" msg['content'] = "Look what I found" mser = json.dumps(msg, indent=2) msig = keyToKey64u( libnacl.crypto_sign(mser.encode("utf-8"), annSk)[:libnacl.crypto_sign_BYTES]) assert msig == "07u1OcQI8FUeWPqeiga3A9k4MPJGSFmC4vShiJNpv2Rke9ssnW7aLx857HC5ZaJ973WSKkLAwPzkl399d01HBA==" # Build key for message from (to, from, uid) (did, sdid, muid) key = "{}/drop/{}/{}".format(ivyDid, annDid, muid) assert key == ('did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=' '/drop' '/did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=' '/m_00035d2976e6a000_26ace93') # save message to database error if duplicate dbing.putSigned(key=key, ser=mser, sig=msig, clobber=False) # no clobber so error #test get inbox for Ivy messages = dbing.getDrops(ivyDid) assert messages assert len(messages) == 1 assert messages[0]['uid'] == muid assert messages[0]['from'] == annDid # create another message from Ann to Ivy dt = datetime.datetime(2000, 1, 4, tzinfo=datetime.timezone.utc) changed = timing.iso8601(dt, aware=True) assert changed == "2000-01-04T00:00:00+00:00" stamp = dt.timestamp() # make time.time value #muid = timing.tuuid(stamp=stamp, prefix="m") muid = "m_00035d3d94be0000_15aabb5" assert muid == "m_00035d3d94be0000_15aabb5" signer = "{}#0".format(annDid) assert signer == "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0" msg = ODict() msg['uid'] = muid msg['kind'] = "found" msg['signer'] = signer msg['date'] = changed msg['to'] = ivyDid msg['from'] = annDid msg['thing'] = thingDid msg['subject'] = "Lose something?" msg['content'] = "Look what I found again" mser = json.dumps(msg, indent=2) msig = keyToKey64u( libnacl.crypto_sign(mser.encode("utf-8"), annSk)[:libnacl.crypto_sign_BYTES]) assert msig == "HgFcqSGI20okVh3K611XvEAsHHiV9yXDnFvd0djlZyA52K09E4BZbCnJ2Ejd8yFfRFc1GcTblbUYpDVwpumgCQ==" # Build key for message from (to, from, uid) (did, sdid, muid) key = "{}/drop/{}/{}".format(ivyDid, annDid, muid) assert key == ('did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=' '/drop' '/did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=' '/m_00035d3d94be0000_15aabb5') # save message to database error if duplicate dbing.putSigned(key=key, ser=mser, sig=msig, clobber=False) # no clobber so error #test get inbox for Ivy messages = dbing.getDrops(ivyDid) assert messages assert len(messages) == 2 assert messages[1]['uid'] == muid assert messages[1]['from'] == annDid # create message from Ivy to Ann dt = datetime.datetime(2000, 1, 4, tzinfo=datetime.timezone.utc) changed = timing.iso8601(dt, aware=True) assert changed == "2000-01-04T00:00:00+00:00" stamp = dt.timestamp() # make time.time value #muid = timing.tuuid(stamp=stamp, prefix="m") muid = "m_00035d3d94be0000_15aabb5" # use duplicate muid to test no collision assert muid == "m_00035d3d94be0000_15aabb5" signer = "{}#0".format(ivyDid) assert signer == "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=#0" msg = ODict() msg['uid'] = muid msg['kind'] = "found" msg['signer'] = signer msg['date'] = changed msg['to'] = annDid msg['from'] = ivyDid msg['thing'] = thingDid msg['subject'] = "Lose something?" msg['content'] = "I am so happy your found it." mser = json.dumps(msg, indent=2) msig = keyToKey64u( libnacl.crypto_sign(mser.encode("utf-8"), annSk)[:libnacl.crypto_sign_BYTES]) assert msig == "62ThJr_GUImtTa54RVhbo1bs5X4DCxjmecHONniQp0Os95Pb8bLrzBgCYr3YOhSB8wMPHYL7L6pm5qQjVPYzAA==" # Build key for message from (to, from, uid) (did, sdid, muid) key = "{}/drop/{}/{}".format(annDid, ivyDid, muid) assert key == ('did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=' '/drop' '/did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=' '/m_00035d3d94be0000_15aabb5') # save message to database error if duplicate dbing.putSigned(key=key, ser=mser, sig=msig, clobber=False) # no clobber so error #test get inbox for Ann messages = dbing.getDrops(annDid) assert messages assert len(messages) == 1 assert messages[0]['uid'] == muid assert messages[0]['from'] == ivyDid #test get inbox for Ivy to make sure still works messages = dbing.getDrops(ivyDid) assert messages assert len(messages) == 2 for message in messages: assert message['from'] == annDid cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def test_putOfferExpire(): """ Test put entry in did2offer database putOfferExpire(expire, did, ouid, dbn="did2offer", env=None) """ print("Testing putOfferExpire in DB Env") dbEnv = dbing.setupTestDbEnv() dt = datetime.datetime(2000, 1, 1, minute=30, tzinfo=datetime.timezone.utc) #stamp = dt.timestamp() # make time.time value #ouid = timing.tuuid(stamp=stamp, prefix="o") ouid = "o_00035d2976e6a000_26ace93" did = "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=" expire = timing.iso8601(dt=dt, aware=True) assert expire == "2000-01-01T00:30:00+00:00" result = dbing.putDidOfferExpire(did, ouid, expire) assert result # verify in database assert dbing.exists(did, dbn='did2offer', dup=True) == True # read from database subDb = dbing.gDbEnv.open_db( b"did2offer", dupsort=True) # open named sub db named dbn within env with dbing.gDbEnv.begin(db=subDb) as txn: # txn is a Transaction object rsrcb = txn.get(did.encode("utf-8")) rsrc = rsrcb.decode("utf-8") assert rsrc == ( '{\n' ' "offer": ' '"did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=/offer/o_00035d2976e6a000_26ace93",\n' ' "expire": "2000-01-01T00:30:00+00:00"\n' '}') dat = json.loads(rsrc, object_pairs_hook=ODict) offer = "{}/offer/{}".format(did, ouid) assert offer == "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=/offer/o_00035d2976e6a000_26ace93" assert dat["offer"] == offer assert dat["expire"] == expire # write another one td = datetime.timedelta(seconds=360) expire1 = timing.iso8601(dt=dt + td, aware=True) assert expire1 == "2000-01-01T00:36:00+00:00" result = dbing.putDidOfferExpire(did, ouid, expire1) assert result == { 'offer': 'did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=/offer/o_00035d2976e6a000_26ace93', 'expire': '2000-01-01T00:36:00+00:00', } # read from database entries = [] subDb = dbing.gDbEnv.open_db( b"did2offer", dupsort=True) # open named sub db named dbn within env with dbing.gDbEnv.begin(db=subDb) as txn: # txn is a Transaction object with txn.cursor() as cursor: if cursor.set_key(did.encode("utf-8")): entries = [ json.loads(value.decode("utf-8"), object_pairs_hook=ODict) for value in cursor.iternext_dup() ] assert len(entries) == 2 assert entries[0]["expire"] == expire assert entries[0]["offer"] == offer assert entries[1]["expire"] == expire1 assert entries[1]["offer"] == offer cleanupTmpBaseDir(dbEnv.path()) print("Done Test")
def test_signedAgentRegistrationWithData(): """ Test helper function """ print("Testing makeSignedAgentRegistration") # random seed used to generate private signing key #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) # Ann's seed seed = (b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`') # creates signing/verification key pair vk, sk = libnacl.crypto_sign_seed_keypair(seed) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) date = timing.iso8601(dt, aware=True) assert date == "2000-01-01T00:00:00+00:00" issuant = ODict(kind="dns", issuer="localhost", registered=date, validationURL="http://localhost:8080/demo/check") issuants = [issuant] # list of hid issuants sig, ser = makeSignedAgentReg(vk, sk, changed=date, issuants=issuants) assert len(sig) == 88 assert sig == 'ELqC0M2G8Fs4Z1FCPP0E2jrfJFbAYKoAu-tDn0G05w7ecb4pqN_8pQuruZs-KbCEzTOHov1OWkZ_fSuFZZKzDA==' assert SEPARATOR not in ser # separator assert ser == ( '{\n' ' "did": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "signer": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "keys": [\n' ' {\n' ' "key": "Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ],\n' ' "issuants": [\n' ' {\n' ' "kind": "dns",\n' ' "issuer": "localhost",\n' ' "registered": "2000-01-01T00:00:00+00:00",\n' ' "validationURL": "http://localhost:8080/demo/check"\n' ' }\n' ' ]\n' '}') # validate dat = validateSignedAgentReg(sig, ser) assert dat is not None assert vk == key64uToKey(dat["keys"][0]["key"]) # random seed used to generate private signing key #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) # Ivy's seed seed = (b"\xb2PK\xad\x9b\x92\xa4\x07\xc6\xfa\x0f\x13\xd7\xe4\x08\xaf\xc7'~\x86" b'\xd2\x92\x93rA|&9\x16Bdi') # creates signing/verification key pair vk, sk = libnacl.crypto_sign_seed_keypair(seed) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) date = timing.iso8601(dt, aware=True) assert date == "2000-01-01T00:00:00+00:00" issuant = ODict(kind="dns", issuer="localhost", registered=date, validationURL="http://localhost:8080/demo/check") issuants = [issuant] # list of hid issuants sig, ser = makeSignedAgentReg(vk, sk, changed=date, issuants=issuants) assert len(sig) == 88 assert sig == 'jc3ZXMA5GuypGWFEsxrGVOBmKDtd0J34UKZyTIYUMohoMYirR8AgH5O28PSHyUB-UlwfWaJlibIPUmZVPTG1DA==' assert SEPARATOR not in ser # separator assert ser == ( '{\n' ' "did": "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=",\n' ' "signer": "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "keys": [\n' ' {\n' ' "key": "dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ],\n' ' "issuants": [\n' ' {\n' ' "kind": "dns",\n' ' "issuer": "localhost",\n' ' "registered": "2000-01-01T00:00:00+00:00",\n' ' "validationURL": "http://localhost:8080/demo/check"\n' ' }\n' ' ]\n' '}') # validate dat = validateSignedAgentReg(sig, ser) assert dat is not None assert vk == key64uToKey(dat["keys"][0]["key"]) # add new key ndat = copy.copy(dat) seed = (b'Z\xda?\x93M\xf8|\xe2!d\x16{s\x9d\x07\xd2\x98\xf2!\xff\xb8\xb6\xf9Z' b'\xe5I\xbc\x97}IFV') # creates signing/verification key pair nvk, nsk = libnacl.crypto_sign_seed_keypair(seed) ndt = datetime.datetime(2000, 1, 2, tzinfo=datetime.timezone.utc) ndate = timing.iso8601(ndt, aware=True) ndat['changed'] = ndate index = 1 signer = "{}#{}".format(dat['did'], index) # signer field value key at index ndat['signer'] = signer nverkey = keyToKey64u(nvk) # make key index field value assert nverkey == '0UX5tP24WPEmAbROdXdygGAM3oDcvrqb3foX4EyayYI=' kind = "EdDSA" ndat['keys'].append(ODict(key=nverkey, kind="EdDSA")) ser = json.dumps(ndat, indent=2) assert ser == ( '{\n' ' "did": "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=",\n' ' "signer": "did:igo:dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=#1",\n' ' "changed": "2000-01-02T00:00:00+00:00",\n' ' "keys": [\n' ' {\n' ' "key": "dZ74MLZXD-1QHoa73w9pQ9GroAvxqFi2RTZWlkC0raY=",\n' ' "kind": "EdDSA"\n' ' },\n' ' {\n' ' "key": "0UX5tP24WPEmAbROdXdygGAM3oDcvrqb3foX4EyayYI=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ],\n' ' "issuants": [\n' ' {\n' ' "kind": "dns",\n' ' "issuer": "localhost",\n' ' "registered": "2000-01-01T00:00:00+00:00",\n' ' "validationURL": "http://localhost:8080/demo/check"\n' ' }\n' ' ]\n' '}') # sign new record with old key sig = keyToKey64u(libnacl.crypto_sign(ser.encode("utf-8"), sk)[:libnacl.crypto_sign_BYTES]) assert sig == 'bTGB92MvNmb65Ka0BD7thquxw1BGEcJRf1c8GpTvcF5Qe-tm0v28qMGKfYQ3EYeVI1VdLWRMtyFApnyAB07yCQ==' assert vk == key64uToKey(dat["keys"][0]["key"]) # sign new record with new key nsig = keyToKey64u(libnacl.crypto_sign(ser.encode("utf-8"), nsk)[:libnacl.crypto_sign_BYTES]) assert nsig == 'o9yjuKHHNJZFi0QD9K6Vpt6fP0XgXlj8z_4D-7s3CcYmuoWAh6NVtYaf_GWw_2sCrHBAA2mAEsml3thLmu50Dw==' ndat = validateSignedAgentWrite(dat, sig, nsig, ser) assert ndat is not None assert nvk == key64uToKey(ndat["keys"][1]["key"]) # random seed used to generate private signing key #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) # Ike's seed seed = (b'!\x85\xaa\x8bq\xc3\xf8n\x93]\x8c\xb18w\xb9\xd8\xd7\xc3\xcf\x8a\x1dP\xa9m' b'\x89\xb6h\xfe\x10\x80\xa6S') # creates signing/verification key pair vk, sk = libnacl.crypto_sign_seed_keypair(seed) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) date = timing.iso8601(dt, aware=True) assert date == "2000-01-01T00:00:00+00:00" issuant = ODict(kind="dns", issuer="localhost", registered=date, validationURL="http://localhost:8080/demo/check") issuants = [issuant] # list of hid issuants sig, ser = makeSignedAgentReg(vk, sk, changed=date, issuants=issuants) assert len(sig) == 88 assert sig == '1HO_9ERLOe30yEQyiwgu7g9DeHC8Nsq-ybQlNtDW9D611J61gm52Na5Cx5acYu71X8g_UR4Eyj05saNBoqcnCw==' assert SEPARATOR not in ser # separator assert ser == ( '{\n' ' "did": "did:igo:3syVH2woCpOvPF0SD9Z0bu_OxNe2ZgxKjTQ961LlMnA=",\n' ' "signer": "did:igo:3syVH2woCpOvPF0SD9Z0bu_OxNe2ZgxKjTQ961LlMnA=#0",\n' ' "changed": "2000-01-01T00:00:00+00:00",\n' ' "keys": [\n' ' {\n' ' "key": "3syVH2woCpOvPF0SD9Z0bu_OxNe2ZgxKjTQ961LlMnA=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ],\n' ' "issuants": [\n' ' {\n' ' "kind": "dns",\n' ' "issuer": "localhost",\n' ' "registered": "2000-01-01T00:00:00+00:00",\n' ' "validationURL": "http://localhost:8080/demo/check"\n' ' }\n' ' ]\n' '}') # validate dat = validateSignedAgentReg(sig, ser) assert dat is not None assert vk == key64uToKey(dat["keys"][0]["key"]) print("Done Test")
def buildSignedServerOffer(dat, ser, sig, tdat, sdat, dt, sk, **kwa): """ Return triple of (odat, oser, osig) Where: odat is server offer dict data oser is JSON serialize version of oser osig is signature base64U using sk Parameters: dat is offer request dat ser is offer request JSON serialization sig is offer request signature sdat is server resource dt is current datetime sk is server private signing key registration is json encoded unicode string of registration record signature is base64 url-file safe unicode string signature generated by signing bytes version of registration Parameters: vk is bytes that is the public verification key sk is bytes that is the private signing key changed is ISO8601 date time stamp string if not provided then uses current datetime **kwa are optional fields to be added to data resource. Each keyword is the associated field name and the argument parameter is the value of that field in the data resource. Keywords in ("did", "signer", "changed", "keys") will be overidden. Common use case is "issuants". offer request fields { "uid": offeruniqueid, "thing": thingDID, "aspirant": AgentDID, "duration": timeinsecondsofferisopen, } offer response fields { "uid": offeruniqueid, "thing": thingDID, "aspirant": AgentDID, "duration": timeinsecondsofferisopen, "expiration": datetimeofexpiration, "signer": serverkeydid, "offerer": ownerkeydid, "offer": Base64serrequest } """ duration = float(dat["duration"]) odat = ODict() if kwa: odat.update(kwa.items()) odat["uid"] = dat["uid"] odat["thing"] = dat["thing"] odat["aspirant"] = dat["aspirant"] odat["duration"] = duration td = datetime.timedelta(seconds=duration) odat["expiration"] = timing.iso8601(dt + td, aware=True) odat["signer"] = sdat["signer"] # assumes sk and sdat["signer"] correspond odat["offerer"] = tdat["signer"] odat["offer"] = keyToKey64u(ser.encode("utf-8")) oser = json.dumps(odat, indent=2) osig = keyToKey64u( libnacl.crypto_sign(oser.encode("utf-8"), sk)[:libnacl.crypto_sign_BYTES]) return (odat, oser, osig)
def reputationProcessReputation(self, **kwa): if dbing.gDbEnv: dt = datetime.datetime.now(tz=datetime.timezone.utc) stamp = int(dt.timestamp() * 1000000) date = timing.iso8601(dt, aware=True) console.verbose("Updating reputation at '{}'\n".format(date)) # Get the data from the 'unprocessed' database try: entries = dbing.repGetEntries(dbName='unprocessed') except dbing.DatabaseError as exception: console.terse("Error processing reputation. {}".format(exception)) #Process the data and move the calculated scores into the 'reputation' database if len(entries) > 0: ridList = [] #try to get ridList from db #try: #ridList = dbing.repGetTxn("ridList", dbName="reputation") #if ridList == None: #ridList = [] for entry in entries: if entry['repute'][ 'rid'] not in ridList: #Ignore reputes with duplicate rids ridList.append(entry['repute']['rid']) result = getAll(entry['reputee'], dbing.repGetEntries()) """ entryAvg = None try: entryAvg = dbing.repGetTxn(entry['reputee'], dbName="reputation") if result != False: and entryAvg != None: newAvg = getAllRun(entry['reputee'], result, average=entryAvg) ser = json.dumps({"reputee": entry['reputee'], "clout": { "score": newAvg[0], "confidence": newAvg[1]}, "reach": { "score": newAvg[2], "confidence": newAvg[3], "average": newAvg[6], "total": newAvg[7]}, "clarity": { "score": newAvg[4], "confidence": newAvg[5], "average": newAvg[8], "total": newAvg[9]}}) try: success = dbing.repPutTxn(entry['reputee'], ser, dbName='reputation') except dbing.DatabaseError as exception: console.terse("Error processing reputation. {}".format(exception)) if not success: console.terse("Error processing reputation.") """ #elif result != False: #print("4") if result != False: ## ser = json.dumps({ "reputee": entry['reputee'], "clout": { "score": result[0], "confidence": result[1] }, "reach": { "score": result[2], "confidence": result[3] }, "clarity": { "score": result[4], "confidence": result[5] } }) try: #print("5") #ridSucess = dbing.repPutTxn("ridList", ridList dbName='reputation') success = dbing.repPutTxn(entry['reputee'], ser, dbName='reputation') except dbing.DatabaseError as exception: console.terse( "Error processing reputation. {}".format( exception)) if not success: console.terse("Error processing reputation.") success = dbing.repDeleteEntries() console.terse("Unprocessed database cleared: {}".format( str(success))) console.verbose("Updated reputation at '{}'\n".format(date)) else: console.verbose("Updated reputation at '{}'\n".format(date))
def setupTestDbAgentsThings(dbn="core", clobber=False): """ Assumes lmdb database environment has been setup already Put test agents and things in db and return duple of dicts (agents, things) keyed by name each value is triple ( did, vk, sk) where vk is public verification key sk is private signing key """ agents = ODict() things = ODict() #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) dt = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc) changed = timing.iso8601(dt, aware=True) # make "ann" the agent and issuer seed = ( b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`') # creates signing/verification key pair avk, ask = libnacl.crypto_sign_seed_keypair(seed) issuant = ODict(kind="dns", issuer="localhost", registered=changed, validationURL="http://localhost:8101/demo/check") issuants = [issuant] # list of issuants hid name spaces sig, ser = makeSignedAgentReg(avk, ask, changed=changed, issuants=issuants) adat = json.loads(ser, object_pairs_hook=ODict) adid = adat['did'] putSigned(key=adid, ser=ser, sig=sig, dbn=dbn, clobber=clobber) agents['ann'] = (adid, avk, ask) # make "ivy" the issurer seed = ( b"\xb2PK\xad\x9b\x92\xa4\x07\xc6\xfa\x0f\x13\xd7\xe4\x08\xaf\xc7'~\x86" b'\xd2\x92\x93rA|&9\x16Bdi') # creates signing/verification key pair ivk, isk = libnacl.crypto_sign_seed_keypair(seed) issuant = ODict(kind="dns", issuer="localhost", registered=changed, validationURL="http://localhost:8101/demo/check") issuants = [issuant] # list of issuants hid name spaces sig, ser = makeSignedAgentReg(ivk, isk, changed=changed, issuants=issuants) idat = json.loads(ser, object_pairs_hook=ODict) idid = idat['did'] putSigned(key=idid, ser=ser, sig=sig, dbn=dbn, clobber=clobber) agents['ivy'] = (idid, ivk, isk) # make "cam" the thing # create thing signed by issuer and put into database seed = ( b'\xba^\xe4\xdd\x81\xeb\x8b\xfa\xb1k\xe2\xfd6~^\x86tC\x9c\xa7\xe3\x1d2\x9d' b'P\xdd&R <\x97\x01') cvk, csk = libnacl.crypto_sign_seed_keypair(seed) signer = idat[ 'signer'] # use same signer key fragment reference as issuer isaac hid = "hid:dns:localhost#02" data = ODict(keywords=["Canon", "EOS Rebel T6", "251440"], message="If found please return.") sig, isig, ser = makeSignedThingReg(cvk, csk, isk, signer, changed=changed, hid=hid, data=data) cdat = json.loads(ser, object_pairs_hook=ODict) cdid = cdat['did'] putSigned(key=cdid, ser=ser, sig=isig, dbn=dbn, clobber=clobber) putHid(hid, cdid) things['cam'] = (cdid, cvk, csk) # make "fae" the finder seed = ( b'\xf9\x13\xf0\xff\xd4\xb3\xbdF\xa2\x80\x1d\xce\xaa\xd9\x87df\xc8\x1f\x91' b';\x9bp+\x1bK\x1ey\xef6\xa7\xf9') # creates signing/verification key pair fvk, fsk = libnacl.crypto_sign_seed_keypair(seed) sig, ser = makeSignedAgentReg(fvk, fsk, changed=changed) fdat = json.loads(ser, object_pairs_hook=ODict) fdid = fdat['did'] putSigned(key=fdid, ser=ser, sig=sig, dbn=dbn, clobber=clobber) agents['fae'] = (fdid, fvk, fsk) # make "ike" another issurer for demo testing #seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) seed = ( b'!\x85\xaa\x8bq\xc3\xf8n\x93]\x8c\xb18w\xb9\xd8\xd7\xc3\xcf\x8a\x1dP\xa9m' b'\x89\xb6h\xfe\x10\x80\xa6S') # creates signing/verification key pair ivk, isk = libnacl.crypto_sign_seed_keypair(seed) issuant = ODict(kind="dns", issuer="localhost", registered=changed, validationURL="http://localhost:8101/demo/check") issuants = [issuant] # list of issuants hid name spaces sig, ser = makeSignedAgentReg(ivk, isk, changed=changed, issuants=issuants) idat = json.loads(ser, object_pairs_hook=ODict) idid = idat['did'] putSigned(key=idid, ser=ser, sig=sig, dbn=dbn, clobber=clobber) agents['ike'] = (idid, ivk, isk) return (agents, things)