File size: 3,885 Bytes
bf8b495
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# 导入所需的库
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)