Exemple #1
0
def send_command(args, callback=lambda sock: print("Connected", sock)):
    """connects to the server and sends the command

    :param args:   this object is similar to the one parsed from the commandline,
        contains "host" and "port" members
    :param callback(sock, respjson): a function to call when connected to the server.
        sock:   Gets passed the socket object, the socket object at this point is already connected and is ready to send or recv.
    :return the callback result
    """

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        print('connecting to server...', end='')
        s.connect((args['host'], args['port']))  # connect
        print('\rConnection established                       ')

        args['auth'] = False
        # setup IV
        args['iv'] = secrets.token_bytes(16)
        request_json = format_args_to_json(args)

        # send the command/request json
        send_msg(s, _string_to_bytes(request_json))

        # check if server acknowledged the command
        # (if resp is included in one of the success response codes)
        resp = recv_msg(s)
        resp_json = json.loads(_bytes_to_string(resp))
        if resp_json['readystate'] in [202]:
            res = callback(s)

            send_msg(s, b'200')  # send OK code
            print('\nTransaction complete')
            return res
Exemple #2
0
def h256(*args):
    sha256 = hashlib.sha256()

    for arg in args:
        if isinstance(arg, int):
            arg = int_to_bytes(arg)
        if isinstance(arg, str):
            arg = _string_to_bytes(arg)
        sha256.update(arg)

    return sha256.digest()
Exemple #3
0
    def callback(conn: socket):
        ciphertext = b''
        with open(filename, 'rb') as f:
            data = f.read()
            ciphertext = args['cipherfunc'](data=data,
                                            key=args['key'],
                                            iv=args['iv'])

        return send_msg(
            conn,
            _string_to_bytes(
                json.dumps({
                    'filename': filename,
                    'data': _bytes_to_string(ciphertext),
                    'iv': _bytes_to_string(args['iv']),
                })))
Exemple #4
0
def recv_next_command(conn: socket, client_parser=None):
    """
    waits for a command by the client, and returns the parsed args,
    responds to the client with 202 and data on success

    :param conn: socket connection
    :return: client command arguments, or None if invalid command
    """
    command_json = _bytes_to_string(recv_msg(conn))
    print("received req:", command_json)

    client_args = parse_command_json(command_json)

    server_resp = _string_to_bytes(
        json.dumps({
            'readystate': 202,  # code "202" meaning (accepted)
        }))
    send_msg(conn, server_resp)
    return client_args
Exemple #5
0
def get(conn: socket, args=None):
    # send the file to client
    if args['file_index']:
        args['filename'] = os.listdir('server_files')[int(args['filename'])]

    iv = secrets.token_bytes(16)
    print('iv=', iv)

    filename = os.path.join('server_files', path_leaf(args['filename']))
    with open(filename, 'rb') as f:
        plaintext = f.read()
        ciphertext = args['cipherfunc'](data=plaintext, key=args['key'], iv=iv)

    print("finished reading file \"{}\", {}B".format(filename,
                                                     len(ciphertext)))

    return send_msg(
        conn,
        _string_to_bytes(
            json.dumps({
                'filename': filename,
                'data': _bytes_to_string(ciphertext),
                'iv': _bytes_to_string(iv),
            })))
Exemple #6
0
def parse_command_json(command_json):
    client_args = {  # extend defaults
        'auth': True,
        'file_index': None,
        'local': False,
        'key': DEFAULT_KEY,
        'cipher': 'none',
        'filename': '',
        'function': lambda x: None,
        'iv': None,
    }
    client_args.update(json.loads(command_json))  # update
    # converting args (parsing strings to bytes and function names to functions)
    client_args['cipherfunc'] = getattr(CipherLib, client_args['cipher'])
    client_args['iv'] = _string_to_bytes(client_args['iv'])
    client_args['function'] = eval(client_args['function'])

    # printing object:
    import pprint
    pp = pprint.PrettyPrinter(indent=4)
    print('client_args received')
    pp.pprint(client_args)

    return client_args
Exemple #7
0
def ls(conn: socket, args=None):
    # send list of files
    filelist = os.listdir('server_files/')
    filelist_json = json.dumps(filelist)
    send_msg(conn, _string_to_bytes(filelist_json))
Exemple #8
0
 def none(data, decrypt=False, key=None, **kwargs) -> bytes:
     if isinstance(data, str):
         data = _string_to_bytes(data)
     return data
