def test_crypto_sign_open(self): pk, sk = pysodium.crypto_sign_keypair() signed = pysodium.crypto_sign(b'howdy', sk) changed = signed[:pysodium.crypto_sign_BYTES] + b'0' + signed[ pysodium.crypto_sign_BYTES + 1:] pysodium.crypto_sign_open(signed, pk) self.assertRaises(ValueError, pysodium.crypto_sign_open, changed, pk)
def change(self, data): # needs id, challenge, sig(id) # returns output from ./response | fail try: pk = self.getpk(data) except: return b'fail' try: data = pysodium.crypto_sign_open(data, pk) except ValueError: print('invalid signature') return b'fail' id = data[1:33] chal = data[33:65] tdir = os.path.expanduser(datadir + binascii.hexlify(id).decode()) k = pysodium.randombytes(32) with open(tdir + '/new', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(k) try: rule = readf(tdir + "/rule") except: return b'fail' try: return respond(chal, id, secret=k) except ValueError: if verbose: print("respond fail") return b'fail'
def loadkey(self, type): if type in ['mp', 'cp', 'sp', 'created', 'valid']: with open(get_pk_filename(self.basedir, self.name), 'rb') as fd: tmp = fd.read() mk = tmp[nacl.crypto_sign_BYTES:nacl.crypto_sign_BYTES + nacl.crypto_sign_PUBLICKEYBYTES] tmp = nacl.crypto_sign_open(tmp, mk) if type == 'mp': self.mp = mk i = nacl.crypto_sign_PUBLICKEYBYTES if type == 'sp': self.sp = tmp[i:i + nacl.crypto_sign_PUBLICKEYBYTES] i += nacl.crypto_sign_PUBLICKEYBYTES if type == 'cp': self.cp = tmp[i:i + nacl.crypto_box_PUBLICKEYBYTES] i += nacl.crypto_box_PUBLICKEYBYTES self.created = parse_isodatetime(tmp[i:i + 32]) self.valid = parse_isodatetime(tmp[i + 32:i + 64]) elif type in ['cs', 'ss']: tmp = get_sk_filename(self.basedir, self.name) if os.path.exists(tmp): tmp = self.decrypt_with_user_pw(tmp, 'subkeys') if type == 'ss': self.ss = tmp[:nacl.crypto_sign_SECRETKEYBYTES] if type == 'cs': self.cs = tmp[nacl.crypto_sign_SECRETKEYBYTES:] elif type == 'ms': tmp = get_sk_filename(self.basedir, self.name, ext='mk') if os.path.exists(tmp): self.ms = self.decrypt_with_user_pw(tmp, 'master key')
def verify(msg, master=False, basedir=None): for keys in get_public_keys(basedir=basedir or pbp.defaultbase): try: verifying_key = keys.mp if master else keys.sp return keys.name, nacl.crypto_sign_open(msg, verifying_key) except ValueError: pass
def loadkey(self, type): if type in ['mp','cp','sp', 'created', 'valid']: with open(get_pk_filename(self.basedir, self.name), 'rb') as fd: tmp=fd.read() mk=tmp[nacl.crypto_sign_BYTES:nacl.crypto_sign_BYTES+nacl.crypto_sign_PUBLICKEYBYTES] tmp = nacl.crypto_sign_open(tmp, mk) if type == 'mp': self.mp=mk i=nacl.crypto_sign_PUBLICKEYBYTES if type == 'sp': self.sp=tmp[i:i+nacl.crypto_sign_PUBLICKEYBYTES] i+=nacl.crypto_sign_PUBLICKEYBYTES if type == 'cp': self.cp=tmp[i:i+nacl.crypto_box_PUBLICKEYBYTES] i+=nacl.crypto_box_PUBLICKEYBYTES self.created = parse_isodatetime(tmp[i:i + 32].decode('utf-8')) self.valid = parse_isodatetime(tmp[i + 32:i + 64].decode('utf-8')) elif type in ['cs', 'ss']: tmp = get_sk_filename(self.basedir, self.name) if os.path.exists(tmp): tmp = self.decrypt_with_user_pw(tmp, '%s subkey' % ('signing' if type == 'ss' else 'encryption')) if type == 'ss': self.ss = tmp[:nacl.crypto_sign_SECRETKEYBYTES] if type == 'cs': self.cs = tmp[nacl.crypto_sign_SECRETKEYBYTES:] else: raise ValueError("missing key %s" % self.name) elif type == 'ms': tmp = get_sk_filename(self.basedir, self.name, ext='mk') if os.path.exists(tmp): self.ms = self.decrypt_with_user_pw(tmp, 'master key') else: raise ValueError("missing key %s" % self.name)
def create(self, data): # needs pubkey, id, challenge, sig(id) # returns output from ./response | fail pk = data[129:161] try: data = pysodium.crypto_sign_open(data, pk) except ValueError: print('invalid signature') return b'fail' id = data[1:33] chal = data[33:65] tdir = datadir + binascii.hexlify(id).decode() if os.path.exists(tdir): print(tdir, 'exists') return b'fail' # key already exists os.mkdir(tdir, 0o700) with open(tdir + '/pub', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(pk) key = pysodium.randombytes(32) with open(tdir + '/key', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(key) return respond(chal, id)
def loadkey(self, type): if type in ["mp", "cp", "sp", "created", "valid"]: with open(get_pk_filename(self.basedir, self.name), "r") as fd: tmp = fd.read() mk = tmp[nacl.crypto_sign_BYTES : nacl.crypto_sign_BYTES + nacl.crypto_sign_PUBLICKEYBYTES] tmp = nacl.crypto_sign_open(tmp, mk) if type == "mp": self.mp = mk i = nacl.crypto_sign_PUBLICKEYBYTES if type == "sp": self.sp = tmp[i : i + nacl.crypto_sign_PUBLICKEYBYTES] i += nacl.crypto_sign_PUBLICKEYBYTES if type == "cp": self.cp = tmp[i : i + nacl.crypto_box_PUBLICKEYBYTES] i += nacl.crypto_box_PUBLICKEYBYTES self.created = parse_isodatetime(tmp[i : i + 32]) self.valid = parse_isodatetime(tmp[i + 32 : i + 64]) elif type in ["cs", "ss"]: tmp = get_sk_filename(self.basedir, self.name) if os.path.exists(tmp): tmp = self.decrypt_with_user_pw(tmp, "%s subkey" % ("signing" if type == "ss" else "encryption")) if type == "ss": self.ss = tmp[: nacl.crypto_sign_SECRETKEYBYTES] if type == "cs": self.cs = tmp[nacl.crypto_sign_SECRETKEYBYTES :] else: raise ValueError("missing key") elif type == "ms": tmp = get_sk_filename(self.basedir, self.name, ext="mk") if os.path.exists(tmp): self.ms = self.decrypt_with_user_pw(tmp, "master key") else: raise ValueError("missing key")
def data_received(self, data): if verbose: print('Data received: ', data) try: data = pysodium.crypto_sign_open(data, self.handler.getserverkey()) except ValueError: raise ValueError('invalid signature.\nabort') if data!=b'ok' and (data[:-42] == b'fail' or len(data)!=sphinxlib.DECAF_255_SER_BYTES+42): raise ValueError('fail') if not self.b: self.cb() return rwd=sphinxlib.finish(self.pwd, self.b, data[:sphinxlib.DECAF_255_SER_BYTES]) if self.handler.namesite is not None: if self.handler.namesite['name'].encode() not in self.handler.list(self.handler.namesite['site']): self.handler.cacheuser(self.handler.namesite) rule = data[sphinxlib.DECAF_255_SER_BYTES:] if len(rule)!=42: raise ValueError('fail') rk = pysodium.crypto_generichash(self.handler.getkey(),self.handler.getsalt()) rule = pysodium.crypto_secretbox_open(rule[24:], rule[:24],rk) rule = struct.unpack(">H",rule)[0] size = (rule & 0x7f) rule = {c for i,c in enumerate(('u','l','s','d')) if (rule >> 7) & (1 << i)} self.cb(bin2pass.derive(rwd,rule,size).decode())
def loadkey(self, type): if type in ['mp','cp','sp', 'created', 'valid']: with open(get_pk_filename(self.basedir, self.name), 'r') as fd: tmp=fd.read() mk=tmp[nacl.crypto_sign_BYTES:nacl.crypto_sign_BYTES+nacl.crypto_sign_PUBLICKEYBYTES] tmp = nacl.crypto_sign_open(tmp, mk) if type == 'mp': self.mp=mk i=nacl.crypto_sign_PUBLICKEYBYTES if type == 'sp': self.sp=tmp[i:i+nacl.crypto_sign_PUBLICKEYBYTES] i+=nacl.crypto_sign_PUBLICKEYBYTES if type == 'cp': self.cp=tmp[i:i+nacl.crypto_box_PUBLICKEYBYTES] i+=nacl.crypto_box_PUBLICKEYBYTES self.created = parse_isodatetime(tmp[i:i + 32]) self.valid = parse_isodatetime(tmp[i + 32:i + 64]) elif type in ['cs', 'ss']: tmp = get_sk_filename(self.basedir, self.name) if os.path.exists(tmp): tmp = self.decrypt_with_user_pw(tmp, 'subkeys') if type == 'ss': self.ss = tmp[:nacl.crypto_sign_SECRETKEYBYTES] if type == 'cs': self.cs = tmp[nacl.crypto_sign_SECRETKEYBYTES:] elif type == 'ms': tmp = get_sk_filename(self.basedir, self.name, ext='mk') if os.path.exists(tmp): self.ms = self.decrypt_with_user_pw(tmp, 'master key')
def sync(self, pk, payload): """Update hg and return new event ids in topological order.""" info = crypto_sign(dumps({c: self.height[h] for c, h in self.can_see[self.head].items()}), self.sk) msg = crypto_sign_open(self.network[pk](self.pk, info), pk) remote_head, remote_hg = loads(msg) new = tuple(toposort(remote_hg.keys() - self.hg.keys(), lambda u: remote_hg[u].p)) for h in new: ev = remote_hg[h] if self.is_valid_event(h, ev): self.add_event(h, ev) if self.is_valid_event(remote_head, remote_hg[remote_head]): h, ev = self.new_event(payload, (self.head, remote_head)) # this really shouldn't fail, let's check it to be sure assert self.is_valid_event(h, ev) self.add_event(h, ev) self.head = h return new + (h,)
def commit(self, data): # needs id, sig(id) try: pk = self.getpk(data) except: return b'fail' try: data = pysodium.crypto_sign_open(data, pk) except ValueError: print('invalid signature') return b'fail' id = data[1:33] tdir = os.path.expanduser(datadir + binascii.hexlify(id).decode()) try: with open(tdir + '/new', 'rb') as fd: k = fd.read() except FileNotFoundError: return b'fail' if (len(k) != 32): return b'fail' with open(tdir + '/key', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(k) os.unlink(tdir + '/new') return b'ok'
def verify_signed_message(signed: bytes, verkey: bytes) -> bool: """ Verify a signed message according to a public verification key. Args: signed: The signed message verkey: The verkey to use in verification Returns: True if verified, else False """ try: pysodium.crypto_sign_open(signed, verkey) except ValueError: return False return True
def proof_open(team, proof): assert isinstance(proof, bytes) proof = b64decode(proof) claimed_chall_id = proof[2 * 64:].decode('utf-8') claimed_chall = Challenge(claimed_chall_id) chall_pk = claimed_chall['pk'] team_pk = team['sign_pk'] membership_proof = pysodium.crypto_sign_open(proof, chall_pk) chall_id = pysodium.crypto_sign_open(membership_proof, team_pk).decode('utf-8') if claimed_chall_id != chall_id: raise ValueError('invalid proof') return claimed_chall
def get_public_key(ip, port, provider_key, provider_url): '''Get public key from provider.''' header = DnsHeader() question = DnsQuestion() question.labels = provider_url.split('.') question.qtype = 16 # TXT record packet = DnsPacket(header) packet.addQuestion(question) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) dest = (ip, port) sock.sendto(packet.toBinary(), dest) (response, address) = sock.recvfrom(1024) bincerts = find_certificates(response) if not bincerts: raise DnscryptException("No certificate received.") certificates = [] for bincert in bincerts: certificates.append(Certificate(bincert)) certificate = max(certificates, key=lambda x: x.serial and not x.expired()) if certificate.expired(): raise DnscryptException("Certificate expired.") if USE_LOCAL_LIBS: try: import pysodium return pysodium.crypto_sign_open( certificate.bincert, provider_key.decode('hex')), certificate.magic_query except ImportError: pass try: import nacl import nacl.bindings return nacl.bindings.crypto_sign_open( certificate.bincert, provider_key.decode('hex')), certificate.magic_query except ImportError: pass import ed25519py return ed25519py.crypto_sign_open( certificate.bincert, provider_key.decode('hex')), certificate.magic_query
def ask_sync(self, pk, info): """Respond to someone wanting to sync (only public method).""" # TODO: only send a diff? maybe with the help of self.height # TODO: thread safe? (allow to run while mainloop is running) cs = loads(crypto_sign_open(info, pk)) subset = {h: self.hg[h] for h in bfs( (self.head,), lambda u: (p for p in self.hg[u].p if self.hg[p].c not in cs or self.height[p] > cs[self.hg[p].c]))} msg = dumps((self.head, subset)) return crypto_sign(msg, self.sk)
def get_public_key(ip, port, provider_key, provider_url): '''Get public key from provider.''' header = DnsHeader() question = DnsQuestion() question.labels = provider_url.split('.') question.qtype = 16 # TXT record packet = DnsPacket(header) packet.addQuestion(question) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) dest = (ip, port) sock.sendto(packet.toBinary(), dest) (response, address) = sock.recvfrom(1024) bincerts = find_certificates(response) if not bincerts: raise DnscryptException("No certificate received.") certificates = [] for bincert in bincerts: certificates.append(Certificate(bincert)) certificate = max(certificates, key=lambda x: x.serial and not x.expired()) if certificate.expired(): raise DnscryptException("Certificate expired.") if USE_LOCAL_LIBS: try: import pysodium return pysodium.crypto_sign_open(certificate.bincert, provider_key.decode('hex')), certificate.magic_query except ImportError: pass try: import nacl import nacl.bindings return nacl.bindings.crypto_sign_open(certificate.bincert, provider_key.decode('hex')), certificate.magic_query except ImportError: pass import ed25519py return ed25519py.crypto_sign_open(certificate.bincert, provider_key.decode('hex')), certificate.magic_query
def parse_innerbox(bytes_): pubkey, rawsigned = mid_pack.unpack(bytes_) try: signed_message = pysodium.crypto_sign_open(rawsigned, pubkey) except: raise SignatureError() inner_ver, ts, seq, signed_message, payload = \ inner_pack.unpack(signed_message) record = Record(pubkey=pubkey, \ inner_ver=inner_ver, \ ts=ts, \ seq=seq, \ rawsig=rawsigned, \ payload=payload) return record
def get(self, data): # needs id, challenge, sig(id) # returns output from ./response | fail try: pk = self.getpk(data) except: return b'fail' try: data = pysodium.crypto_sign_open(data, pk) except ValueError: print('invalid signature') return b'fail' id = data[1:33] chal = data[33:65] return respond(chal, id)
def delete(self, data): # needs id, sig(id) # returns ok | fail try: pk = self.getpk(data) except: return b'fail' try: data = pysodium.crypto_sign_open(data, pk) except ValueError: print('invalid signature') return b'fail' id = data[1:33] tdir = datadir + binascii.hexlify(id).decode() shutil.rmtree(tdir) return b'ok'
def import_handler(infile=None, basedir=None): # imports ascii armored key from infile or stdin to basedir if not infile: b85 = sys.stdin.readline().strip() else: with file(infile) as fd: b85 = fd.readline().strip() pkt = b85decode(b85) mp = pkt[nacl.crypto_sign_BYTES:nacl.crypto_sign_BYTES+nacl.crypto_sign_PUBLICKEYBYTES] keys = nacl.crypto_sign_open(pkt, mp) if not keys: return name = keys[nacl.crypto_sign_PUBLICKEYBYTES*3:] peer = publickey.Identity(name, basedir=basedir) peer.mp = mp peer.cp = keys[nacl.crypto_sign_PUBLICKEYBYTES:nacl.crypto_sign_PUBLICKEYBYTES*2] peer.sp = keys[nacl.crypto_sign_PUBLICKEYBYTES*2:nacl.crypto_sign_PUBLICKEYBYTES*3] # TODO check if key exists, then ask for confirmation of pk overwrite peer.save() return name
def parse_and_validate_redirect_url(self, url: str, state: str): data_object = parse_signed_attempt_from_url(url) signed_attempt, double_name, rest = ( lambda signedAttempt, doubleName, **rest: (signedAttempt, doubleName, rest))( **data_object) user_public_key = self.get_public_key_for_double_name(double_name) sign_result = pysodium.crypto_sign_open( b64decode(signed_attempt), user_public_key ) sign_result_dict = json.loads(sign_result.decode("utf-8")) if sign_result_dict['signedState'] != state: raise ValueError('state could not be matched') if sign_result_dict['doubleName'] != double_name: raise ValueError('The name cannot be matched.') if sign_result_dict['appId'] != self.app_id: raise ValueError('The appId cannot be matched.') encrypted_data = sign_result_dict['data'] keyPair = generate_key_pair(self.seed_phrase) profile_data = decrypt( encrypted_data['ciphertext'], encrypted_data['nonce'], keyPair[1], user_public_key ) return { 'selectedImageId': sign_result_dict['selectedImageId'], 'randomRoom': sign_result_dict['randomRoom'], 'profile': json.loads(profile_data), }
def import_handler(infile=None, basedir=None): # imports ascii armored key from infile or stdin to basedir if not infile: b85 = sys.stdin.readline().strip() else: with open(infile, 'r') as fd: b85 = fd.readline().strip() pkt = b85decode(b85) mp = pkt[nacl.crypto_sign_BYTES:nacl.crypto_sign_BYTES+nacl.crypto_sign_PUBLICKEYBYTES] keys = nacl.crypto_sign_open(pkt, mp) if not keys: return name = keys[(nacl.crypto_sign_PUBLICKEYBYTES*3)+2*32:].decode('utf-8') kfile = publickey.get_pk_filename(basedir, name) if os.path.exists(kfile): bkp = kfile+'.old' print >>sys.stderr, "backing up existing key to %s" % bkp os.rename(kfile,bkp) with open(kfile, 'wb') as fd: fd.write(pkt) # TODO check if key exists, then ask for confirmation of pk overwrite return name
def change(self, data): # needs id, challenge, sig(id) # returns output from ./response | fail try: pk = self.getpk(data) except: return b'fail' try: data = pysodium.crypto_sign_open(data, pk) except ValueError: print('invalid signature') return b'fail' id = data[1:33] chal = data[33:65] tdir = datadir + binascii.hexlify(id).decode() key = pysodium.randombytes(32) with open(tdir + '/key', 'wb') as fd: os.fchmod(fd.fileno(), 0o600) fd.write(key) return respond(chal, id)
def data_received(self, data): if verbose: print('Data received: {!r}'.format(data.decode())) try: data = pysodium.crypto_sign_open(data, serverkey) except ValueError: print('invalid signature.\nabort') return if data == b'fail': print('fail') return if not self.b: return rwd = sphinx.finish(self.b, data) rule = getrule(datadir, id) if not rule: print("no password rule defined for this password.") rule, size = rule print(bin2pass.derive(rwd, rule, size).decode())
def import_handler(infile=None, basedir=None): if not infile: b85 = sys.stdin.readline().strip() else: with open(infile, 'rb') as fd: b85 = fd.readline().strip() pkt = b85decode(b85) mp = pkt[nacl.crypto_sign_BYTES:nacl.crypto_sign_BYTES + nacl.crypto_sign_PUBLICKEYBYTES] keys = nacl.crypto_sign_open(pkt, mp) if not keys: die("invalid key") name = keys[nacl.crypto_sign_PUBLICKEYBYTES * 3:] peer = publickey.Identity(name, basedir=basedir) peer.mp = mp peer.cp = keys[nacl. crypto_sign_PUBLICKEYBYTES:nacl.crypto_sign_PUBLICKEYBYTES * 2] peer.sp = keys[nacl.crypto_sign_PUBLICKEYBYTES * 2:nacl.crypto_sign_PUBLICKEYBYTES * 3] # TODO check if key exists, then ask for confirmation of pk overwrite peer.save() print('Success: imported public keys for', name)
def loadkey(self, type): if type in ['mp', 'cp', 'sp', 'created', 'valid']: with open(get_pk_filename(self.basedir, self.name), 'rb') as fd: tmp = fd.read() mk = tmp[nacl.crypto_sign_BYTES:nacl.crypto_sign_BYTES + nacl.crypto_sign_PUBLICKEYBYTES] tmp = nacl.crypto_sign_open(tmp, mk) if type == 'mp': self.mp = mk i = nacl.crypto_sign_PUBLICKEYBYTES if type == 'sp': self.sp = tmp[i:i + nacl.crypto_sign_PUBLICKEYBYTES] i += nacl.crypto_sign_PUBLICKEYBYTES if type == 'cp': self.cp = tmp[i:i + nacl.crypto_box_PUBLICKEYBYTES] i += nacl.crypto_box_PUBLICKEYBYTES self.created = parse_isodatetime(tmp[i:i + 32].decode('utf-8')) self.valid = parse_isodatetime(tmp[i + 32:i + 64].decode('utf-8')) elif type in ['cs', 'ss']: tmp = get_sk_filename(self.basedir, self.name) if os.path.exists(tmp): tmp = self.decrypt_with_user_pw( tmp, '%s subkey' % ('signing' if type == 'ss' else 'encryption')) if type == 'ss': self.ss = tmp[:nacl.crypto_sign_SECRETKEYBYTES] if type == 'cs': self.cs = tmp[nacl.crypto_sign_SECRETKEYBYTES:] else: raise ValueError("missing key %s" % self.name) elif type == 'ms': tmp = get_sk_filename(self.basedir, self.name, ext='mk') if os.path.exists(tmp): self.ms = self.decrypt_with_user_pw(tmp, 'master key') else: raise ValueError("missing key %s" % self.name)
def verify(self, msg, master=False): try: return nacl.crypto_sign_open(msg, self.mp if master else self.sp) except ValueError: return
def test_crypto_sign_open(self): pk, sk = pysodium.crypto_sign_keypair() signed = pysodium.crypto_sign(b'howdy', sk) changed = signed[:pysodium.crypto_sign_BYTES] + b'0' + signed[pysodium.crypto_sign_BYTES + 1:] pysodium.crypto_sign_open(signed, pk) self.assertRaises(ValueError, pysodium.crypto_sign_open, changed, pk)
import pysodium pk=None sk=None with open("keys/sign_public.key", "rb") as in_file: pk = in_file.read() with open("keys/sign_private.key", "rb") as in_file: sk = in_file.read() signed = pysodium.crypto_sign(b'test', sk) ret=pysodium.crypto_sign_open(signed, pk) print(ret)
def decrypt_payload(payload, pubkey): return crypto_sign_open(payload, pubkey)
#!/usr/bin/python3 import msgpack import base64 import pysodium rot = base64.b64decode('kwDEAZDEIHn1MDouHBP7X1w945IARpSuHVVsCdwAA7B4E2+AWXKh') chain = base64.b64decode('chain-to-analyze') try: chain = msgpack.unpackb(chain, raw=False) legacy = False except: print("Warning: Legacy chain.") legacy = True chain = msgpack.unpackb(chain, raw=True) chain = [rot] + chain pk = None for npk in chain: if pk != None: pk = msgpack.unpackb(pysodium.crypto_sign_open(npk, pk[2]), raw=legacy) else: pk = msgpack.unpackb(npk, raw=legacy) print("Raw Key:", base64.b64encode(msgpack.packb(pk, use_bin_type=(not legacy)))) print("Timestamp:", pk[0]) print("Posion:", msgpack.unpackb(pk[1], raw=legacy)) print("Key:", pk[2].hex()) print("")
query.write(protocolOut) bytes = transportOut.getvalue() sign_pk=None sign_sk=None with open("keys/sign_public.key", "rb") as in_file: sign_pk = in_file.read() with open("keys/sign_private.key", "rb") as in_file: sign_sk = in_file.read() signed = pysodium.crypto_sign(bytes, sign_sk) base64bytes=base64.b64encode(signed) #assert can verify and de-serialize recoveredbytes=base64.b64decode(base64bytes) plaintextbytes=pysodium.crypto_sign_open(recoveredbytes, sign_pk) transportIn = TTransport.TMemoryBuffer(plaintextbytes) protocolIn = TBinaryProtocol.TBinaryProtocol(transportIn) recoveredqueries = Query() recoveredqueries.read(protocolIn) print(recoveredqueries) queryFile = open ("queries/ucla.query", "wb") querybytearray=bytearray(base64bytes) queryFile.write(querybytearray) keyfile=os.path.join(".","keys/sign_public.key") with open(keyfile, "rb") as in_file: sign_pk = in_file.read()
def process_chain(chain, topic=None, usage=None, allowlist=None, denylist=None): # # chain should be a single msgpack array, with the next item in the array # signed by the entity with public key given in the current item. The first # item must be signed by a root of trust (which are given in allowlist). # Each (signed) item is itself a msgpack array containing: # (0) a max_age timestamp (64-bit unsigned unix maximum time signature is valid) # (1) a poison array. Sets allowed signature key usages, topics, pathlengths. # (2) public key # Possibly more items in (3)+, especially common for the final item, # but not needed to check the chain. # # Raises a ValueError if chain does not match topic or usage criteria, or # uses a denylisted key, unless there is ultimately a chain between # an allowlisted key and the final item with no denylisted keys. # The final item might itself be the allowlisted key. # # Otherwise, returns an array containing two arrays. The first array # contains: # (0) The minimum max_age timestamp # (1) The intersection of allowed topics and usages, in the # poison array (i.e. the net allowed topics and usages) # (2) The public key # And any items in (3)+ from the final item. # The second array contains one entry per item in the chain, containing # a textual / human readable description (useful for verbose messages) of # how the item was interpreted. # printable = [] if allowlist is None: raise ProcessChainError("No possible roots of trust!", printable) last_error = ProcessChainError("No roots of trust found!", printable) for rot in allowlist: printable = [] try: denylisted = False val = [rot] + msgpack.unpackb(chain, raw=True) if len(val) < 2: # must be validating at least one chain item beyond the item from the allowlist raise ValueError("Chain too short!") pk = None for npk in val: if not (pk is None): if key_in_list(pk[2], denylist) != None: denylisted = True logging.warning( "Chain uses denylisted signing key %s.", pk[2].hex()) # this is not immediately fatal because a subkey might be allowlisted elif key_in_list(pk[2], allowlist) != None: # allowlisted subkey overrides denylist denylisted = False pk = intersect_certs( pk, msgpack.unpackb(key_in_list(pk[2], allowlist), raw=True), True) try: pk = intersect_certs( pk, msgpack.unpackb(pysodium.crypto_sign_open( npk, pk[2]), raw=True), False) except: raise ValueError("Invalid signing!") else: pk = msgpack.unpackb(npk, raw=True) # root is unsigned printable.append(str(printable_cert(pk))) # must finally check if leaf key is in allowlist/denylist if key_in_list(pk[2], allowlist) != None: denylisted = False if key_in_list(pk[2], denylist) != None: denylisted = True # make sure our chain doesn't have breaking denylisted keys if denylisted: raise ValueError("Chain uses denylisted public key") # ensure composite chain is valid if (pk[0] < time() and pk[0] != 0): raise ValueError("Expired Chain!") if not validate_poison('topics', topic, pk): raise ValueError( "No matching topic in allowed intersection set.") if not validate_poison('usages', usage, pk): raise ValueError( "No matching usage in allowed intersection set.") if not validate_poison('pathlen', 0, pk): raise ValueError("Exceeded allowed pathlen.") return [pk, printable] except ValueError as e: printable.append(str(e)) last_error = ProcessChainError("Error during Validation:", printable) # We allow a key to self-sign itself to be denylisted. This enables any private # key to denylist itself try: chain = msgpack.unpackb(chain, raw=True) if len(chain) == 2: pk = msgpack.unpackb(chain[0], raw=True) pk0 = pk[2] pk = intersect_certs( pk, msgpack.unpackb(pysodium.crypto_sign_open(chain[1], pk[2]), raw=True), False) if pk0 == pk[2] and multimatch( usage, ['key-denylist']) and validate_poison( 'usages', 'key-denylist', pk) and validate_poison( 'pathlen', 0, pk): return [pk, [str(printable_cert(pk))]] except: pass raise last_error