Further enhance and add a web-gui with a more aesthetic and natural gui.

```
#!/usr/bin/env python3
"""
SRVK Algorithm Implementation with GUI in Python

This script implements the Super RSA Versatile Key (SRVK) algorithm with a GUI.
The GUI allows users to interactively perform key generation, encryption, and decryption.
It supports key rotation and encryption of large datasets by splitting them into blocks.

Author: [Your Name]
Date: [Date]
"""

import os
import tkinter as tk
from tkinter import filedialog, messagebox, simpledialog
import threading
import pickle
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives import ciphers
from cryptography.hazmat.primitives.ciphers import algorithms, modes, Cipher
from cryptography.hazmat.backends import default_backend
from cryptography.exceptions import InvalidTag

def generate_keys(rsa_key_size=2048, symmetric_key_size=256):
    """
    Generates RSA key pair and symmetric key.

    Parameters:
    - rsa_key_size (int): Size of the RSA key in bits (2048, 4096, or 8192)
    - symmetric_key_size (int): Size of the symmetric key in bits (128 or 256)

    Returns:
    - rsa_private_key: RSA private key object
    - rsa_public_key: RSA public key object
    - symmetric_key (bytes): Symmetric key bytes
    """
    # Generate RSA key pair
    rsa_private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=rsa_key_size,
        backend=default_backend()
    )
    rsa_public_key = rsa_private_key.public_key()

    # Generate symmetric key
    if symmetric_key_size not in [128, 256]:
        raise ValueError("Symmetric key size must be 128 or 256 bits.")
    symmetric_key = os.urandom(symmetric_key_size // 8)  # Convert bits to bytes

    return rsa_private_key, rsa_public_key, symmetric_key

def srvk_encrypt(plaintext, rsa_public_key, symmetric_key=None, block_size=1024*1024, key_rotation_interval=0):
    """
    Encrypts the plaintext using the SRVK algorithm.

    Parameters:
    - plaintext (bytes): Data to encrypt
    - rsa_public_key: RSA public key object
    - symmetric_key (bytes): Optional; symmetric key to use (if None, a new key is generated)
    - block_size (int): Size of data blocks to split plaintext into
    - key_rotation_interval (int): Number of blocks after which to rotate symmetric key (0 for no rotation)

    Returns:
    - A dictionary containing:
        - 'encrypted_symmetric_keys': List of encrypted symmetric keys
        - 'cipher_blocks': List of cipher blocks (each block is a dictionary with 'ciphertext', 'nonce', 'tag', 'key_index')
    """
    # If no symmetric key is provided, generate one
    if symmetric_key is None:
        symmetric_key = os.urandom(32)  # 256-bit key

    encrypted_symmetric_keys = []
    cipher_blocks = []

    # Split plaintext into blocks
    blocks = [plaintext[i:i+block_size] for i in range(0, len(plaintext), block_size)]
    num_blocks = len(blocks)

    current_symmetric_key = symmetric_key
    encrypted_symmetric_key = rsa_public_key.encrypt(
        current_symmetric_key,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    encrypted_symmetric_keys.append(encrypted_symmetric_key)
    key_index = 0

    for i, block in enumerate(blocks):
        # Key rotation
        if key_rotation_interval > 0 and i > 0 and i % key_rotation_interval == 0:
            # Rotate symmetric key
            current_symmetric_key = os.urandom(32)
            encrypted_symmetric_key = rsa_public_key.encrypt(
                current_symmetric_key,
                padding.OAEP(
                    mgf=padding.MGF1(algorithm=hashes.SHA256()),
                    algorithm=hashes.SHA256(),
                    label=None
                )
            )
            encrypted_symmetric_keys.append(encrypted_symmetric_key)
            key_index += 1

        # Encrypt the block with AES-GCM
        nonce = os.urandom(12)  # 96-bit nonce for GCM
        aes_cipher = Cipher(
            algorithms.AES(current_symmetric_key),
            modes.GCM(nonce),
            backend=default_backend()
        ).encryptor()

        ciphertext = aes_cipher.update(block) + aes_cipher.finalize()
        tag = aes_cipher.tag

        cipher_blocks.append({
            'ciphertext': ciphertext,
            'nonce': nonce,
            'tag': tag,
            'key_index': key_index  # Indicates which encrypted symmetric key to use
        })

    return {
        'encrypted_symmetric_keys': encrypted_symmetric_keys,
        'cipher_blocks': cipher_blocks
    }

def srvk_decrypt(encrypted_data, rsa_private_key):
    """
    Decrypts the encrypted data using the SRVK algorithm.

    Parameters:
    - encrypted_data (dict): The encrypted data as returned by srvk_encrypt
    - rsa_private_key: RSA private key object

    Returns:
    - plaintext (bytes)
    """
    encrypted_symmetric_keys = encrypted_data['encrypted_symmetric_keys']
    cipher_blocks = encrypted_data['cipher_blocks']

    # Decrypt symmetric keys
    symmetric_keys = []
    for encrypted_symmetric_key in encrypted_symmetric_keys:
        symmetric_key = rsa_private_key.decrypt(
            encrypted_symmetric_key,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        symmetric_keys.append(symmetric_key)

    # Decrypt cipher blocks
    plaintext_blocks = []
    for block in cipher_blocks:
        key_index = block['key_index']
        symmetric_key = symmetric_keys[key_index]

        nonce = block['nonce']
        tag = block['tag']
        ciphertext = block['ciphertext']

        # Decrypt the block with AES-GCM
        try:
            aes_cipher = Cipher(
                algorithms.AES(symmetric_key),
                modes.GCM(nonce, tag),
                backend=default_backend()
            ).decryptor()

            plaintext_block = aes_cipher.update(ciphertext) + aes_cipher.finalize()
        except InvalidTag:
            raise ValueError("Decryption failed. Invalid authentication tag.")

        plaintext_blocks.append(plaintext_block)

    # Reassemble plaintext
    plaintext = b''.join(plaintext_blocks)

    return plaintext

def save_rsa_private_key(private_key, filepath, password=None):
    """
    Saves RSA private key to a file in PEM format.

    Parameters:
    - private_key: RSA private key object
    - filepath (str): Path to save the private key file
    - password (bytes): Optional; password to encrypt the private key
    """
    pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.BestAvailableEncryption(password) if password else serialization.NoEncryption()
    )

    with open(filepath, 'wb') as f:
        f.write(pem)

def load_rsa_private_key(filepath, password=None):
    """
    Loads RSA private key from a PEM file.

    Parameters:
    - filepath (str): Path to the private key PEM file
    - password (bytes): Optional; password to decrypt the private key

    Returns:
    - private_key: RSA private key object
    """
    with open(filepath, 'rb') as f:
        pem_data = f.read()

    private_key = serialization.load_pem_private_key(
        pem_data,
        password=password,
        backend=default_backend()
    )

    return private_key

def save_rsa_public_key(public_key, filepath):
    """
    Saves RSA public key to a file in PEM format.

    Parameters:
    - public_key: RSA public key object
    - filepath (str): Path to save the public key file
    """
    pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )

    with open(filepath, 'wb') as f:
        f.write(pem)

def load_rsa_public_key(filepath):
    """
    Loads RSA public key from a PEM file.

    Parameters:
    - filepath (str): Path to the public key PEM file

    Returns:
    - public_key: RSA public key object
    """
    with open(filepath, 'rb') as f:
        pem_data = f.read()

    public_key = serialization.load_pem_public_key(
        pem_data,
        backend=default_backend()
    )

    return public_key

def generate_keys_gui():
    # Prompt user for RSA key size
    rsa_key_size = simpledialog.askinteger("RSA Key Size", "Enter RSA key size (2048, 4096, or 8192):", initialvalue=2048)
    if rsa_key_size not in [2048, 4096, 8192]:
        messagebox.showerror("Error", "Invalid RSA key size. Choose 2048, 4096, or 8192.")
        return

    # Prompt user for symmetric key size
    symmetric_key_size = simpledialog.askinteger("Symmetric Key Size", "Enter symmetric key size (128 or 256):", initialvalue=256)
    if symmetric_key_size not in [128, 256]:
        messagebox.showerror("Error", "Invalid symmetric key size. Choose 128 or 256.")
        return

    # Generate keys
    rsa_private_key, rsa_public_key, symmetric_key = generate_keys(rsa_key_size=rsa_key_size, symmetric_key_size=symmetric_key_size)

    # Save keys
    save_path = filedialog.asksaveasfilename(title="Save Private Key As", defaultextension=".pem")
    if save_path:
        password = simpledialog.askstring("Private Key Encryption", "Enter password for private key encryption (leave blank for no password):", show='*')
        if password == '':
            password = None
        else:
            password = password.encode()
        save_rsa_private_key(rsa_private_key, save_path, password=password)
        messagebox.showinfo("Success", f"Private key saved to {save_path}")

    save_public_path = filedialog.asksaveasfilename(title="Save Public Key As", defaultextension=".pem")
    if save_public_path:
        save_rsa_public_key(rsa_public_key, save_public_path)
        messagebox.showinfo("Success", f"Public key saved to {save_public_path}")

def encrypt_gui():
    # Load RSA public key
    pub_key_path = filedialog.askopenfilename(title="Select RSA Public Key", filetypes=[("PEM files", "*.pem")])
    if not pub_key_path:
        return
    try:
        rsa_public_key = load_rsa_public_key(pub_key_path)
    except Exception as e:
        messagebox.showerror("Error", f"Failed to load public key: {e}")
        return

    # Select file to encrypt
    plaintext_path = filedialog.askopenfilename(title="Select File to Encrypt")
    if not plaintext_path:
        return
    with open(plaintext_path, 'rb') as f:
        plaintext = f.read()

    # Prompt for block size
    block_size = simpledialog.askinteger("Block Size", "Enter block size in bytes (e.g., 1048576 for 1MB):", initialvalue=1048576)
    if block_size is None:
        return

    # Prompt for key rotation interval
    key_rotation_interval = simpledialog.askinteger("Key Rotation Interval", "Enter key rotation interval (number of blocks, 0 for no rotation):", initialvalue=0)
    if key_rotation_interval is None:
        return

    # Encrypt
    try:
        encrypted_data = srvk_encrypt(
            plaintext=plaintext,
            rsa_public_key=rsa_public_key,
            block_size=block_size,
            key_rotation_interval=key_rotation_interval
        )
    except Exception as e:
        messagebox.showerror("Error", f"Encryption failed: {e}")
        return

    # Save encrypted data
    save_encrypted_path = filedialog.asksaveasfilename(title="Save Encrypted Data As", defaultextension=".enc")
    if save_encrypted_path:
        with open(save_encrypted_path, 'wb') as f:
            # For simplicity, we use pickle for serialization (ensure data safety in actual use)
            pickle.dump(encrypted_data, f)
        messagebox.showinfo("Success", f"Encrypted data saved to {save_encrypted_path}")

def decrypt_gui():
    # Load RSA private key
    priv_key_path = filedialog.askopenfilename(title="Select RSA Private Key", filetypes=[("PEM files", "*.pem")])
    if not priv_key_path:
        return
    password = simpledialog.askstring("Private Key Password", "Enter password for private key (leave blank if none):", show='*')
    if password == '':
        password = None
    else:
        password = password.encode()
    try:
        rsa_private_key = load_rsa_private_key(priv_key_path, password=password)
    except Exception as e:
        messagebox.showerror("Error", f"Failed to load private key: {e}")
        return

    # Select file to decrypt
    encrypted_path = filedialog.askopenfilename(title="Select Encrypted File", filetypes=[("Encrypted files", "*.enc")])
    if not encrypted_path:
        return
    with open(encrypted_path, 'rb') as f:
        try:
            encrypted_data = pickle.load(f)
        except Exception as e:
            messagebox.showerror("Error", f"Failed to load encrypted data: {e}")
            return

    # Decrypt
    try:
        plaintext = srvk_decrypt(
            encrypted_data=encrypted_data,
            rsa_private_key=rsa_private_key
        )
    except Exception as e:
        messagebox.showerror("Error", f"Decryption failed: {e}")
        return

    # Save decrypted data
    save_plaintext_path = filedialog.asksaveasfilename(title="Save Decrypted Data As")
    if save_plaintext_path:
        with open(save_plaintext_path, 'wb') as f:
            f.write(plaintext)
        messagebox.showinfo("Success", f"Decrypted data saved to {save_plaintext_path}")

def main_gui():
    root = tk.Tk()
    root.title("SRVK Encryption/Decryption")

    # Set window size and disable resizing
    root.geometry("400x250")
    root.resizable(False, False)

    # Create and place the buttons
    btn_generate_keys = tk.Button(root, text="Generate Keys", command=generate_keys_gui, width=30, height=2)
    btn_generate_keys.pack(pady=10)

    btn_encrypt = tk.Button(root, text="Encrypt File", command=encrypt_gui, width=30, height=2)
    btn_encrypt.pack(pady=10)

    btn_decrypt = tk.Button(root, text="Decrypt File", command=decrypt_gui, width=30, height=2)
    btn_decrypt.pack(pady=10)

    # Add an exit button
    btn_exit = tk.Button(root, text="Exit", command=root.quit, width=30, height=2)
    btn_exit.pack(pady=10)

    root.mainloop()

if __name__ == "__main__":
    main_gui()