aboutsummaryrefslogtreecommitdiff
path: root/main.sts
blob: 5159f93dd57a71cbc7a275774176c24e3ae2ab67 (plain)
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
module ia32/elf/begin.sts
module ia32/float/float.sts
module cipher.sts
module keygen.sts
module freq.sts

[ sd 0 swap drop ]

defword nicedist
    1 float_iload 2 float_iload float_div
exit

defword calcdist ; distance from ideal as sqrt sum square diff
    1b ref as calcdist.textfr
    local calcdist.fr
    0 do dup 1a = until
        dup word_size mul dup dup
                calcdist.fr + @ float_fload
                calcdist.textfr + @ float_fload
            float_sub float_fstore dup float_fload float_fload
        float_mul float_fstore swap calcdist.fr + !
    1 + od drop newline sys_write
    0 do dup 19 = until
        swap float_fload swap float_fload float_add float_fstore swap
    1 + od drop
    float_fload float_sqrt nicedist float_less
exit

defword checktext
    as checktext.length
    local checktext.text
        ; Count frequencies:
    ; 26 latin letters:
    0 0 0 0 0  0 0 0 0 0  0 0 0
    0 0 0 0 0  0 0 0 0 0  0 0 0 local checktext.fr
    ; count how much of each letter is in text:
    0 local checktext.count
    checktext.length do 1 -
        dup word_size mul checktext.text + @
        dup dup 'z' > 0 = swap 'a' < 0 = mul if
            dup 'z' swap - word_size mul checktext.fr + dup @ 1 + swap !
            checktext.count @ 1 + checktext.count !
        fi dup dup 'Z' > 0 = swap 'A' < 0 = mul if
            dup 'Z' swap - word_size mul checktext.fr + dup @ 1 + swap !
            checktext.count @ 1 + checktext.count !
        fi dup 9 < if drop drop drop
            drop drop drop drop drop  drop drop drop drop drop  drop drop drop
            drop drop drop drop drop  drop drop drop drop drop  drop drop drop
        0 exit fi dup dup 1f > 0 = swap e < 0 = mul if drop drop drop
            drop drop drop drop drop  drop drop drop drop drop  drop drop drop
            drop drop drop drop drop  drop drop drop drop drop  drop drop drop
        0 exit fi drop
    dup 0 = untilod drop
; ZERO DIVISION SHALL NOT PASS
checktext.count 0 = if drop
    drop drop drop drop drop  drop drop drop drop drop  drop drop drop
    drop drop drop drop drop  drop drop drop drop drop  drop drop drop
0 exit fi
    ; normalize:
    0 do dup 1a = until
            dup word_size mul checktext.fr + dup @ float_iload
            checktext.count @ float_iload
        float_div float_fstore swap !
    1 + od drop
        ; Decide if text is real:
    freq_eng calcdist if 1 else
    0 fi
        ; Remove frequencies from stack:
    sd
    sd sd sd sd sd  sd sd sd sd sd  sd sd sd
    sd sd sd sd sd  sd sd sd sd sd  sd sd sd
exit

set_entry float_init ; this is program with floats
    ; read file into stack
    0 do sys_read 0 = until
        swap 1 +
    od drop as length
    local ciphertext

    0 ; initial key is empty
    do
        ; generate next key to try
        keygen as keylen local key

        ; decipher text (length is the same as for ciphertext)
        keylen 1 - length do 1 -
            as textpos local pos
                textpos word_size mul ciphertext + @
                key
                keylen
                pos
            cipher
            swap textpos
        dup 0 = untilod drop drop
        local plaintext

        ; check deciphering attempt, exit if Ok or keylen = max (2)
    keylen 2 = if eeeee else length checktext fi dup until drop
        ; else remove the text from stack and place keylen back
        0 do dup length = until
            swap drop 1 +
        od drop keylen
    od as langcode

    ; output language
    langcode 1 = if
        'e' sys_write_err
        'n' sys_write_err
        'g' sys_write_err
        'l' sys_write_err
        'i' sys_write_err
        's' sys_write_err
        'h' sys_write_err
    fi langcode 2 = if
        'd' sys_write_err
        'u' sys_write_err
        't' sys_write_err
        'c' sys_write_err
        'h' sys_write_err
    fi langcode 3 = if
        'g' sys_write_err
        'e' sys_write_err
        'r' sys_write_err
        'm' sys_write_err
        'a' sys_write_err
        'n' sys_write_err
    fi langcode 4 = if
        'f' sys_write_err
        'r' sys_write_err
        'e' sys_write_err
        'n' sys_write_err
        'c' sys_write_err
        'h' sys_write_err
    fi langcode 5 = if
        's' sys_write_err
        'p' sys_write_err
        'a' sys_write_err
        'n' sys_write_err
        'i' sys_write_err
        's' sys_write_err
        'h' sys_write_err
    fi langcode 6 = if
        'i' sys_write_err
        't' sys_write_err
        'a' sys_write_err
        'l' sys_write_err
        'i' sys_write_err
        'a' sys_write_err
        'n' sys_write_err
    fi langcode eeeee = if
        'e' sys_write_err
        'r' sys_write_err
        'r' sys_write_err
        'o' sys_write_err
        'r' sys_write_err
    fi

    ; output text
    length do 1 -
        dup word_size mul plaintext + @ sys_write
    dup 0 = untilod
sys_exit

module ia32/elf/end.sts