def centralServer(id, Key = "", nonce = ""):
    channel = grpc.insecure_channel('localhost:50051')
    stub = central_grpc.CentralStub(channel)
    servers = []

    """ choose service from stub and then proto message from pb
        serialized message with respect to the proto    """

    if nonce == "":
        response = stub.GiveFS(centralpb.Request(name = str(id))).name.encode()
        fernet = Fernet(Key.encode())
        plaintext = fernet.decrypt(response).decode()
        servers = plaintext.split(" ")
        print("The Number of File Servers active are {}.\nSelect the File Server to establish communication:\n".format(len(servers)))
        for i, s in enumerate(servers):
            print(i + 1, ") " + s)

    else:
        # print(id.decode(), type(id))
        response = stub.Registration(centralpb.Request(name = id.decode()))
        fernet = Fernet(Key.encode())
        plaintext = fernet.decrypt(response.name.encode()).decode()
        if int(plaintext) + 1 == int(nonce):
            print("Registration complete successfully.")

    return servers
def sendToCentral(id, nonce="", Key=""):
    channel = grpc.insecure_channel('localhost:50051')
    stub = central_grpc.CentralStub(channel)

    response = stub.Registration(centralpb.Request(name=id))
    fernet = Fernet(Key.encode())
    plaintext = fernet.decrypt(response.name.encode()).decode()
    if int(plaintext) + 1 == int(nonce):
        print("Registration complete successfully.")
def checkCenter(key, pid):
    fernet = Fernet(key.encode())
    channel = grpc.insecure_channel('localhost:50051')
    stub = central_grpc.CentralStub(channel)

    response = stub.GetUpdate(centralpb.Request(name = pid))
    plaintext = fernet.decrypt(response.name.encode()).decode()
    if len(plaintext) == 0:
        return 
    
    print("\nThe following files have been added : FileName[FileServer]\n")
    plaintext = plaintext.split()
    for i,p in enumerate(plaintext):
        print ("  ", i+1, ") ", p)
    return    
def getSharedKey(cur_serv, kdcKey, pid):
    """
    pid, server, nonce
    nonce, fs, shared_key, ticket
    (ticket) = decoded ciphertext encrypted by kdcFS key - (session_key + pid)
    make a rpc req to FS with two messages - (nonce)sharedkey.decode() and ticketcipher 
    Response encrypted by session_key - nonce-1 
    """
    print("\nNeedham-Schroeder Authentication: \n")
    nonce = generate_nonce()
    msg = str(pid) + " " + cur_serv + " " + nonce

    channel = grpc.insecure_channel('localhost:50051')
    stub = central_grpc.CentralStub(channel)
    response = stub.GenKey(centralpb.Request(name = msg)).name.encode()

    print("\nSTEP1: Sent a request to the KDC for a ticket to establish session between the client with pid {} and File Server {}.".format(pid, cur_serv))

    fernet = Fernet(kdcKey.encode())
    plaintext = fernet.decrypt(response).decode()
    _, _, shared_key, ticketCipher = plaintext.split(" ")

    shared_key = shared_key.encode()
    fernet = Fernet(shared_key)
    plaintext = nonce
    ciphertext = fernet.encrypt(plaintext.encode()).decode()

    print("STEP2: Session Key and Ticket received.\nSTEP3: Sent RPC request to FS with an encrypted nonce `{}` and Ticket.".format(nonce))

    port = cur_serv[2:]
    channel = 'localhost:' + port
    channel = grpc.insecure_channel(channel)
    stub = filepb_grpc.FileServerStub(channel)
    response = stub.ShareKey(filepb.CPReq(file1 = ciphertext, file2 = ticketCipher)).name.encode()

    plaintext = fernet.decrypt(response).decode()

    if int(plaintext) + 1 == int(nonce):
        print("STEP4: Received an Ecrypted nonce from FS `{}`.\nSTEP5: Sent the Encrypted nonce to FS.".format(plaintext))
        print("Session has been established between client with pid {} and file server {}.\n".format(pid, cur_serv))
        return shared_key
    else:
        print("Connection failed to establish.")
        exit()
    def NEW(self, request, context):
        self.sessionCount += 1
        fernet = Fernet(self.session[1].encode())
        plaintext = fernet.decrypt(request.name.encode()).decode()

        fer = Fernet(self.kdcKey)
        ciphertext = fer.encrypt(
            (plaintext + " " + self.session[0]).encode()).decode()
        msg = "FS" + self.port + " " + ciphertext

        channel = grpc.insecure_channel('localhost:50051')
        stub = central_grpc.CentralStub(channel)
        stub.NewFile(centralpb.Request(name=msg))

        content = "File has been created by client with PID " + self.session[0]
        with open(os.path.join(self.directory, plaintext), 'w') as f:
            f.write(content)
        print(
            "   {}) NEW request from Client with PID {}. Submitted the update to Central Server."
            .format(self.sessionCount, self.session[0]))
        ciphertext = fernet.encrypt((content).encode()).decode()
        return filepb.Response(name=ciphertext)