def __init__(self, seed=None): ''' Create a signing key, if not seed it supplied a keypair is generated ''' if seed: if len(seed) != libnacl.crypto_sign_SEEDBYTES: raise ValueError('Invalid seed bytes') self.vk, self.sk = libnacl.crypto_sign_seed_keypair(seed) else: seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) self.vk, self.sk = libnacl.crypto_sign_seed_keypair(seed) self.seed = seed
def _parse(pub, priv=None): """Parse key data""" _assert_libnacl() if priv: # if we have private data consider it seed data pub, priv = libnacl.crypto_sign_seed_keypair(priv) return pub, priv
def nacl_keygen(seed=None): """ generate nacl keypair """ if not seed: seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) sk, vk = libnacl.crypto_sign_seed_keypair(seed) return sk, vk, seed
def createEncAndSigKeys(enc_key_dir, sig_key_dir, name, seed=None): seed = seed or randomSeed() if isinstance(seed, str): seed = seed.encode() # ATTENTION: Passing `seed` encoded to bytes or not in # `crypto_sign_seed_keypair` will generate different keypairs verif_key, sig_key = crypto_sign_seed_keypair(seed) createCertsFromKeys(sig_key_dir, name, z85.encode(verif_key), z85.encode(sig_key[:32])) public_key, secret_key = ep2c(verif_key), es2c(sig_key) createCertsFromKeys(enc_key_dir, name, z85.encode(public_key), z85.encode(secret_key)) return (public_key, secret_key), (verif_key, sig_key)
async def seed_to_did(self, seed): """ Resolve a DID and verkey from a seed """ if isinstance(seed, str): if len(seed) != 32: seed = base64.b64decode(seed) else: seed = seed.encode('ascii') vk, sk = libnacl.crypto_sign_seed_keypair(seed) did = base58.b58encode(vk[:16]).decode('ascii') verkey = base58.b58encode(vk).decode('ascii') return (did, verkey)
def __init__(self, seed, encoder=encoding.RawEncoder): # Decode the seed seed = encoder.decode(seed) # Verify that our seed is the proper size if len(seed) != libnacl.crypto_sign_SEEDBYTES: raise ValueError("The seed must be exactly %d bytes long" % libnacl.crypto_sign_SEEDBYTES) public_key, secret_key = libnacl.crypto_sign_seed_keypair(seed) self._seed = seed self._signing_key = secret_key self.verify_key = VerifyKey(public_key)
def genDidHistory(seed, changed="2000-01-01T00:00:00+00:00", signer=0, numSigners=3): # seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk = libnacl.crypto_sign_seed_keypair(seed) did = makeDid(vk) body = {"id": did, "changed": changed, "signer": signer, "signers": []} for i in range(0, numSigners): body['signers'].append(keyToKey64u(vk)) return vk, sk, did, json.dumps(body, ensure_ascii=False).encode()
def test_UserRegMissingSinature(self): username = ''.join( random.choice(string.ascii_lowercase + string.digits) for _ in range(10)) seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) verkey, sigkey = libnacl.crypto_sign_seed_keypair(seed) signature, registration = makeUserReg(verkey, sigkey, username=username) url = 'http://localhost:8080/register' headers = {'content-type': 'application/json'} r = requests.post(url, headers=headers, data=registration) self.assertEqual(r.status_code, 400) self.assertEqual(r.content, b'{"title": "Missing signature"}')
def test_userDoubleRegistration(self): username, _ = self.test_RegisterUser() seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) verkey, sigkey = libnacl.crypto_sign_seed_keypair(seed) signature, registration = makeUserReg(verkey, sigkey, username=username) url = 'http://localhost:8080/register' headers = { 'Signature': 'signer="' + signature + '"', 'content-type': 'application/json' } r = requests.post(url, headers=headers, data=registration) self.assertEqual(r.status_code, 409)
def refreshKeys(self): """ Refreshes keys as needed so valid set of keys """ if not self.seed: # no signing key seed so create new one self.seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) if not self.sigkey or not self.verkey: # ensure also sigkey and verkey self.verkey, self.sigkey = libnacl.crypto_sign_seed_keypair( self.seed) if not self.prikey: # no private encryption key so create new pair self.pubkey, self.prikey = libnacl.crypto_box_keypair() if not self.pubkey: # no public decryption key so create one from prikey self.pubkey = libnacl.crypto_scalarmult_base(self.prikey)
def __init__(self, seed, encoder=encoding.RawEncoder): # Decode the seed seed = encoder.decode(seed) # Verify that our seed is the proper size if len(seed) != libnacl.crypto_sign_SEEDBYTES: raise ValueError( "The seed must be exactly %d bytes long" % libnacl.crypto_sign_SEEDBYTES ) public_key, secret_key = libnacl.crypto_sign_seed_keypair(seed) self._seed = seed self._signing_key = secret_key self.verify_key = VerifyKey(public_key)
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 genOtpBlob(seed=None, changed="2000-01-01T00:00:00+00:00"): if seed is None: seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk = libnacl.crypto_sign_seed_keypair(seed) did = h.makeDid(vk) body = { "id": did, "changed": changed, "blob": "AeYbsHot0pmdWAcgTo5sD8iAuSQAfnH5U6wiIGpVNJQQoYKBYrPPxAoIc1i5SHCIDS8KFFgf8i0tDq8XGizaCgo9yjuKHHNJZFi0Q" "D9K6Vpt6fP0XgXlj8z_4D-7s3CcYmuoWAh6NVtYaf_GWw_2sCrHBAA2mAEsml3thLmu50Dw", } return vk, sk, did, json.dumps(body, ensure_ascii=False).encode('utf-8')
def keyGen(seed=None): """ keyGen generates a url-file safe base64 public private key pair. If a seed is not provided libnacl's randombytes() function will be used to generate a seed. :param seed: The seed value used during key generation. :return: url-file safe base64 verifier/public key, signing/private key """ if seed is None: seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk = libnacl.crypto_sign_seed_keypair(seed) did = didering.didGen(vk) return keyToKey64u(vk), keyToKey64u(sk), did
def test_RegisterUser(self, username=None): if username is None: username = ''.join( random.choice(string.ascii_lowercase + string.digits) for _ in range(10)) seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) verkey, sigkey = libnacl.crypto_sign_seed_keypair(seed) signature, registration = makeUserReg(verkey, sigkey, username=username) url = 'http://localhost:8080/register' headers = { 'Signature': 'signer="' + signature + '"', 'content-type': 'application/json' } r = requests.post(url, headers=headers, data=registration) self.assertEqual(r.status_code, 201) return username, sigkey
def test_UserRegInvalidSignature(self): username = ''.join( random.choice(string.ascii_lowercase + string.digits) for _ in range(10)) seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) verkey, sigkey = libnacl.crypto_sign_seed_keypair(seed) signature, registration = makeUserReg(verkey, sigkey, username=username) decoded = base64.urlsafe_b64decode(signature.encode('utf-8')) decoded = decoded + os.urandom(4) signature = str(base64.urlsafe_b64encode(decoded)) url = 'http://localhost:8080/register' headers = { 'Signature': 'signer="' + signature + '"', 'content-type': 'application/json' } r = requests.post(url, headers=headers, data=registration) self.assertEqual(r.status_code, 400) self.assertEqual(r.content, b'{"title": "Invalid signature"}')
def __init__(self, filename): self.filename = os.path.abspath(filename) self.threadLocal = threading.local() #Deterministically generate a keypair that we will use to sign all correspondance self.localNodeVK, self.localNodeSK = libnacl.crypto_sign_seed_keypair( libnacl.crypto_generichash( os.path.basename(filename).encode("utf8"), nodeID)) print(len(self.localNodeVK), self.localNodeVK, 90) #Websockets that are subscribing to us. self.subscribers = weakref.WeakValueDictionary() self.dbConnect() self.config = configparser.ConfigParser() if os.path.exists(filename + ".conf"): self.config.read(filename + ".conf") self.threadLocal.conn.row_factory = sqlite3.Row # self.threadLocal.conn.execute("PRAGMA wal_checkpoint=FULL") self.threadLocal.conn.execute("PRAGMA secure_delete = off") # Yep, we're really just gonna use it as a document store like this. self.threadLocal.conn.execute( '''CREATE TABLE IF NOT EXISTS document (rowid integer primary key, json text, signature text, localinfo text)''' ) self.threadLocal.conn.execute('''CREATE TABLE IF NOT EXISTS meta (key text primary key, value text)''') self.threadLocal.conn.execute('''CREATE TABLE IF NOT EXISTS peers (peerID text primary key, lastArrival integer, info text)''') # To keep indexing simple and universal, it only works on three properties. _tags, _description and _body. self.threadLocal.conn.execute(''' CREATE VIRTUAL TABLE IF NOT EXISTS search USING fts5(tags, description, body, content='')''' ) self.threadLocal.conn.execute( '''CREATE INDEX IF NOT EXISTS document_parent ON document(json_extract(json,"$.parent")) WHERE json_extract(json,"$.parent") IS NOT null ''' ) self.threadLocal.conn.execute( '''CREATE INDEX IF NOT EXISTS document_link ON document(json_extract(json,"$.link")) WHERE json_extract(json,"$.link") IS NOT null''' ) self.threadLocal.conn.execute( '''CREATE INDEX IF NOT EXISTS document_name ON document(json_extract(json,"$.name"))''' ) self.threadLocal.conn.execute( '''CREATE INDEX IF NOT EXISTS document_id ON document(json_extract(json,"$.id"))''' ) self.threadLocal.conn.execute( '''CREATE INDEX IF NOT EXISTS document_type ON document(json_extract(json,"$.type"))''' ) self.threadLocal.conn.execute(""" CREATE TRIGGER IF NOT EXISTS search_index AFTER INSERT ON document BEGIN INSERT INTO search(rowid, tags, description, body) VALUES (new.rowid, IFNULL(json_extract(new.json,"$.tags"), ""), IFNULL(json_extract(new.json,"$.description"), ""), IFNULL(json_extract(new.json,"$.body"), "")); END; """) self.threadLocal.conn.execute( """ CREATE TRIGGER IF NOT EXISTS search_delete AFTER DELETE ON document BEGIN INSERT INTO search(search, rowid, tags, description, body) VALUES ('delete', old.rowid, IFNULL(json_extract(old.json,"$.tags"), ""), IFNULL(json_extract(old.json,"$.description"), ""), IFNULL(json_extract(old.json,"$.body"), "")); END;""") self.threadLocal.conn.execute(""" CREATE TRIGGER IF NOT EXISTS search_update AFTER UPDATE ON document BEGIN INSERT INTO search(search, rowid, tags, description, body) VALUES ('delete', old.rowid, IFNULL(json_extract(old.json,"$.tags"), ""), IFNULL(json_extract(old.json,"$.description"), ""), IFNULL(json_extract(old.json,"$.body"), "")); INSERT INTO search(rowid, tags, description, body) VALUES (new.rowid, IFNULL(json_extract(new.json,"$.tags"), ""), IFNULL(json_extract(new.json,"$.description"), ""), IFNULL(json_extract(new.json,"$.body"), "")); END; """) self.keys = configparser.ConfigParser() if os.path.exists(filename + ".keys"): self.keys.read(filename + ".keys") pk = base64.b64decode(self.keys.get('key', 'public', fallback='')) sk = base64.b64decode(self.keys.get('key', 'secret', fallback='')) # Generate a keypair for this particular node. if not (pk and sk): pk, sk = libnacl.crypto_sign_keypair() try: self.keys.add_section("key") except: pass self.keys.set('key', 'public', base64.b64encode(pk).decode('utf8')) self.keys.set('key', 'secret', base64.b64encode(sk).decode('utf8')) # Add our new key to the approved list, for our local copy. if 'approved' not in self.config: self.config.add_section('approved') self.config.set('approved', 'autogenerated', base64.b64encode(pk).decode()) self.saveConfig() self.publicKey = pk self.secretKey = sk if 'sync' not in self.config: self.config.add_section('sync') self.config.set('sync', 'syncKey', base64.b64encode(os.urandom(24)).decode('utf8')) self.config.set('sync', 'writePassword', base64.b64encode(os.urandom(24)).decode('utf8')) self.saveConfig() self.syncKey = self.config.get('sync', 'syncKey', fallback=None) self.writePassword = self.config.get('sync', 'writePassword', fallback='') if self.syncKey: databaseBySyncKeyHash[libnacl.crypto_generichash( self.syncKey.encode("utf8"))[:16]] = self if self.writePassword: databaseBySyncKeyHash[libnacl.crypto_generichash( self.writePassword.encode("utf8"))[:16]] = self print(list(databaseBySyncKeyHash.keys())) self.approvedPublicKeys = {} if 'approved' in self.config: for i in self.config['approved']: # Reverse lookup self.approvedPublicKeys[self.config['approved'][i]] = i
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 testPutSignValidation(client): url = "{0}/{1}".format(HISTORY_BASE_PATH, DID) headers = {"Signature": ""} # Test url did matches id did body = deepcopy(putData) body['id'] = "did:dad:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=" exp_result = { "title": "Validation Error", "description": "Url did must match id field did." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test missing Signature Header body = deepcopy(putData) exp_result = { "title": "Authorization Error", "description": "Empty Signature header." } verifyRequest(client.simulate_put, url, body, headers, exp_result, falcon.HTTP_401) exp_result = { "title": "Missing header value", "description": "The Signature header is required." } response = client.simulate_put( url, body=json.dumps(body, ensure_ascii=False).encode('utf-8')) assert response.status == falcon.HTTP_400 assert json.loads(response.content) == exp_result # Test partial signature header headers = { "Signature": 'signer="' + h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), SK) + '"' } exp_result = { "title": "Authorization Error", "description": "Signature header missing signature for \"rotation\"." } verifyRequest(client.simulate_put, url, body, headers, exp_result, falcon.HTTP_401) headers = { "Signature": 'rotation="' + h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), SK) + '"' } exp_result = { "title": "Authorization Error", "description": "Signature header missing signature for \"signer\"." } verifyRequest(client.simulate_put, url, body, headers, exp_result, falcon.HTTP_401) # Test invalid signer signature body = deepcopy(putData) body['signers'][1] = "Xq5YqaL6L48pf0fu7IUhL0JRaU2_RxFP0AL43wYn148=" exp_result = { "title": "Authorization Error", "description": "Could not validate the request signature for rotation field. Unverifiable signature." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_401) # Test invalid rotation signature body = deepcopy(putData) body['signers'][0] = "Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=" body['signers'][1] = "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=" exp_result = { "title": "Authorization Error", "description": "Could not validate the request signature for signer field. Unverifiable signature." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_401) # validate that signer and rotation signature fields are working correctly seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk = libnacl.crypto_sign_seed_keypair(seed) pvk, psk = libnacl.crypto_sign_seed_keypair(seed) ppvk, ppsk = libnacl.crypto_sign_seed_keypair(seed) did = h.makeDid(vk) vk = h.keyToKey64u(vk) pvk = h.keyToKey64u(pvk) ppvk = h.keyToKey64u(ppvk) body = { "id": did, "changed": str(arrow.utcnow()), "signer": 0, "signers": [vk, pvk] } bbody = json.dumps(body, ensure_ascii=False).encode('utf-8') headers = {"Signature": 'signer="{0}"'.format(h.signResource(bbody, sk))} verifyRequest(client.simulate_post, HISTORY_BASE_PATH, body, headers=headers, exp_status=falcon.HTTP_201) body['signer'] = 1 body['changed'] = str(arrow.utcnow()) body['signers'].append(ppvk) bbody = json.dumps(body, ensure_ascii=False).encode('utf-8') headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(h.signResource(bbody, sk), h.signResource(bbody, psk)) } url = "{0}/{1}".format(HISTORY_BASE_PATH, did) verifyRequest(client.simulate_put, url, body, headers=headers, exp_status=falcon.HTTP_200)
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)
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_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 test_makeDidSign(): """ Testing making DID keys and signature. """ seed = ( b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`') vk, sk = libnacl.crypto_sign_seed_keypair(seed) reg = OrderedDict() did = helping.makeDid(vk) assert did.startswith("did:igo:") assert len(did) == 52 signer = "{}#0".format(did) didy, index = signer.rsplit("#", maxsplit=1) index = int(index) assert index == 0 verkey = helping.keyToKey64u(vk) kind = "EdDSA" reg["did"] = did reg["signer"] = signer reg["keys"] = [OrderedDict(key=verkey, kind=kind)] assert reg["keys"][index]["key"] == verkey assert reg == OrderedDict([ ('did', 'did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE='), ('signer', 'did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0'), ('keys', [ OrderedDict([('key', 'Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE='), ('kind', 'EdDSA')]) ]) ]) regser = json.dumps(reg, indent=2) assert len(regser) == 244 assert SEPARATOR not in regser assert regser == ( '{\n' ' "did":"did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "signer":"did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "keys":[\n' ' {\n' ' "key":"Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "kind":"EdDSA"\n' ' }\n' ' ]\n' '}') regdeser = json.loads(regser) assert reg == regdeser regserb = regser.encode("utf-8") rregser = regserb.decode("utf-8") assert rregser == regser sig = libnacl.crypto_sign(regserb, sk)[:libnacl.crypto_sign_BYTES] assert len(sig) == 64 signature = helping.keyToKey64u(sig) assert len(signature) == 88 assert signature == ( 'a5WI7gLrxxaoWlKF62jd_8Pk51Ss7ejcVDSYWVlk7OWF0YcvmJv_Fg7HB39xA4zmHwYyfz9J9dIYYSjp9QBpAg==' ) rsig = helping.key64uToKey(signature) assert rsig == sig result = helping.verify(sig, regserb, vk) assert result print("test/help/test_helping: test_makeDidSign() \033[92mPASSED\033[0m")
def test_makeDidSign(): """ Testing utility functions for did keys and signature """ print("Testing makeDid and Signature keys") # 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) # create registration record as dict reg = ODict() did = makeDid(vk) # create the did assert did.startswith("did:igo:") assert len(did) == 52 signer = "{}#0".format(did) # make signer field value to be key index 0 didy, index = signer.rsplit("#", maxsplit=1) index = int(index) assert index == 0 verkey = keyToKey64u(vk) # make key index field value kind = "EdDSA" reg["did"] = did reg["signer"] = signer reg["keys"] = [ODict(key=verkey, kind=kind)] assert reg["keys"][index]["key"] == verkey assert reg == ODict([ ('did', 'did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE='), ('signer', 'did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0'), ('keys', [ ODict([ ('key', 'Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE='), ('kind', 'EdDSA') ]) ]) ]) regser = json.dumps(reg, indent=2) assert len(regser) == 249 assert SEPARATOR not in regser # separator assert regser == ('{\n' ' "did": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "signer": "did:igo:Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=#0",\n' ' "keys": [\n' ' {\n' ' "key": "Qt27fThWoNZsa88VrTkep6H-4HA8tr54sHON1vWl6FE=",\n' ' "kind": "EdDSA"\n' ' }\n' ' ]\n' '}') regdeser = json.loads(regser, object_pairs_hook=ODict) assert reg == regdeser regserb = regser.encode("utf-8") # re convert to bytes rregser = regserb.decode("utf-8") # reconvert assert rregser == regser # roundtrip # sign bytes sig = libnacl.crypto_sign(regserb, sk)[:libnacl.crypto_sign_BYTES] assert len(sig) == 64 signature = keyToKey64u(sig) assert len(signature) == 88 assert signature == ('B0Qc72RP5IOodsQRQ_s4MKMNe0PIAqwjKsBl4b6lK9co2XPZHLmz' 'QFHWzjA2PvxWso09cEkEHIeet5pjFhLUDg==') rsig = key64uToKey(signature) assert rsig == sig result = verify(sig, regserb, vk) assert result print("Done Test")
def test_dumpLoadKeys(): """ """ print("Testing dump load keys") baseDirPath = setupTmpBaseDir() assert baseDirPath.startswith("/tmp/bluepea") assert baseDirPath.endswith("test") keyDirPath = os.path.join(baseDirPath, "keys") os.makedirs(keyDirPath) assert os.path.exists(keyDirPath) keyFilePath = os.path.join(keyDirPath, "signer.json") assert keyFilePath.endswith("keys/signer.json") # 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 verkey, sigkey = libnacl.crypto_sign_seed_keypair(seed) assert seed == sigkey[:32] assert verkey == ( b'B\xdd\xbb}8V\xa0\xd6lk\xcf\x15\xad9\x1e\xa7\xa1\xfe\xe0p<\xb6\xbex' b'\xb0s\x8d\xd6\xf5\xa5\xe8Q') assert sigkey == ( b'PTi\x15\xd5\xd3`\xf1u\x15}^r\x9bfH\x02l\xc6\x1b\x1d\x1c\x0b9\xd7{\xc0_' b'\xf2K\x93`B\xdd\xbb}8V\xa0\xd6lk\xcf\x15\xad9\x1e\xa7\xa1\xfe\xe0p<\xb6\xbex' b'\xb0s\x8d\xd6\xf5\xa5\xe8Q') keyData = ODict(seed=binascii.hexlify(seed).decode('utf-8'), sigkey=binascii.hexlify(sigkey).decode('utf-8'), verkey=binascii.hexlify(verkey).decode('utf-8')) assert keyData == ODict([ ('seed', '50546915d5d360f175157d5e729b6648026cc61b1d1c0b39d77bc05ff24b9360'), ('sigkey', ('50546915d5d360f175157d5e729b6648026cc61b1d1c0b39d77bc05ff24b93604' '2ddbb7d3856a0d66c6bcf15ad391ea7a1fee0703cb6be78b0738dd6f5a5e851')), ('verkey', '42ddbb7d3856a0d66c6bcf15ad391ea7a1fee0703cb6be78b0738dd6f5a5e851') ]) keeping.dumpKeys(keyData, keyFilePath) assert os.path.exists(keyFilePath) mode = stat.filemode(os.stat(keyFilePath).st_mode) assert mode == "-rw-------" keyDataFiled = keeping.loadKeys(keyFilePath) assert keyData == keyDataFiled sd = binascii.unhexlify(keyDataFiled['seed'].encode('utf-8')) assert sd == seed sk = binascii.unhexlify(keyDataFiled['sigkey'].encode('utf-8')) assert sk == sigkey vk = binascii.unhexlify(keyDataFiled['verkey'].encode('utf-8')) assert vk == verkey cleanupTmpBaseDir(baseDirPath) assert not os.path.exists(keyFilePath) print("Done Test")
def createTestDid(): seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) publicKey, secretKey = libnacl.crypto_sign_seed_keypair(seed) return (makeDid(publicKey), secretKey)
def _parse(pub, priv=None): """Parse key data""" if priv: # if we have private data consider it seed data pub, priv = libnacl.crypto_sign_seed_keypair(priv) return pub, priv