def nacl_sign(m, sk): """ sign message m with secret key sk return signature """ s = libnacl.crypto_sign(m,sk) return s[:_SIG_SIZE]
def test_box(self): msg = b'Are you suggesting coconuts migrate?' # run 1 vk1, sk1 = libnacl.crypto_sign_keypair() sig = libnacl.crypto_sign(msg, sk1) self.assertEqual(msg, sig[libnacl.crypto_sign_BYTES:]) sig_msg = libnacl.crypto_sign_open(sig, vk1) self.assertEqual(msg, sig_msg)
def nacl_sign(m, sk): """ sign message m with secret key sk return signed message """ if libnacl: s = libnacl.crypto_sign(m,sk)[:_SIG_SIZE] assert len(s) == _SIG_SIZE return s
def testSimpleSigningWithSimpleKeys(): print("signing with a simple (non-signing) key pair") sk = PrivateKey.generate() prikey = sk._private_key assert len(prikey) == 32 pubkey = sk.public_key._public_key assert len(pubkey) == 32 msg = b'1234' cmsg = crypto_sign(msg, prikey)
def _signData(self, sk): bdata = json.dumps(self.data, ensure_ascii=False, separators=(",", ":")).encode() bsk = base64.urlsafe_b64decode(sk.encode("utf-8")) sig = libnacl.crypto_sign(bdata, bsk) sig = sig[:libnacl.crypto_sign_BYTES] return base64.urlsafe_b64encode(sig).decode("utf-8")
def sign(self, signing_key) -> None: """ Signs an event with the given signing key, setting its signature :param signing_key: The signing key to use :return: None """ signing_key_byte = base64_decode(signing_key.encode("UTF-8")) self.signature = base64_encode( crypto_sign(self.body.encode("UTF-8"), signing_key_byte)).decode("UTF-8")
def testSimpleSigning(): sik = SigningKey(randombytes(32)) sigkey = sik._signing_key assert len(sigkey) == 64 # why is a signing key 64 bytes and not 32? verkey = sik.verify_key._key assert len(verkey) == 32 msg = b'1234' cmsg = crypto_sign(msg, sigkey) dmsg = crypto_sign_open(cmsg, verkey) assert msg == dmsg
def testSignatureValidation(): vk, sk = libnacl.crypto_sign_keypair() data = {'message': 'this is a test'} signed = libnacl.crypto_sign(bytes(data['message'], 'utf-8'), sk) base64Signature = base64.b64encode(signed) base64Key = base64.b64encode(vk) verified, message = validateSignature(base64Signature, base64Key, dumps(data)) assert verified data = {'message': 'this will fail'} verified, message = validateSignature(base64Signature, base64Key, dumps(data)) assert not verified
def _sign(self, data): """Generate EdDSA signature""" assert self.key[1] is not None assert len(self.key[1]) == libnacl.crypto_sign_SECRETKEYBYTES # compute sha512 of data h = libnacl.crypto_hash_sha512(data) # sign hash of data # crypto_sign makes a signed message we just want the signature smsg = libnacl.crypto_sign(h, self.key[1]) return smsg[:0-len(h)]
def _sign(self, data): """Generate EdDSA signature""" assert self.key[1] is not None assert len(self.key[1]) == libnacl.crypto_sign_SECRETKEYBYTES # compute sha512 of data h = libnacl.crypto_hash_sha512(data) # sign hash of data # crypto_sign makes a signed message we just want the signature smsg = libnacl.crypto_sign(h, self.key[1]) return smsg[:0 - len(h)]
def testSimpleSigningIsHasConsistentVerKey(): seed = randombytes(32) sik = SigningKey(seed) sigkey = sik._signing_key verkey = sik.verify_key._key msg = b'1234' cmsg = crypto_sign(msg, sigkey) dmsg = crypto_sign_open(cmsg, verkey) cmsg2 = crypto_sign(msg, sigkey) dmsg2 = crypto_sign_open(cmsg2, verkey) assert msg == dmsg assert dmsg == dmsg2 sik2 = SigningKey(seed) sigkey2 = sik2._signing_key verkey2 = sik2.verify_key._key assert sigkey2 == sigkey assert verkey2 == verkey
def signResource(resource, sk): """ Produce a signature for resource :param resource: byte string message to be signed :param sk: byte string signing key :return: base64 url-file safe string """ sig = libnacl.crypto_sign(resource, sk) sig = sig[:libnacl.crypto_sign_BYTES] return bytesToStr64u(sig)
def encodeMessage(self, d, useWritePassword=False): "Given a JSON message, encode it so as to be suitable to send to another node" if useWritePassword and not self.writePassword: raise RuntimeError("You don't have a write password") pw = self.writePassword if useWritePassword else self.syncKey pw = pw.encode("utf8").ljust(32, b'\0') r = jsonEncode(d).encode('utf8') t = struct.pack("<Q", int(time.time() * 1000000)) r = libnacl.crypto_secretbox(r, t + b'\0' * 16, pw) return libnacl.crypto_generichash( pw)[:16] + self.localNodeVK + libnacl.crypto_sign( t + r, self.localNodeSK)
def signResource(resource, sk): """ Cryptographically signs a resource. Parameters: resource - Resource to be signed sk - signing secret key Return: Encoded bytes key """ sig = libnacl.crypto_sign(resource, sk) sig = sig[:libnacl.crypto_sign_BYTES] return keyToKey64u(sig)
def sign(self, message, encoder=encoding.RawEncoder): """ Sign a message using this key. :param message: [:class:`bytes`] The data to be signed. :param encoder: A class that is used to encode the signed message. :rtype: :class:`~SignedMessage` """ raw_signed = libnacl.crypto_sign(message, self._signing_key) signature = encoder.encode(raw_signed[:libnacl.crypto_sign_BYTES]) message = encoder.encode(raw_signed[libnacl.crypto_sign_BYTES:]) signed = encoder.encode(raw_signed) return SignedMessage._from_parts(signature, message, signed)
def signResource(resource, sKey): """ signResource accepts a byte string and an EdDSA (Ed25519) key in the form of a byte string and returns a base64 url-file safe signature. :param resource: byte string to be signed :param sKey: signing/private key from EdDSA (Ed25519) key :return: url-file safe base64 signature string """ if resource is None: return None sig = libnacl.crypto_sign(resource, sKey) sig = sig[:libnacl.crypto_sign_BYTES] return gen.keyToKey64u(sig)
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 signature(self, msg): ''' Return just the signature for the message ''' return libnacl.crypto_sign(msg, self.sk)[:libnacl.crypto_sign_BYTES]
def sign(self, msg): ''' Sign the given message with this key ''' return libnacl.crypto_sign(msg, self.sk)
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_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_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 setDocument(self, doc, signature=b''): if not signature and not self.secretKey: raise ValueError( "Cannot sign any new documents, you do not have the keys:" + str(self.secretKey)) if signature: if not isinstance(doc, str): raise ValueError( "Doc ,ust be an exact JSON string when providing a signature" ) key = signature.split(":") if not key in self.approvedPublicKeys: raise RuntimeError("Message was signed with a bad key") libnacl.crypto_sign_verify_detached( base64.b64decode( signature.split(":")[1], libnacl.crypto_generichash(doc.encode('utf8')), base64.b64decode(key))) doc = json.loads(doc) doc['time'] = doc.get('time', time.time() * 1000000) doc['arrival'] = doc.get('arrival', time.time() * 1000000) doc['id'] = doc.get('id', str(uuid.uuid4())) doc['name'] = doc.get('name', doc['id']) doc['type'] = doc.get('type', '') # If a UUID has been supplied, we want to erase any old record bearing that name. cur = self.threadLocal.conn.cursor() cur.execute( 'SELECT json_extract(json,"$.time") FROM document WHERE json_extract(json,"$.id")=?', (doc['id'], )) x = cur.fetchone() d = jsonEncode(doc) # If we are generating a new message, sign it automatically. if not signature: signature = libnacl.crypto_sign( libnacl.crypto_generichash(d.encode('utf8')), self.secretKey) if x: # Check that record we are trying to insert is newer, else ignore if x[0] < doc['time']: self.threadLocal.conn.execute( "UPDATE document SET json=?, signature=? WHERE json_extract(json,'$.id')=?", (d, signature, doc['id'])) # If we are marking this as deleted, we can ditch everything that depends on it. # We don't even have to just set them as deleted, we can relly delete them, the deleted parent record # is enough for other nodes to know this shouldn't exist anymore. if doc['type'] == "null": self.threadLocal.conn.execute( "DELETE FROM document WHERE json_extract(json,'$.id')=?", (doc['id'], )) return doc['id'] else: return doc['id'] self.threadLocal.conn.execute( "INSERT INTO document VALUES (null,?,?,?)", (d, signature, '')) return doc['id']
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 new(cls, vk, sk, msg): # type: (str, str, str) -> Signature return cls(pb.Signature(vk=vk, signed_document=libnacl.crypto_sign(msg, sk)))
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 signRequest(sk, request): sig = libnacl.crypto_sign(request, sk)[:libnacl.crypto_sign_BYTES] signature = keyToKey64u(sig) return signature
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 signResource(resource, sKey): sig = libnacl.crypto_sign(resource, sKey) sig = sig[:libnacl.crypto_sign_BYTES] return keyToKey64u(sig)
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)