-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvigenere.lua
More file actions
360 lines (320 loc) · 12.5 KB
/
vigenere.lua
File metadata and controls
360 lines (320 loc) · 12.5 KB
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
-- Vigenere.lua
-- Raymas
--
-- decryptor for vigenere method
-- paramters
local params = {...}
-- LANGUAGE FREQUENCIES
alphabet = "abcdefghijklmnopqrstuvwxyz"
english = "eariotnslcudpmhgbfywkvxzjq"
french = "eaisnrtoludcmpégbvhfqyxjèàkwzêçôâîûùïüëö"
spanish = "eaosnrildtucmpbhqyvgÓÍfjzÁÉÑxÚkwÜ"
-- 1. Cracking key length
function keylengthguess(text, language, maxkeylength, verbose)
if (maxkeylength == nil) then maxkeylength = 20 end
if (verbose == nil) then verbose = false end
local results = {}
local minMax = 0
for keylength = 1, maxkeylength, 1 do
-- count every character in text
local charmap = {}
local keyindex = 0
for i = 1, #text do
local c = text:lower():sub(i,i)
if language:find(c) then
if keyindex % keylength == 0 then
if (charmap[c]) then charmap[c] = charmap[c] + 1 else charmap[c] = 1 end
end
keyindex = keyindex + 1
end
end
-- end of key search
local sortedOccurences = getKeysSortedByValue(charmap, function(a, b) return a < b end)
local occurencesOfMinLetter = charmap[sortedOccurences[1]]
local occurencesOfMaxLetter = charmap[sortedOccurences[#sortedOccurences]]
local minProb = occurencesOfMinLetter / keyindex * keylength * 100
local maxProb = occurencesOfMaxLetter / keyindex * keylength * 100
-- the probability of key length is greater than previuously : updating results
if (maxProb - minProb) > minMax then
minMax = maxProb - minProb
results["prob"] = minMax
results["keylength"] = keylength
results["keyindex"] = keyindex
results["charmap"] = charmap
end
end
return results
end
-- 2. Cracking key
function guessingKey(text, language, keylength, verbose)
if (verbose == nil) then verbose = false end
local key = "";
for index = 1, keylength, 1 do
local charmap = {}
local keyindex = 1
for i = 1, #text do
local c = text:lower():sub(i,i)
if language:find(c) then
if (keyindex == index) then
if (charmap[c]) then charmap[c] = charmap[c] + 1 else charmap[c] = 1 end
end
keyindex = onePadding((keyindex + 1) % (keylength + 1))
end
end
-- guessing statistically the key
local sortedOccurences = getKeysSortedByValue(charmap, function(a, b) return a < b end)
if (#sortedOccurences ~= 0) then
local k = language:sub(1, 1)
local maxLetter = string.char(((letterValue(sortedOccurences[#sortedOccurences]) - letterValue(k)) % 26) + string.byte('a'))
key = key .. maxLetter
end
end
return key
end
-- 3. Decrypt
function decrypt(text, key, language)
local decrypted = ""
local keyindex = 1
key = key:lower()
for i = 1, #text, 1 do
local c = text:lower():sub(i,i)
if language:find(c) then
local k = key:sub(keyindex,keyindex)
decrypted = decrypted .. string.char(((26 + letterValue(c) - letterValue(k)) % 26) + string.byte('a'))
keyindex = onePadding((keyindex + 1) % (#key + 1))
else
decrypted = decrypted .. c
end
end
return decrypted
end
-- 4. Encrypt
function encrypt(text, key, language)
local crypted = ""
local keyindex = 1
key = key:lower()
for i = 1, #text, 1 do
local c = text:lower():sub(i,i)
if language:find(c) then
local k = key:sub(keyindex,keyindex)
crypted = crypted .. string.char(((26 + letterValue(c) + letterValue(k)) % 26) + string.byte('a'))
keyindex = onePadding((keyindex + 1) % (#key + 1))
else
crypted = crypted .. c
end
end
return crypted
end
-- N/A usefull functions
function compare(a, b)
return a[1] < b[1]
end
function printDict(d)
for k,v in pairs(d) do print(k,v) end
end
function getKeysSortedByValue(tbl, sortFunction)
local keys = {}
for key in pairs(tbl) do table.insert(keys, key) end
table.sort(keys, function(a, b) return sortFunction(tbl[a], tbl[b]) end)
return keys
end
function letterValue(letter)
return (letter:byte() - ("a"):byte())
end
function onePadding(int)
return (int > 0) and int or 1
end
function isInList(key, list)
for _,v in pairs(list) do
if v == key then
return true
end
end
return false
end
function getIndex(key, list)
for t,v in pairs(list) do
if v == key then
return t
end
end
return nil
end
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
-- Help
function printHelp()
print("Usage : lua vigenere.lua [MODE] [OPTIONS]")
print("")
print("# MODES: #")
print("\te\tencrypt by entering a key, and a text")
print("\td\tdecrypt by entering a key, and a text")
print("\tc\tcrack")
print("#-------------------------------------------#")
print("\te parameter : lua vigenere.lua e [OPTIONS --raw | OPTIONS --file] key")
print("")
print("\t\t--raw 'text in console'")
print("\t\t--file [path to file]")
print("#-------------------------------------------#")
print("\td parameter : lua vigenere.lua [OPTIONS --raw | OPTIONS --file] key")
print("")
print("\t\t--raw 'text in console'")
print("\t\t--file [path to file]")
print("#-------------------------------------------#")
print("\tc parameter : lua vigenere.lua [(OPTIONS --raw | OPTIONS --file) && --maxkeylength keylength]")
print("\t\t--raw 'text in console'")
print("\t\t--file [path to file]")
print("\t\t--maxkeylength [integer keylength] : this parameter is mandatory")
print("\t\t--trylength [lower:upper] : this parameter is mandatory and should not be used with maxkeylength")
print("#-------------------------------------------#")
end
-- TEST FUNCTION
function TEST()
longText = [===[
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sed ipsum sit amet metus suscipit pharetra. Pellentesque imperdiet a enim ut cursus. Nullam euismod blandit urna, sit amet faucibus lectus tristique ac. Nulla congue ac lacus nec tempus. Suspendisse dapibus metus vel diam porta interdum. Donec pulvinar a magna id dignissim. Nulla eleifend laoreet urna. Aliquam sit amet risus vitae neque ornare sodales nec vel odio. Vivamus eu est id lacus faucibus eleifend. Nulla nec pharetra massa. Duis quis iaculis elit. Cras et hendrerit elit. Sed at neque et orci semper eleifend vitae eget nisl. Morbi malesuada pellentesque urna, sit amet efficitur purus eleifend accumsan. Etiam lectus nisl, consectetur eget lacus vitae, cursus facilisis libero. Nullam vitae vehicula eros. Vestibulum vitae commodo velit. Integer elementum pellentesque venenatis. Duis eget urna ac lectus ullamcorper ullamcorper et vel risus. In ante est, consequat eget lacinia vel, tincidunt nec erat. Integer lobortis mi ante, ut condimentum purus commodo vel. In hac habitasse platea dictumst. Suspendisse vulputate hendrerit nisi elementum vulputate.
Nulla posuere vestibulum sem, id pulvinar quam malesuada dapibus. Integer porttitor ac velit quis malesuada. Cras eu ligula quis arcu dictum ultrices ac at odio. Nulla sit amet nulla sed odio vehicula aliquam sed nec tortor. Sed viverra enim sit amet odio elementum, ut vehicula erat convallis. Ut leo mauris, blandit ut pulvinar sit amet, tristique at quam. Integer est eros, ornare non erat at, vulputate tempus neque. Sed ornare felis sit amet lectus pellentesque, ac suscipit ex venenatis. In finibus vel lorem ac dignissim.
Aenean rutrum sodales urna, non venenatis diam scelerisque et. Aliquam porttitor augue sed dapibus auctor. Nulla tempus leo nec leo tristique interdum. Maecenas vehicula, enim ac efficitur ullamcorper, ligula ante elementum ligula, vitae semper enim sapien sit amet felis. Nullam lobortis accumsan est, accumsan lobortis neque sollicitudin eget. Morbi lacus arcu, vulputate sed dictum sed, auctor id elit. Proin nisl dui, pellentesque et diam et, mattis convallis sapien. Aliquam semper imperdiet ante, non suscipit risus molestie sed. Morbi gravida sem metus, sed varius augue eleifend sed. Donec pulvinar ipsum nunc, at mattis ex sodales at. In dignissim libero nisl, sit amet pharetra diam aliquet non. Aliquam consectetur lacinia ex ac sollicitudin.
In non auctor leo. Praesent maximus luctus tortor. Donec luctus, dolor vel mattis porttitor, orci felis vestibulum eros, sit amet tempus lorem felis ut nulla. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc non consequat neque. Donec mollis gravida urna, sed iaculis augue pellentesque non. Suspendisse ac porta urna. Sed congue finibus felis viverra varius. In nisl justo, iaculis sed fringilla nec, semper non dui. Vivamus cursus ante eu interdum ultricies. Nunc volutpat consectetur volutpat. Nam ut massa nec massa eleifend mollis non sed ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;]===]
print("#----------------------------#")
r = encrypt(longText, "lua", english)
print(r)
print("#----------------------------#")
print(" DECRYPTION ")
print("#----------------------------#")
len = keylengthguess(r, english, 5)
print("Length guess is : " .. len.keylength)
pseudoKey = guessingKey(r, english, len.keylength)
print("Psuedo key guess is : ".. pseudoKey)
print("#----------------------------#")
print(" TESTING ")
print("#----------------------------#")
d = decrypt(r, pseudoKey, english)
print(d)
print("#----------------------------#")
end
-- Main Function
function main(args)
if #args > 0 then
if isInList("e", args) then
cmdEncode(args)
elseif isInList("d", args) then
cmdDecode(args)
elseif isInList("c", args) then
cmdCrack(args)
elseif isInList("-h", args) or isInList("--help", args) then
printHelp()
else
print("No command found. Use --help for list and usages")
end
else
printHelp()
end
end
function cmdEncode(cli)
local string = nil
local key = nil
local language = english
if isInList("--file", cli) then
local path = getIndex("--file", cli) + 1
if cli[path] ~= nil then
file = io.open(cli[path], "r")
string = file:read("*a")
else
print("Error argument : incorrect path")
os.exit()
end
elseif isInList("--raw", cli) then
local text = getIndex("--raw", cli) + 1
if cli[text] ~= nil then
string = cli[text]
else
print("Error argument : incorrect text")
os.exit()
end
end
key = cli[#cli]
print(encrypt(string, key, english))
end
function cmdDecode(cli)
local string = nil
local key = nil
local language = english
if isInList("--file", cli) then
local path = getIndex("--file", cli) + 1
if cli[path] ~= nil then
file = io.open(cli[path], "r")
string = file:read("*a")
else
print("Error argument : incorrect path")
os.exit()
end
elseif isInList("--raw", cli) then
local text = getIndex("--raw", cli) + 1
if cli[text] ~= nil then
string = cli[text]
else
print("Error argument : incorrect text")
os.exit()
end
end
key = cli[#cli]
print(decrypt(string, key, language))
end
function cmdCrack(cli)
local string = nil
local keylength = nil
local lower = nil
local upper = nil
local language = english
if isInList("--file", cli) then
local path = getIndex("--file", cli) + 1
if cli[path] ~= nil then
file = io.open(cli[path], "r")
string = file:read("*a")
else
print("Error argument : incorrect path")
os.exit()
end
elseif isInList("--raw", cli) then
local text = getIndex("--raw", cli) + 1
if cli[text] ~= nil then
string = cli[text]
else
print("Error argument : incorrect text")
os.exit()
end
end
if isInList("--maxkeylength", cli) then
local mkl = getIndex("--maxkeylength", cli) + 1
if cli[mkl] ~= nil then
keylength = cli[mkl]
end
elseif isInList("--trylength", cli) then
local tl = getIndex("--trylength", cli) + 1
if cli[tl] ~= nil then
lower, upper = cli[tl]:match("([^,]+):([^,]+)")
end
end
if keylength then
local keyguess = guessingKey(string, language, keylength)
print("Key guess is : " .. keyguess)
print(decrypt(string, keyguess, language))
elseif lower and upper then
for try = tonumber(lower), tonumber(upper), 1 do
local keyguess = guessingKey(string, language, try)
print("[" .. try .. "] Key guess is : " .. keyguess)
end
else
local len = keylengthguess(string, english)
print("Length guess is : " .. len.keylength)w
local pseudoKey = guessingKey(string, english, len.keylength)
print("Key guess is : ".. pseudoKey)
print(decrypt(string, pseudoKey, language))
end
end
main(params)