Exemple #9
0
def authenticate(args, is_client=True, conn=None):
    ## setting up asymmetric key
    # n, e, d, q, p = init_asym_key(is_client)
    # pubkey = rsa.PublicKey(n, e)
    # privkey = rsa.PrivateKey(n, e, d, q, p)

    pubkey, privkey = rsa.newkeys(2048, poolsize=8)

    ## setting up Diffie Hellmen
    # Alice is the client, Bob is the server
    exp, g, m = init_DiffieHellman()
    # g_x_mod_m = (g ** exp) % m
    g_x_mod_m = exp_mod(g, exp, m)

    if is_client:
        name = "Alice"
    else:
        name = "Bob"

    ## Generating challenge
    r_challenge = int_from_bytes(secrets.token_bytes(256 // 8))  # 256-b = 8-B

    ## setting args attrs
    init_info = {
        'r_challenge': r_challenge,
        'name': name,
        'g_x_mod_m': g_x_mod_m,  # Diffie Hellman segment
        'n': pubkey.n,
        'e': pubkey.e,
    }

    name = _string_to_bytes(name)

    if is_client:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as conn:
            print('connecting to server...', end='')
            conn.connect((args['host'], args['port']))  # connect
            print('\rConnection established                       ')

            if 'test' in args and args['test'] == 2:
                privkey.d -= 1

            ##############
            # send msg 1 #
            ##############
            args['seq'] = 1
            args['msg1'] = init_info
            print('auth: sending auth command and msg1...:', list(args.keys()))
            send_msg(conn, _string_to_bytes(format_args_to_json(args)))

            # OK 200 response
            resp = json.loads(_bytes_to_string(recv_msg(conn)))
            if resp['readystate'] in [200]:
                print(
                    "ERROR: server did not respond with OK 200, terminating session..."
                )
                return

            ##############
            # recv msg 2 #
            ##############
            msg2 = msg2args(recv_msg(conn))
            assert msg2['seq'] == 2
            print('auth: received msg 2:', list(msg2.keys()))

            info_b = msg2['info']
            name_b = _string_to_bytes(info_b['name'])

            g_ab_mod_m = compute_dh_key(exp, info_b['g_x_mod_m'], m)

            # assemble Bob's public key
            pubkey_b = rsa.PublicKey(info_b['n'], info_b['e'])

            ## step 2
            # H= h256(Alice, Bob,         R A ,        R B ,               g a mod m,  g b mod m, g ab mod m)
            H = h256(name, name_b, r_challenge, info_b['r_challenge'],
                     g_x_mod_m, info_b['g_x_mod_m'], g_ab_mod_m)

            ## step 3 verificying secret
            S_b_signature = msg2['S'].strip(b'\x00')
            S_b = H + name_b
            rsa.verify(S_b, S_b_signature, pubkey_b)

            # build key
            K = h256(g_ab_mod_m)

            ## destroy a:
            print('destroying exponent a:', exp)
            del exp

            ##############
            # send msg 3 #
            ##############
            S_a = H + name
            S_a_signature = rsa.sign(S_a, privkey, 'SHA-256')

            msg3_payload = name + S_a_signature
            msg3_ciphertext = CipherLib.aes(msg3_payload, key=K)

            msg3 = {
                'seq': 3,
                'payload': msg3_ciphertext,
            }
            print('auth: sending msg #3', list(msg3.keys()))

            # sending E(Alice, S_A ,)
            print('sending msg3:', msg3)
            send_msg(conn, args2msg(msg3))

            return K

    else:  # if server (Bob)

        ##############
        # recv msg 1 #
        ##############

        # changing key for testing, auth should fail
        if 'test' in args and args['test'] == 1:
            privkey.d -= 1

        # client has already sent the stuff
        msg1 = args['msg1']
        assert args['seq'] == 1
        print('auth: received msg1', list(msg1.keys()))

        name_a = _string_to_bytes(msg1['name'])
        g_ab_mod_m = compute_dh_key(exp, msg1['g_x_mod_m'], m)

        # assemble Alice's public key
        pubkey_a = rsa.PublicKey(msg1['n'], msg1['e'])

        ##############
        # send msg 2 #
        ##############
        # H = h 256 (Alice, Alice, R A , R B , g a mod m, g b mod m, g ab mod m)
        H = h256(name_a, name, msg1['r_challenge'], r_challenge,
                 msg1['g_x_mod_m'], g_x_mod_m, g_ab_mod_m)

        S_b = H + name
        S_b_signature = rsa.sign(S_b, privkey, 'SHA-256')

        K = h256(g_ab_mod_m)

        # R_B , g b mod m, S B
        # this was prepared in the beginning of this function (after init DH)
        msg2 = {
            'seq': 2,
            'S': S_b_signature,
            'info': init_info,
        }
        print('sending msg2:', msg2)
        send_msg(conn, args2msg(msg2))

        ##############
        # recv msg 3 #
        ##############
        msg3_container = msg2args(recv_msg(conn))
        assert msg3_container['seq'] == 3
        msg3_ciphertext = msg3_container['payload']

        msg3 = CipherLib.aes(msg3_ciphertext, decrypt=True, key=K)

        ## verifying secret
        S_a_signature = msg3[len(name_a):].strip(b'\x00')
        S_a = (H + name_a)
        try:
            rsa.verify(S_a, S_a_signature, pubkey_a)
        except rsa.VerificationError as e:
            print('AUTHENTICATION FAILED!! S_a did not match signature:\n',
                  S_a_signature, ' is not the signature of ', S_a)
            return False

        ## destroy b:
        print('destroying exponent b:', exp)
        del exp

        return K