Example #1
0
def handleKeyAdvertisementServer(client, data, privDhVal=None):
    print("key ad received")  # DEBUG
    validKeyHashes = None
    try:
        sessionKey = client.getSessionKey()
        unencryptedData = AES.decrypt(data=data, key=sessionKey)
        msg = Message.fromBytes(unencryptedData)
        validKeyHashes = msg.getObjectKeyHashes()
        if validKeyHashes == False or validKeyHashes == None:  # Not a valid KEY_ADVERTISEMENT.
            return False
    except:  # Not a proper message, likely wrong level of encryption
        raise
        if data != -1:
            return False

    state = client.getConnectionState()

    # Update server state and calculate session key
    if state == ServerState.KEYS_ADVERTISED:
        client.setConnectionState(ServerState.DATA_EXCHANGE)
        client.setObjectKeyHashes(validKeyHashes)

    sendMsg = Message(MessageType.KEY_ADVERTISEMENT_ACK)
    sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)

    sock = client.getSocket()
    sendBytes(client, sendMsgBytes)

    print("key ad sent")  # DEBUG

    return True
Example #2
0
def handleShutdown(client):
    client.setConnectionState(ServerState.SHUTDOWN_SENT)

    sock = client.getSocket()
    sock.settimeout(RESPONSE_TIMEOUT)

    maxResendCount = 10
    resendCount = 0

    sessionKey = client.getSessionKey()
    sendMsg = Message(MessageType.SHUTDOWN_CLOSEE_ACK)
    sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)

    sendBytes(client, sendMsgBytes)

    while client.getConnectionState(
    ) != ServerState.SHUTDOWN_COMPLETE and resendCount < maxResendCount:
        try:
            data = sock.recv(1024)
        except:
            resendCount += 1
            continue

        if data == -1:
            sendBytes(client, sendMsgBytes)
        else:
            unencryptedData = AES.decrypt(data=data, key=sessionKey)
            msg = Message.fromBytes(unencryptedData)
            if msg.type == MessageType.SHUTDOWN_CLOSER_ACK:
                client.setConnectionState(ServerState.SHUTDOWN_COMPLETE)
            else:
                sendBytes(client, sendMsgBytes)

        resendCount += 1
Example #3
0
def handleObjectRequestAck(server, data):

    status = None
    reqNum = None
    try:
        unencryptedData = AES.decrypt(data=data, key=server.getSessionKey())
        msg = Message.fromBytes(unencryptedData)
        status = msg.getStatus()
        reqNum = msg.getRequestNumber()
        if status in {False, None} or reqNum in {False, None}:
            return (False, None, None)
    except:
        return (False, None, None)

    if not server.checkRequestNumberUsed(reqNum):
        return (False, None, None)

    if server.getRequestNumberState(
            reqNum) < DataExchangeState.EXCHANGE_COMPLETE:
        server.setRequestNumberState(reqNum,
                                     DataExchangeState.EXCHANGE_COMPLETE)

    sock = server.getSocket()
    sessionKey = server.getSessionKey()
    sendMsgData = {"requestNum": reqNum}
    sendMsg = Message(MessageType.DATA_ACK, sendMsgData)
    sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)
    sendBytes(server, sendMsgBytes)

    return (True, status, reqNum)
Example #4
0
def handleKeyAdvertisement(server, data):
    sock = server.getSocket()

    keyHashes = None
    try:
        unencryptedData = AES.decrypt(data=data, key=server.getSessionKey())
        msg = Message.fromBytes(unencryptedData)
        keyHashes = msg.getObjectKeyHashes()
        if keyHashes == False or keyHashes == None:
            return False
    except:
        raise
        if data != -1:  # Not a timeout
            return False

    if server.getConnectionState() == ClientState.DIFFIE_HELLMAN_SENT:
        server.setConnectionState(ClientState.KEYS_ADVERTISED)
        server.setObjectKeyHashes(keyHashes)

    allowedKeys = list(objectKeyDict.keys())
    sendMsgData = {"keys": allowedKeys}
    sendMsg = Message(MessageType.KEY_ADVERTISEMENT, sendMsgData)
    sendMsgBytes = AES.encrypt(sendMsg.toBytes(), server.getSessionKey())
    sendBytes(server, sendMsgBytes)
    return True
