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'
Example #2
0
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'
Example #3
0
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')
Example #4
0
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')
Example #5
0
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'
Example #7
0
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)