-
Notifications
You must be signed in to change notification settings - Fork 2
/
EasyEncryptionEverywhere.html
357 lines (316 loc) · 30.5 KB
/
EasyEncryptionEverywhere.html
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Easy Encryption Everywhere</title>
<script>
const base64selfDecryptingLibSource = "dmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7CiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH0KICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH0KICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvclsidGhyb3ciXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9CiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH0KICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7CiAgICB9KTsKfTsKdmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHsKICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7CiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgInRocm93IjogdmVyYigxKSwgInJldHVybiI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZzsKICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfQogICAgZnVuY3Rpb24gc3RlcChvcCkgewogICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuIik7CiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHsKICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVsicmV0dXJuIl0gOiBvcFswXSA/IHlbInRocm93Il0gfHwgKCh0ID0geVsicmV0dXJuIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0OwogICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07CiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHsKICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTsKICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTsKICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9CiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH0KICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH0KICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpOwogICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7CiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfQogICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9OwogICAgfQp9OwpleHBvcnQgZnVuY3Rpb24gYnVmZmVyVG9VaW50OEFycmF5KGJ1ZmZlcikgewogICAgdmFyIGxlbiA9IGJ1ZmZlci5sZW5ndGg7CiAgICB2YXIgYnl0ZXMgPSBuZXcgVWludDhBcnJheShsZW4pOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICAgIGJ5dGVzW2ldID0gYnVmZmVyW2ldOwogICAgfQogICAgcmV0dXJuIGJ5dGVzOwp9Ci8vIE5vZGUuanMgYW5kIGJyb3dzZXIgaGF2ZSBkaWZmZXJlbnQgZW52aXJvbm1lbnRzIGFuZAovLyBkaWZmZXJlbnQgd2F5cyBvZiBjb252ZXJ0aW5nIGJldHdlZW4gc3RyaW5ncyBhbmQgYmluYXJ5IGRhdGEuCmV4cG9ydCBmdW5jdGlvbiBiYXNlNjRUb1VpbnQ4QXJyYXkoYmFzZTY0KSB7CiAgICBpZiAodHlwZW9mIEJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcpIHsKICAgICAgICAvLyBOb2RlLmpzIGVudmlyb25tZW50IGZvciB0ZXN0aW5nLgogICAgICAgIHJldHVybiBidWZmZXJUb1VpbnQ4QXJyYXkoQnVmZmVyLmZyb20oYmFzZTY0LCAnYmFzZTY0JykpOwogICAgfQogICAgZWxzZSBpZiAodHlwZW9mIGF0b2IgIT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgLy8gQnJvd3NlciBlbnZpcm9ubWVudAogICAgICAgIHZhciBiaW5hcnlTdHJpbmcgPSBhdG9iKGJhc2U2NCk7CiAgICAgICAgdmFyIGxlbiA9IGJpbmFyeVN0cmluZy5sZW5ndGg7CiAgICAgICAgdmFyIGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobGVuKTsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgIGJ5dGVzW2ldID0gYmluYXJ5U3RyaW5nLmNoYXJDb2RlQXQoaSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBieXRlczsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gc3VpdGFibGUgYmFzZTY0IGRlY29kaW5nIG1ldGhvZCBmb3VuZCcpOwogICAgfQp9Ci8qIENvbXBpbGVkIHZlcnNpb24gb2YgdGhpcyBmdW5jdGlvbiBBTkQgQUxMIEhFTFBFUiBGVU5DVElPTlMKICAgc2hvdWxkIGJlIGluIFNlbGZFeHRyYWN0aW5nVGVtcGxhdGUuaHRtbCAgKi8KZXhwb3J0IGZ1bmN0aW9uIGRlY3J5cHRTdHJpbmcoY3J5cHRvLCBzdWJ0bGUsIHBhc3N3b3JkLCBiYXNlNjRFbmNvZGVkU2FsdCwgYmFzZTY0RW5jb2RlZEl2LCBiYXNlNjRFbmNvZGVkRW5jcnlwdGVkRmlsZSkgewogICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBzYWx0LCBrZXksIGFlc0tleSwgaXYsIGVuY3J5cHRlZEZpbGUsIGRlY3J5cHRlZEZpbGUsIGVfMTsKICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7CiAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgICBzYWx0ID0gYmFzZTY0VG9VaW50OEFycmF5KGJhc2U2NEVuY29kZWRTYWx0KTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBzdWJ0bGUuaW1wb3J0S2V5KCdyYXcnLCBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUocGFzc3dvcmQpLCB7IG5hbWU6ICdQQktERjInIH0sIGZhbHNlLCBbJ2Rlcml2ZUJpdHMnLCAnZGVyaXZlS2V5J10pXTsKICAgICAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgICAgICBrZXkgPSBfYS5zZW50KCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0IC8qeWllbGQqLywgc3VidGxlLmRlcml2ZUtleSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnUEJLREYyJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbHQ6IHNhbHQuYnVmZmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0aW9uczogNjAwMDAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzaDogJ1NIQS0yNTYnCiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGtleSwgeyBuYW1lOiAnQUVTLUdDTScsIGxlbmd0aDogMjU2IH0sIHRydWUsIFsnZW5jcnlwdCcsICdkZWNyeXB0J10pXTsKICAgICAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICAgICAgICBhZXNLZXkgPSBfYS5zZW50KCk7CiAgICAgICAgICAgICAgICAgICAgaXYgPSBiYXNlNjRUb1VpbnQ4QXJyYXkoYmFzZTY0RW5jb2RlZEl2KTsKICAgICAgICAgICAgICAgICAgICBlbmNyeXB0ZWRGaWxlID0gYmFzZTY0VG9VaW50OEFycmF5KGJhc2U2NEVuY29kZWRFbmNyeXB0ZWRGaWxlKTsKICAgICAgICAgICAgICAgICAgICBfYS5sYWJlbCA9IDM7CiAgICAgICAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFszLCA1LCAsIDZdKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQgLyp5aWVsZCovLCBzdWJ0bGUuZGVjcnlwdCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnQUVTLUdDTScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdjogaXYuYnVmZmVyCiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGFlc0tleSwgZW5jcnlwdGVkRmlsZSldOwogICAgICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICAgICAgICAgIGRlY3J5cHRlZEZpbGUgPSBfYS5zZW50KCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi8sIG5ldyBVaW50OEFycmF5KGRlY3J5cHRlZEZpbGUpXTsKICAgICAgICAgICAgICAgIGNhc2UgNToKICAgICAgICAgICAgICAgICAgICBlXzEgPSBfYS5zZW50KCk7CiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlXzEpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiAvKnJldHVybiovLCBudWxsXTsKICAgICAgICAgICAgICAgIGNhc2UgNjogcmV0dXJuIFsyIC8qcmV0dXJuKi9dOwogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICB9KTsKfQovLyMgc291cmNlTWFwcGluZ1VSTD1TZWxmRGVjcnlwdGluZ0xpYi5qcy5tYXA="
const base64selfDecryptingTemplate = "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KICAgIDxoZWFkPgogICAgICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4KICAgICAgICA8dGl0bGU+UGFzc3dvcmQtcHJvdGVjdGVkIGNvcHkgb2YgPCEtLUZJTEVOQU1FLS0+PC90aXRsZT4KICAgICAgICA8c2NyaXB0PgogICAgICAgICAgICBsZXQgYmFzZTY0RW5jb2RlZEZpbGUgPSAiPCEtLUVOQ1JZUFRFRF9GSUxFLS0+IjsKICAgICAgICAgICAgbGV0IGJhc2U2NEVuY29kZWRTYWx0ID0gIjwhLS1TQUxULS0+IjsKICAgICAgICAgICAgbGV0IGJhc2U2NEVuY29kZWRJViA9ICI8IS0tSU5JVElBTElaQVRJT05fVkVDVE9SLS0+IjsKCiAgICAgICAgICAgIC8vPCEtLURFQ1JZUFRJT05fTElCLS0+CgoKICAgICAgICAgICAgYXN5bmMgZnVuY3Rpb24gaGFuZGxlQnV0dG9uKGV2ZW50KSB7CiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOwoKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cuY3J5cHRvID09PSAidW5kZWZpbmVkIikgewogICAgICAgICAgICAgICAgICAgICAgICBhbGVydCgiWW91ciBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgdGhlIFdlYiBDcnlwdG9ncmFwaHkgQVBJLiAgTWFqb3IgYnJvd3NlcnMgc2luY2UgMjAxNSBzdXBwb3J0IFdlYiBDcnlwdG8uICBQbGVhc2UgdXBkYXRlIG9yIHVzZSBhIGRpZmZlcmVudCBicm93c2VyLiIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfSAKCiAgICAgICAgICAgICAgICAgICAgbGV0IHN1YnRsZTsgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cuY3J5cHRvLnN1YnRsZSAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VidGxlID0gd2luZG93LmNyeXB0by5zdWJ0bGU7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93LmNyeXB0by53ZWJraXRTdWJ0bGUgIT09ICJ1bmRlZmluZWQiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnRsZSA9IHdpbmRvdy5jcnlwdG8ud2Via2l0U3VidGxlOyAgLy8gRWFybHkgU2FmYXJpIHN1cHBvcnQKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBhbGVydCgiWW91ciBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgdGhlIFdlYiBDcnlwdG9ncmFwaHkgQVBJLiAgIE1ham9yIGJyb3dzZXJzIHNpbmNlIDIwMTUgc3VwcG9ydCBXZWIgQ3J5cHRvLiAgUGxlYXNlIHVwZGF0ZSBvciB1c2UgYSBkaWZmZXJlbnQgYnJvd3Nlci4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAgICAgCiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBsZXQgcGFzc3dvcmQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicGFzc3dvcmQiKS52YWx1ZTsKCiAgICAgICAgICAgICAgICAgICAgbGV0IGRlY3J5cHRlZCA9IGF3YWl0IGRlY3J5cHRTdHJpbmcod2luZG93LmNyeXB0bywgc3VidGxlLCBwYXNzd29yZCwgYmFzZTY0RW5jb2RlZFNhbHQsIGJhc2U2NEVuY29kZWRJViwgYmFzZTY0RW5jb2RlZEZpbGUpOwoKICAgICAgICAgICAgICAgICAgICBpZiAoZGVjcnlwdGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBibG9iID0gbmV3IEJsb2IoW2RlY3J5cHRlZF0pOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgdXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTsKCiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpOwogICAgICAgICAgICAgICAgICAgICAgICBsaW5rLnNldEF0dHJpYnV0ZSgiaHJlZiIsIHVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsuc2V0QXR0cmlidXRlKCJkb3dubG9hZCIsICI8IS0tRklMRU5BTUUtLT4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGluay5zdHlsZS52aXNpYmlsaXR5ID0gImhpZGRlbiI7CiAgICAgICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQobGluayk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsuY2xpY2soKTsKICAgICAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChsaW5rKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBhbGVydCgiSW5jb3JyZWN0IHBhc3N3b3JkIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICBhbGVydCgiQW4gZXJyb3Igb2NjdXJyZWQuICBDaGVjayB0aGUgY29uc29sZSBsb2cgZm9yIGRldGFpbHMuIik7CiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgPC9zY3JpcHQ+CiAgICA8L2hlYWQ+CiAgICA8Ym9keSBzdHlsZT0ibWF4LXdpZHRoOjE4Y207IG1hcmdpbjogYXV0bzsiPgogICAgICAgIDxoMSBzdHlsZT0iZm9udC1mYW1pbHk6IEFyaWFsLCBzYW5zLXNlcmlmOyI+CiAgICAgICAgICAgIDwhLS0gbG9nbyAtLT4gICAgCiAgICAgICAgICAgIDxzdmcgd2lkdGg9IjFlbSIgdmlld0JveD0iMCAwIDEwMCAxMjUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICAgICAgICAgICAgICA8ZGVmcz48L2RlZnM+CiAgICAgICAgICAgICAgICA8ZWxsaXBzZSBzdHlsZT0ic3Ryb2tlOiByZ2IoMCwgMCwgMCk7IiBjeD0iNTAiIGN5PSI0NSIgcng9IjQ1IiByeT0iNDUiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgIDxlbGxpcHNlIHN0eWxlPSJzdHJva2U6IHJnYigwLCAwLCAwKTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyIgY3g9IjUwIiBjeT0iNDUiIHJ4PSIyNSIgcnk9IjI1Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICA8cmVjdCB4PSIwIiB5PSI0MCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI4NSIgc3R5bGU9InN0cm9rZTogcmdiKDAsIDAsIDApOyI+PC9yZWN0PgogICAgICAgICAgICAgICAgPHRleHQgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZm9udC1mYW1pbHk6IEFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDQwcHg7IHdoaXRlLXNwYWNlOiBwcmU7IiB4PSIxMCIgeT0iOTUiPkVFRTwvdGV4dD4KICAgICAgICAgICAgPC9zdmc+CiAgICAgICAgICAgIFBhc3N3b3JkLXByb3RlY3RlZCBmaWxlOiA8IS0tRklMRU5BTUUtLT48L2gxPgogICAgICAgIDxwPgogICAgICAgICAgICBUaGlzIGlzIGEgcGFzc3dvcmQtcHJvdGVjdGVkIGZpbGUgY3JlYXRlZCB3aXRoIAogICAgICAgICAgICA8YSBocmVmPSJodHRwczovL21pY2hhZWxkbmFoYXMuY29tL0Vhc3lFbmNyeXB0aW9uRXZlcnl3aGVyZS5odG1sIj5FYXN5IEVuY3J5cHRpb24gRXZlcnl3aGVyZTwvYT4uCiAgICAgICAgICAgIEl0IHVzZXMgQUVTLTI1NiBlbmNyeXB0aW9uLCB3aGljaCB3YXMgCiAgICAgICAgICAgIDxhIGhyZWY9Imh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbW1lcmNpYWxfTmF0aW9uYWxfU2VjdXJpdHlfQWxnb3JpdGhtX1N1aXRlIj5hcHByb3ZlZCBieSB0aGUgCiAgICAgICAgICAgIFVTIGdvdmVybm1lbnQgZm9yIFRvcCBTZWNyZXQgZG9jdW1lbnRzPC9hPi4gCiAgICAgICAgPC9wPgogICAgICAgIDxiciAvPgogICAgICAgIAogICAgICAgIDxwPgogICAgICAgICAgICBQbGVhc2UgZW50ZXIgdGhlIHBhc3N3b3JkIHRvIGV4dHJhY3QgIjwhLS1GSUxFTkFNRS0tPiIuCiAgICAgICAgICAgIDxmb3JtIGFjdGlvbj0iIiBpZD0icGFzc3dvcmRGb3JtIiBvbnN1Ym1pdD0iaGFuZGxlQnV0dG9uKGV2ZW50KSI+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJwYXNzd29yZCI+UGFzc3dvcmQ6PC9sYWJlbD4KICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBpZD0icGFzc3dvcmQiIC8+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCI+RGVjcnlwdCBGaWxlPC9idXR0b24+CiAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICA8L3A+ICAgIAogICAgPC9ib2R5Pgo8L2h0bWw+Cg=="
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
function encryptBuffer(crypto, subtle, fileUint8Array, password) {
return __awaiter(this, void 0, void 0, function () {
var salt, key, aesKey, iv, encryptedFile, base64EncodedSalt, base64EncodedIv, base64EncodedEncryptedFile;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
salt = crypto.getRandomValues(new Uint8Array(16));
return [4 /*yield*/, subtle.importKey('raw', new TextEncoder().encode(password), { name: 'PBKDF2' }, false, ['deriveBits', 'deriveKey'])];
case 1:
key = _a.sent();
return [4 /*yield*/, subtle.deriveKey({
name: 'PBKDF2',
salt: salt,
iterations: 600000,
hash: 'SHA-256'
}, key, { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt'])];
case 2:
aesKey = _a.sent();
iv = crypto.getRandomValues(new Uint8Array(12));
return [4 /*yield*/, subtle.encrypt({
name: 'AES-GCM',
iv: iv
}, aesKey, fileUint8Array.buffer)];
case 3:
encryptedFile = _a.sent();
base64EncodedSalt = btoa(Uint8ArrayToString(new Uint8Array(salt)));
base64EncodedIv = btoa(Uint8ArrayToString(new Uint8Array(iv)));
base64EncodedEncryptedFile = btoa(Uint8ArrayToString(new Uint8Array(encryptedFile)));
return [2 /*return*/, [base64EncodedSalt, base64EncodedIv, base64EncodedEncryptedFile,]];
}
});
});
}
function Uint8ArrayToString(uint8Array) {
// This exceeds the stack size for large files on Chrome:
// return String.fromCharCode.apply(null, uint8Array);
// Cannot just append to a string, because strings are constant
// and appending is O(N) runtime. So, we push to an array and
// then call join.
var arrayOfString = [];
for (var i = 0; i < uint8Array.length; i++) {
arrayOfString.push(String.fromCharCode(uint8Array[i]));
}
return arrayOfString.join('');
}
function base64ToString(s) {
if (typeof Buffer !== 'undefined') {
// Node.js environment for testing.
return Buffer.from(s, 'base64').toString('utf-8');
}
else {
// Browser environment
return atob(s);
}
}
function generateEncryptedHmtlFile(crypto, subtle, fileUint8Array, password, filenameWithoutDir, base64selfDecryptingLibSource, base64selfDecryptingTemplate) {
return __awaiter(this, void 0, void 0, function () {
var _a, base64EncodedSalt, base64EncodedIv, base64EncodedEncryptedFile, selfDecryptingLibSource, selfDecryptingTemplate, htmlFile;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, encryptBuffer(crypto, subtle, fileUint8Array, password)];
case 1:
_a = _b.sent(), base64EncodedSalt = _a[0], base64EncodedIv = _a[1], base64EncodedEncryptedFile = _a[2];
selfDecryptingLibSource = base64ToString(base64selfDecryptingLibSource);
selfDecryptingLibSource = selfDecryptingLibSource.replace(/export /g, '');
selfDecryptingTemplate = base64ToString(base64selfDecryptingTemplate);
htmlFile = selfDecryptingTemplate
.replace(/<!--FILENAME-->/g, filenameWithoutDir)
.replace(/<!--ENCRYPTED_FILE-->/g, base64EncodedEncryptedFile)
.replace(/<!--INITIALIZATION_VECTOR-->/g, base64EncodedIv)
.replace(/<!--SALT-->/g, base64EncodedSalt)
.replace(/\/\/<!--DECRYPTION_LIB-->/g, selfDecryptingLibSource);
return [2 /*return*/, htmlFile];
}
});
});
}
function generateRandomPassword(crypto) {
var LENGTH = 24;
// No 0,O,1,l,I
// About 60 values
var charset = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
var randArray = new Uint8Array(LENGTH * 4); // 4 is a huge safety factor.
crypto.getRandomValues(randArray);
var retVal = "";
var randIndex = 0;
while (retVal.length < LENGTH) {
var rand = randArray[randIndex] % 64;
randIndex++;
if (rand < charset.length) {
retVal += charset.charAt(rand);
if (retVal.length % 5 == 4 && retVal.length != LENGTH) {
retVal += "-";
}
}
}
return retVal;
}
//# sourceMappingURL=EncryptingLib.js.map
/* Test code (uncomment to test HTML template file)
function generateEncryptedHmtlFile(crypto,
subtle,
fileContent,
password,
filename,
base64selfDecryptingLibSource,
base64selfDecryptingTemplate) {
alert("You are executing test code. Your file is NOT encrypted.")
console.log("File content as Uint8Array:", fileContent);
console.log("Password:", password);
console.log("Filename:", filename);
return fileContent
}
function generateRandomPassword() {
return "testPassword";
}
*/
// Initialize password field with a random password
function newPassword() {
if (typeof window.crypto !== "undefined") {
document.getElementById('passwordInput').value = generateRandomPassword(window.crypto);
}
}
async function handleButton(event) {
try {
event.preventDefault();
if (typeof window.crypto === "undefined") {
alert("Your browser does not support the Web Cryptography API. Major browsers since 2015 support Web Crypto. Please update or use a different browser.");
return;
}
let subtle;
if (typeof window.crypto.subtle !== "undefined") {
subtle = window.crypto.subtle;
} else if (typeof window.crypto.webkitSubtle !== "undefined") {
subtle = window.crypto.webkitSubtle; // Early Safari support
} else {
alert("Your browser does not support the Web Cryptography API. Major browsers since 2015 support Web Crypto. Please update or use a different browser.");
return;
}
const fileInput = document.getElementById('fileInput');
const passwordInput = document.getElementById('passwordInput');
if (!passwordInput.value) {
// TODO: When left blank, this program should generate a random password.
alert("Please enter a password.");
return;
}
if (fileInput.files.length === 1) {
const file = fileInput.files[0];
const buffer = await file.arrayBuffer()
const inputUint8Array = new Uint8Array(buffer)
const outputUint8Array = await generateEncryptedHmtlFile(window.crypto,
subtle,
inputUint8Array,
passwordInput.value,
file.name,
base64selfDecryptingLibSource,
base64selfDecryptingTemplate);
if (outputUint8Array) {
let blob = new Blob([outputUint8Array]);
let url = URL.createObjectURL(blob);
let link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", file.name + ".ENCRYPTED.html");
link.style.visibility = "hidden";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} else {
alert("Encryption failed. No file was created.");
}
} else if (fileInput.files.length > 1) {
alert("This program can only encrypt one file at a time.");
} else {
alert("Please select a file.");
}
} catch (error) {
alert("An error occurred. Check console log for details.");
console.error(error);
}
}
</script>
</head>
<body style="max-width:18cm; margin: auto;">
<h1 style="font-family: Arial, sans-serif;">
<!-- logo -->
<svg width="1em" viewBox="0 0 100 125" xmlns="http://www.w3.org/2000/svg">
<defs></defs>
<ellipse style="stroke: rgb(0, 0, 0);" cx="50" cy="45" rx="45" ry="45"></ellipse>
<ellipse style="stroke: rgb(0, 0, 0); fill: rgb(255, 255, 255);" cx="50" cy="45" rx="25" ry="25"></ellipse>
<rect x="0" y="40" width="100" height="85" style="stroke: rgb(0, 0, 0);"></rect>
<text style="fill: rgb(255, 255, 255); font-family: Arial, sans-serif; font-size: 40px; white-space: pre;" x="10" y="95">EEE</text>
</svg>
Easy Encryption Everywhere</h1>
<p><i>Create a password-protected file. It's easy!</i></p>
<form action="" onsubmit="handleButton(event)">
<label for="fileInput">File:</label>
<input type="file" id="fileInput"><br><br>
<label for="passwordInput">Password:</label>
<input type="text" id="passwordInput" style="font-family: monospace; width: 25em;">
<button type="button" onclick="newPassword()">Generate a Strong Random Password</button><br><br>
<button type="submit">Encrypt!</button>
</form>
<br />
<br />
<br />
<hr />
<h2>What is <i>Easy Encryption Everywhere</i>?</h2>
<p>Easy Encryption Everywhere creates password-protected files
using high-level encryption
and almost every receiver can decrypt them.</p>
<p><b>Easy:</b> You choose a file and enter a password.
Then, Easy Encryption Everywhere encrypts the file inside your own webbrowser.
The password-protected data is saved inside an HTML file.
The recipient opens that HTML file in their webbrowser and types in the password.
Easy Encryption Everywhere decrypts the file inside their webbrowser
and they get the file.</p>
<p><b>Encryption:</b> Easy Encryption Everywhere uses the AES algorithm with 256-bit keys,
which was <a href="https://en.wikipedia.org/wiki/Commercial_National_Security_Algorithm_Suite">approved in 2022 by the US government for Top Secret documents</a>.
</p>
<p><b>Everywhere:</b> As long as the recipient has a major webbrowser from 2015 or later,
they can decrypt the file.</p>
<h2>Who do I thank for this?</h2>
<p>
<b><a href="https://www.unifiedeventsolutions.com/">Unified Event Solutions</a></b>.
My friend owns the company and they needed to send credit card data to a client.
My friend didn't know what encryption software was on the client's computer
and wasn't sure if the client could install software.
My friend sponsored the initial version of Easy Encryption Everywhere.</p>
<p>Unified Event Solutions organizes large conferences.
If you have a multi-hotel conference and need services like
site selection, hotel contract negotiation, and/or transportation, please
reward my friend's decision to open-source this software and
<a href="https://www.unifiedeventsolutions.com/contact.html">contact Unified Event Solutions</a>.</p>
<h2>How do I trust you?</h2>
<p>I'm a good guy and been developing open-source for decades,
but trust over the internet is <i>hard</i>.</p>
<p>To start, the authentic copy of Easy Encryption Everywhere
is at <a href="https://michaeldnahas.com/EasyEncryptionEverywhere.html">https://michaeldnahas.com/EasyEncryptionEverywhere.html</a>.
Beware someone pointing you to a different site or sending you a saved HTML file.
</p>
<p>If you're paranoid and know JavaScript, you can load this webpage,
disconnect your computer from the internet, encrypt your data,
and look at the generated HTML file. The JavaScript program
inside the HTML is simple to understand.</p>
<p>
<a href="https://github.com/mdnahas/easy_encryption_everywhere">All code is open-sourced and available on Github</a>.
You can look at the code and see that it doesn't send/save your data anywhere.
Or, if you don't trust my website, you're welcome to compile the TypeScript for yourself.
</p>
<h2>What tech does this use?</h2>
<p>Easy Encryption Everywhere uses the Web Cryptography API,
which is available in major webbrowsers since 2015.
For generating an encryption key,
it uses PBKDF2-HMAC-SHA256 with a 128-bit salt and 600,000 iterations.
For encryption, it uses AES-GCM with a 256-bit key and a 96-bit initialization vector.
The salt, initialization vector, and passwords are generated using crypto.getRandomValues().
</p>
<p>If you're a geek, check out the code.
It has a program that produces a program that produces a program!</p>
<h2>What legal mumbo-jumbo do you have to say?</h2>
<p>Easy Encryption Everywhere comes with no warrantee.
(That said, I trust it enough to have my friend's company use it.)
Easy Encryption Everywhere is my trademark.
If you modify the code, you cannot call it "Easy Encryption Everywhere."
(But you can send me a pull request on Github to have your changed integrated into Easy Encryption Everywhere.)
It is licensed under <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons BY 4.0 license</a>.
Copyright 2024 Michael D. Nahas.
</p>
<br/>
<a href="#">Back to top of page.</a>
</body>
</html>