Example #5
0
def handleDiffieHellmanResponse(client, data, privDhVal=None):
    dhVal = None
    try:
        clientPubKey = client.getPubKey()
        encryptedData, signature = RSA.separateSignature(data, clientPubKey)
        unencryptedData = RSA.decrypt(data=encryptedData, key=ownPrivKey)
        if not RSA.checkSignature(unencryptedData, clientPubKey, signature):
            return False
        msg = Message.fromBytes(unencryptedData)
        dhVal = msg.getDiffieHellmanValue()
        if dhVal == False or dhVal == None:  # Not a valid DIFFIE_HELLMAN_RESPONSE. Probably an encrypted message that start with the right number
            return False
    except:  # Not a proper message, likely wrong level of encryption
        if data != -1:
            return False

    state = client.getConnectionState()

    # Update server state and calculate session key
    if state == ServerState.CONNECT_RESPONSE_SENT:
        client.setConnectionState(ServerState.KEYS_ADVERTISED)
        sessionKey = DH.createDiffieHellmanKey(dhVal, privDhVal)
        client.setSessionKey(sessionKey)

    sessionKey = client.getSessionKey()

    allowedKeys = list(objectKeyDict.keys())
    sendMsgData = {"keys": allowedKeys}
    sendMsg = Message(MessageType.KEY_ADVERTISEMENT, sendMsgData)
    sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)

    sock = client.getSocket()
    sendBytes(client, sendMsgBytes)
Example #6
0
def handleDataResponse(server, msg):
    reqNum = msg.getRequestNumber()
    keyHash = msg.getObjectKeyHash()
    dataHash = msg.getObjectDataHash()
    data = msg.getObjectData()
    objectName = msg.getObjectName()

    if reqNum in {False, None} or keyHash in {False, None} or dataHash in {
            False, None
    } or data in {False, None} or objectName in {False, None}:
        return False

    if server.checkRequestNumberUsed(reqNum) == False:
        return False
    requestData = server.getRequestNumberData(reqNum)
    if requestData == None or objectName != requestData['name']:
        return False
    key = objectKeyDict.get(keyHash)
    key = base64.b64decode(key)
    if key == None:
        return False

    unencryptedDataHash = AES.decrypt(data=dataHash, key=key)
    unencryptedData = AES.decrypt(data=data, key=key)

    preHashValue = bytearray(unencryptedData) + bytearray(objectName, "ascii")
    if getHash(bytes(
            preHashValue)) != unencryptedDataHash:  # Not the correct object
        return False

    if server.getRequestNumberState(reqNum) == DataExchangeState.REQUEST_SENT:
        saveObject(unencryptedData, objectName, server.getSaveFileLocation())
        server.setRequestNumberState(reqNum,
                                     DataExchangeState.EXCHANGE_COMPLETE)

    sock = server.getSocket()
    sessionKey = server.getSessionKey()

    sendMsgData = {"requestNum": reqNum}
    sendMsg = Message(MessageType.DATA_ACK, sendMsgData)
    sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)
    sendBytes(server, sendMsgBytes)

    return True
Example #7
0
def handleKeyAdvertisementAck(server, data):
    try:
        unencryptedData = AES.decrypt(data=data, key=server.getSessionKey())
        msg = Message.fromBytes(unencryptedData)
        if msg.getType() != MessageType.KEY_ADVERTISEMENT_ACK:
            return False
    except:
        return False

    print("key ad recv")  # DEBUG
    if server.getConnectionState() == ClientState.KEYS_ADVERTISED:
        server.setConnectionState(ClientState.DATA_EXCHANGE)
Example #8
0
def initiateShutdown(server):
    server.setConnectionState(ClientState.SHUTDOWN_SENT)

    sock = server.getSocket()
    sock.settimeout(RESPONSE_TIMEOUT)

    maxResendCount = 10
    resendCount = 0

    sessionKey = server.getSessionKey()
    sendMsg = Message(MessageType.SHUTDOWN_REQUEST)
    sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)

    sendBytes(server, sendMsgBytes)

    while server.getConnectionState(
    ) != ClientState.SHUTDOWN_COMPLETE and resendCount < maxResendCount:
        data = None
        try:
            data = sock.recv(1024)
        except socket.timeout:
            data = -1

        if data == -1:
            sendBytes(server, sendMsgBytes)
        else:
            unencryptedData = AES.decrypt(data=data, key=sessionKey)
            msg = Message.fromBytes(unencryptedData)
            if msg.type == MessageType.SHUTDOWN_CLOSEE_ACK:
                server.setConnectionState(ClientState.SHUTDOWN_COMPLETE)
                sendMsg = Message(MessageType.SHUTDOWN_CLOSER_ACK)
                sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(),
                                           key=sessionKey)
                sendBytes(server, sendMsgBytes)
            else:
                sendBytes(server, sendMsgBytes)

        resendCount += 1

    sock.close()
