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 sphinxlib.respond(chal, k) + rule except ValueError: if verbose: print("respond fail") return b'fail'
def respond(chal, id, secret=None): path = os.path.expanduser(datadir + binascii.hexlify(id).decode()) if not secret: try: secret = readf(path + '/key') except ValueError: return b'fail' # key not found if len(secret) != sphinxlib.DECAF_255_SCALAR_BYTES: if verbose: print("secret wrong size") return b'fail' try: rule = readf(path + '/rule') except ValueError: return b'fail' # key not found with open(path + '/xpub', 'rb') as fd: xpk = fd.read() rule = pysodium.crypto_box_seal(rule, xpk) try: return sphinxlib.respond(chal, secret) + rule except ValueError: if verbose: print("respond fail") return b'fail'
def create(s, msg): if len(msg) != 65: fail(s) print('Data received:', msg.hex()) op, msg = pop(msg, 1) id, msg = pop(msg, 32) alpha, msg = pop(msg, 32) # check if id is unique id = binascii.hexlify(id).decode() tdir = os.path.join(datadir, id) if (os.path.exists(tdir)): fail(s) # 1st step OPRF with a new seed k = pysodium.randombytes(32) try: beta = sphinxlib.respond(alpha, k) except: fail(s) s.send(beta) # wait for auth signing pubkey and rules msg = s.recv(32 + RULE_SIZE + 64) # pubkey, rule, signature if len(msg) != 32 + RULE_SIZE + 64: fail(s) # verify auth sig on packet pk = msg[0:32] try: msg = verify_blob(msg, pk) except ValueError: fail(s) rules = msg[32:] # 3rd phase update_blob(s) # add user to host record if not os.path.exists(datadir): os.mkdir(datadir, 0o700) os.mkdir(tdir, 0o700) save_blob(id, 'key', k) save_blob(id, 'pub', pk) save_blob(id, 'rules', rules) s.send(b'ok')
def change(conn, msg): op, msg = pop(msg, 1) id, msg = pop(msg, 32) alpha, msg = pop(msg, 32) if msg != b'': if verbose: print('invalid get msg, trailing content %r' % msg) fail(conn) id = binascii.hexlify(id).decode() tdir = os.path.join(datadir, id) if not os.path.exists(tdir): if verbose: print("%s doesn't exist" % tdir) fail(conn) auth(conn, id, alpha) alpha = conn.recv(32) if (len(alpha) != 32): fail(conn) k = pysodium.randombytes(32) try: beta = sphinxlib.respond(alpha, k) except: fail(conn) conn.send(beta) blob = conn.recv(32 + RULE_SIZE + 64) if len(blob) != 32 + RULE_SIZE + 64: fail(conn) pk = blob[:32] try: rules = verify_blob(blob, pk)[32:] except ValueError: fail(conn) save_blob(id, 'new', k) save_blob(id, "rules.new", rules) save_blob(id, "pub.new", pk) conn.send(b'ok')
def auth(s, id, alpha): pk = load_blob(id, 'pub', 32) if pk is None: print('no pubkey found in %s' % id) fail(s) nonce = pysodium.randombytes(32) k = load_blob(id, 'key') if k is not None: try: beta = sphinxlib.respond(alpha, k) except: fail(s) else: beta = b'' s.send(b''.join([beta, nonce])) sig = s.recv(64) try: pysodium.crypto_sign_verify_detached(sig, nonce, pk) except: print('bad sig') fail(s)
def respond(chal, id): path = os.path.expanduser(datadir + binascii.hexlify(id).decode()) try: secret = readf(path + '/key') except ValueError: return b'fail' # key not found if len(secret) != sphinxlib.DECAF_255_SCALAR_BYTES: if verbose: print("secret wrong size") return b'fail' try: rule = readf(path + '/rule') except ValueError: return b'fail' # key not found try: return sphinxlib.respond(chal, secret) + rule except ValueError: if verbose: print("respond fail") return b'fail'
def get(conn, msg): _, msg = pop(msg, 1) id, msg = pop(msg, 32) alpha, msg = pop(msg, 32) if msg != b'': if verbose: print('invalid get msg, trailing content %r' % msg) fail(conn) id = binascii.hexlify(id).decode() k = load_blob(id, 'key', 32) if k is None: # maybe execute protocol with static but random value to not leak which host ids exist? fail(conn) rules = load_blob(id, 'rules', RULE_SIZE) if rules is None: fail(conn) try: beta = sphinxlib.respond(alpha, k) except: fail(conn) conn.send(beta + rules)