simplecrack / app.py
Jack698's picture
Update app.py
bf8b495 verified
# 导入所需的库
from pycipher import SimpleSubstitution as SimpleSub
import random
import re
from ngram_score import ngram_score
import proability
import gradio as gr
def decrypt_text_internal(ciphertext):
fitness = ngram_score('quadgrams.txt')
ctext = re.sub('[^A-Z]', '', ciphertext.upper())
maxkey = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
maxscore = -99e9
parentscore, parentkey = maxscore, maxkey[:]
i = 0
# Limit iterations to prevent infinite loops in a web server environment
while i < 1000:
i = i + 1
random.shuffle(parentkey)
deciphered = SimpleSub(parentkey).decipher(ctext)
parentscore = fitness.score(deciphered)
count = 0
while count < 1000:
a = random.randint(0, 25)
b = random.randint(0, 25)
child = parentkey[:]
child[a], child[b] = child[b], child[a]
deciphered = SimpleSub(child).decipher(ctext)
score = fitness.score(deciphered)
if score > parentscore:
parentscore = score
parentkey = child[:]
count = 0
count = count + 1
if parentscore > maxscore:
maxscore, maxkey = parentscore, parentkey[:]
ss = SimpleSub(maxkey)
plaintext = ss.decipher(ctext)
plaintext1 = add_punctuation_and_spaces(ciphertext, plaintext)
# In a web context, we return the first good result.
# The original loop was infinite, which is not suitable for a server.
return plaintext1
# Fallback if no good solution is found within the iteration limit
ss = SimpleSub(maxkey)
plaintext = ss.decipher(ctext)
return add_punctuation_and_spaces(ciphertext, plaintext)
def output(string1, dic, string2):
modified_string1 = list(string1)
modified_string2 = list(string2)
for i in range(len(string1)):
if modified_string1[i] in dic and modified_string2[i] != ' ':
modified_string2[i] = dic[modified_string1[i]]
modified_string2 = ''.join(modified_string2)
return modified_string2
def add_punctuation_and_spaces(ciphertext, plaintext):
result = ""
j = 0
for i in range(len(ciphertext)):
if not ciphertext[i].isalpha():
result += ciphertext[i]
else:
if ciphertext[i].islower():
result += plaintext[j].lower()
else:
# The original code had a bug here, always making it lowercase.
# This is a guess at the intended behavior.
result += plaintext[j]
j += 1
return result
def decrypt_interface(ciphertext, key):
"""
This is the main function that will be exposed through the Gradio interface.
"""
if not ciphertext:
return "Please enter some ciphertext."
plaintext = decrypt_text_internal(ciphertext)
if key:
try:
key_dic = proability.read_key(key)
plaintext = output(ciphertext, key_dic, plaintext)
except Exception as e:
return f"Error processing key: {e}. Please check the key format (e.g., a=B c=D)."
return plaintext
# Create the Gradio interface
iface = gr.Interface(
fn=decrypt_interface,
inputs=[
gr.Textbox(lines=10, label="Ciphertext", placeholder="Enter the text to decrypt..."),
gr.Textbox(lines=2, label="Known Key Mappings (Optional)", placeholder="e.g., a=B c=D")
],
outputs=gr.Textbox(lines=10, label="Plaintext"),
title="Simple Substitution Cipher Decryptor",
description="An automatic decryption tool for simple substitution ciphers. You can optionally provide known letter mappings to improve accuracy."
)
# Launch the app
if __name__ == "__main__":
iface.launch(server_name="127.0.0.1", server_port=7860)