Example #9
0
def dataExchangeLoop(client):
    sock = client.getSocket()
    sessionKey = client.getSessionKey()

    sock.settimeout(RESPONSE_TIMEOUT)
    connectionTimeout = 5

    lastMessageTime = time()
    while client.getConnectionState() == ServerState.DATA_EXCHANGE and time(
    ) < lastMessageTime + connectionTimeout:
        try:
            data = sock.recv(1024)
        except socket.timeout:
            continue

        msg = None
        type = None
        try:
            unencryptedData = AES.decrypt(key=sessionKey, data=data)
            msg = Message.fromBytes(unencryptedData)
            type = msg.getType()
            if type != MessageType.SHUTDOWN_REQUEST and type != MessageType.OBJECT_REQUEST and type != MessageType.DATA_ACK and type != KEY_ADVERTISEMENT:
                continue

            lastMessageTime = time()
        except:  # Probably an OBJECT_REQUEST
            try:
                msg = Message.fromBytes(data)
                type = msg.getType()
                if type == MessageType.OBJECT_REQUEST:
                    handleObjectRequest(client, msg)
            except:  # An invalid message
                continue

        if type == MessageType.SHUTDOWN_REQUEST:
            handleShutdown(client)
        elif type == MessageType.DATA_ACK:
            handleDataAck(client, msg)
        elif type == MessageType.KEY_ADVERTISEMENT:
            handleKeyAdvertisementServer(client, data)
Example #10
0
def handleObjectRequest(client, msg):  # TODO add an objReqAck
    print("objreq recv")  # DEBUG
    reqNum = msg.getRequestNumber()
    target = msg.getTargetObject()
    keyHash = msg.getRequestedObjectKeyHash()
    sock = client.getSocket()

    # Make sure all values exist
    if reqNum == False or reqNum == None or target == False or target == None or keyHash == False or keyHash == None:
        return

    if not isValidRequestNumber(reqNum) or not keyHash in objectKeyDict.keys(
    ):  # TODO create func and decide what makes a request number
        return
    elif not client.checkRequestNumberUsed(reqNum):  # A new request
        client.setRequestNumberState(reqNum, DataExchangeState.DATA_SENT)

        objectData = retrieveData(target, client.getLoadFileLocation())
        objectKey = objectKeyDict[keyHash]
        # Send an object request ack if either fails
        if objectData == None:  # TODO or whatever fail value is for obtainData
            sessionKey = client.getSessionKey()
            sendMsgData = {
                "status": DataExchangeStatus.OBJ_NOT_FOUND,
                "requestNum": reqNum
            }
            sendMsg = Message(MessageType.OBJECT_REQUEST_ACK, sendMsgData)
            sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)
            sendBytes(client, sendMsgBytes)
            print("Requested file not found: '{}'".format(target))
            return
        elif objectKey == None:
            sessionKey = client.getSessionKey()
            sendMsgData = {
                "status": DataExchangeStatus.UNKNOWN_KEY,
                "requestNum": reqNum
            }
            sendMsg = Message(MessageType.OBJECT_REQUEST_ACK, sendMsgData)
            sendMsgBytes = AES.encrypt(data=sendMsg.toBytes(), key=sessionKey)
            sendBytes(client, sendMsgBytes)
            print("Object key unknown for requested file: '{}'".format(target))
            return

        objectKey = base64.b64decode(objectKey)
        encryptedObjectData = AES.encrypt(data=objectData, key=objectKey)
        preHashValue = bytearray(objectData) + bytearray(target, "ascii")
        objectHash = getHash(preHashValue)  # TODO make it actually append
        encryptedObjectHash = AES.encrypt(data=bytes(objectHash),
                                          key=objectKey)

        messageData = {
            "keyHash": keyHash,
            "dataHash": encryptedObjectHash,
            "data": encryptedObjectData,
            "objectName": target,
            "requestNum": reqNum,
            "expiration": time() + 3600
        }
        client.setRequestNumberData(
            reqNum,
            messageData)  # Save the data to avoid recomputing for resends

        sendMsg = Message(MessageType.DATA_MESSAGE, messageData)
        sendMsgBytes = sendMsg.toBytes()

        sendBytes(client, sendMsgBytes)
        print("File found and sent: '{}'".format(target))
    elif client.getRequestNumberState(
            reqNum) == DataExchangeState.DATA_SENT:  # A resend request
        messageData = client.getRequestNumberData(reqNum)
        sendMsg = Message(MessageType.DATA_MESSAGE, messageData)
        sendMsgBytes = sendMsg.toBytes()

        sendBytes(client, sendMsgBytes)