Spaces:
Paused
Paused
import secrets | |
import string | |
from Crypto.Cipher import AES | |
from Crypto.Random import get_random_bytes | |
from Crypto.Util.Padding import pad, unpad | |
from Crypto.Hash import SHA256 | |
import base64 | |
import gradio as gr | |
def generate_random_key(length=32): | |
"""Generate a random key with digits, uppercase, lowercase, and special characters.""" | |
characters = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation | |
key = ( | |
secrets.choice(string.ascii_lowercase) + | |
secrets.choice(string.ascii_uppercase) + | |
secrets.choice(string.digits) + | |
secrets.choice(string.punctuation) | |
) | |
key += ''.join(secrets.choice(characters) for _ in range(length - 4)) | |
key_list = list(key) | |
secrets.SystemRandom().shuffle(key_list) | |
return ''.join(key_list) | |
def derive_key(custom_key, key_size): | |
"""Derive a key of specified size (128, 192, or 256 bits) from a custom string using SHA-256.""" | |
hasher = SHA256.new() | |
hasher.update(custom_key.encode('utf-8')) | |
full_hash = hasher.digest() | |
# Convert key_size to integer before division | |
return full_hash[:int(key_size) // 8] | |
def encrypt_string(plain_text, key, key_size): | |
"""Encrypt a string using AES in CBC mode with specified key size.""" | |
try: | |
if not plain_text: | |
return "Error: Please provide text to encrypt." | |
if not key: | |
return "Error: Please provide a key." | |
derived_key = derive_key(key, key_size) | |
plain_text_bytes = plain_text.encode('utf-8') | |
iv = get_random_bytes(AES.block_size) | |
cipher = AES.new(derived_key, AES.MODE_CBC, iv) | |
padded_text = pad(plain_text_bytes, AES.block_size) | |
cipher_text = cipher.encrypt(padded_text) | |
return base64.b64encode(iv + cipher_text).decode('utf-8') | |
except Exception as e: | |
return f"Encryption error: {str(e)}" | |
def decrypt_string(encrypted_text, key, key_size): | |
"""Decrypt a string using AES in CBC mode with specified key size.""" | |
try: | |
if not encrypted_text: | |
return "Error: Please provide encrypted text." | |
if not key: | |
return "Error: Please provide a key." | |
derived_key = derive_key(key, key_size) | |
raw = base64.b64decode(encrypted_text) | |
iv = raw[:AES.block_size] | |
cipher_text = raw[AES.block_size:] | |
cipher = AES.new(derived_key, AES.MODE_CBC, iv) | |
padded_text = cipher.decrypt(cipher_text) | |
return unpad(padded_text, AES.block_size).decode('utf-8') | |
except Exception as e: | |
return f"Decryption error: {str(e)}" | |
def generate_and_display_key(): | |
"""Generate and return a random key.""" | |
return generate_random_key() | |
# Gradio interface | |
with gr.Blocks() as demo: | |
gr.Markdown("# AES Encryption/Decryption App") | |
gr.Markdown("Encrypt or decrypt text using AES (128, 192, or 256-bit keys).") | |
with gr.Row(): | |
key_size = gr.Radio( | |
choices=["128", "192", "256"], | |
label="AES Key Size (bits)", | |
value="256" | |
) | |
with gr.Row(): | |
custom_key = gr.Textbox( | |
label="Custom Key", | |
placeholder="Enter your key or generate one", | |
lines=1 | |
) | |
generate_key_btn = gr.Button("Generate Random Key") | |
with gr.Row(): | |
input_text = gr.Textbox( | |
label="Input Text", | |
placeholder="Enter text to encrypt", | |
lines=3 | |
) | |
with gr.Row(): | |
encrypt_btn = gr.Button("Encrypt") | |
decrypt_btn = gr.Button("Decrypt") | |
output_text = gr.Textbox( | |
label="Output", | |
placeholder="Result will appear here", | |
lines=3, | |
interactive=False | |
) | |
# Event handlers | |
generate_key_btn.click( | |
fn=generate_and_display_key, | |
outputs=custom_key | |
) | |
encrypt_btn.click( | |
fn=encrypt_string, | |
inputs=[input_text, custom_key, key_size], | |
outputs=output_text | |
) | |
decrypt_btn.click( | |
fn=decrypt_string, | |
inputs=[input_text, custom_key, key_size], | |
outputs=output_text | |
) | |
# Launch the app | |
demo.launch() |