Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | daniel-mar | 1 | <?php |
2 | |||
3 | // ViaThinkSoft CryptoChat |
||
4 | // (C) 2014 by Daniel Marschall, ViaThinkSoft |
||
5 | // Licensed under the terms of GPLv3 |
||
6 | |||
7 | // ----------------------------------------------------------------------------------------------- |
||
8 | |||
9 | require __DIR__ . '/../config/config.inc.php'; |
||
10 | define('PRODUCT_NAME', 'CryptoChat'); |
||
11 | define('MCC_VER', trim(file_get_contents(__DIR__ . '/../VERSION'))); |
||
12 | |||
13 | header('Content-type: text/html; charset=utf-8'); |
||
14 | |||
15 | ?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
||
16 | "http://www.w3.org/TR/html4/loose.dtd"> |
||
17 | |||
18 | <html> |
||
19 | |||
20 | <head> |
||
21 | <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=utf-8"> |
||
22 | <title><?php echo PRODUCT_NAME; ?> - Manually encrypt chat lines</title> |
||
23 | |||
24 | <script type="text/javascript" src="../<?php echo DEP_DIR_CRYPTOJS; ?>/rollups/sha256.js"></script> |
||
25 | <script type="text/javascript" src="../<?php echo DEP_DIR_CRYPTOJS; ?>/rollups/sha1.js"></script> |
||
26 | <script type="text/javascript" src="../<?php echo DEP_DIR_CRYPTOJS; ?>/rollups/aes.js"></script> |
||
27 | <script type="text/javascript" src="../<?php echo DEP_DIR_CRYPTOJS; ?>/rollups/md5.js"></script> |
||
28 | |||
29 | <script type="text/javascript"> |
||
30 | |||
31 | var roomSalt = null; |
||
32 | |||
33 | // http://stackoverflow.com/questions/1349404/generate-a-string-of-5-random-characters-in-javascript/1349426#1349426 |
||
34 | function randomString(len) { |
||
35 | var text = ""; |
||
36 | var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; |
||
37 | |||
38 | for( var i=0; i < len; i++ ) { |
||
39 | text += possible.charAt(Math.floor(Math.random() * possible.length)); |
||
40 | } |
||
41 | |||
42 | return text; |
||
43 | } |
||
44 | |||
45 | // -------------------------------------------- |
||
46 | |||
47 | // --- MD5 |
||
48 | |||
49 | var selftest_md5_finished = false; |
||
50 | function selftest_md5() { |
||
51 | if (selftest_md5_finished) return; |
||
52 | selftest_md5_finished = true; |
||
53 | |||
54 | var errors = ""; |
||
55 | cmp_a = CryptoJS.enc.Base64.stringify(CryptoJS.MD5("Message")); |
||
56 | cmp_b = "TCqP5+ryRyHMep8BdRFb1A=="; |
||
57 | if (cmp_a !== cmp_b) { |
||
58 | errors += "MD5 self test failed!\n"; |
||
59 | console.error("MD5 self test failed: '" + cmp_a + "' vs. '" + cmp_b + "'"); |
||
60 | } |
||
61 | |||
62 | if (errors) { |
||
63 | alert(errors+"\nYour browser seems to be buggy. Decryption of particular messages might fail."); |
||
64 | } else { |
||
65 | console.info("AES self test passed"); |
||
66 | } |
||
67 | } |
||
68 | |||
69 | function md5(message) { |
||
70 | selftest_md5(); |
||
71 | var hash = CryptoJS.MD5(message); |
||
72 | hash = CryptoJS.enc.Base64.stringify(hash); |
||
73 | return hash; |
||
74 | } |
||
75 | |||
76 | // --- SHA1 |
||
77 | |||
78 | var selftest_sha1_finished = false; |
||
79 | function selftest_sha1() { |
||
80 | if (selftest_sha1_finished) return; |
||
81 | selftest_sha1_finished = true; |
||
82 | |||
83 | var errors = ""; |
||
84 | cmp_a = CryptoJS.enc.Base64.stringify(CryptoJS.SHA1("Message")); |
||
85 | cmp_b = "aPQUX+593navzrkQFlkkrRTPDQA="; |
||
86 | if (cmp_a !== cmp_b) { |
||
87 | errors += "SHA1 self test failed!\n"; |
||
88 | console.error("SHA1 self test failed: '" + cmp_a + "' vs. '" + cmp_b + "'"); |
||
89 | } |
||
90 | |||
91 | if (errors) { |
||
92 | alert(errors+"\nYour browser seems to be buggy. Decryption of particular messages might fail."); |
||
93 | } else { |
||
94 | console.info("SHA1 self test passed"); |
||
95 | } |
||
96 | } |
||
97 | |||
98 | function sha1(message) { |
||
99 | selftest_sha1(); |
||
100 | var hash = CryptoJS.SHA1(message); |
||
101 | hash = CryptoJS.enc.Base64.stringify(hash); |
||
102 | return hash; |
||
103 | } |
||
104 | |||
105 | function sha1_base16(message) { |
||
106 | selftest_sha1(); |
||
107 | return CryptoJS.SHA1(message).toString(); |
||
108 | } |
||
109 | |||
110 | // --- SHA256 |
||
111 | |||
112 | var selftest_sha256_finished = false; |
||
113 | function selftest_sha256() { |
||
114 | if (selftest_sha256_finished) return; |
||
115 | selftest_sha256_finished = true; |
||
116 | |||
117 | var errors = ""; |
||
118 | cmp_a = CryptoJS.enc.Base64.stringify(CryptoJS.SHA256("Message")); |
||
119 | cmp_b = "L3dmip37+NWEi57rSnFFypTG7ZI25Kdz9tyvpRMrL5E="; |
||
120 | if (cmp_a !== cmp_b) { |
||
121 | errors += "SHA256 self test failed!\n"; |
||
122 | console.error("SHA256 self test failed: '" + cmp_a + "' vs. '" + cmp_b + "'"); |
||
123 | } |
||
124 | |||
125 | if (errors) { |
||
126 | alert(errors+"\nYour browser seems to be buggy. Decryption of particular messages might fail."); |
||
127 | } else { |
||
128 | console.info("AES self test passed"); |
||
129 | } |
||
130 | } |
||
131 | |||
132 | function sha256(message) { |
||
133 | selftest_sha256(); |
||
134 | var hash = CryptoJS.SHA256(message); |
||
135 | hash = CryptoJS.enc.Base64.stringify(hash); |
||
136 | return hash; |
||
137 | } |
||
138 | |||
139 | // --- AES |
||
140 | |||
141 | var selftest_aes_finished = false; |
||
142 | function selftest_aes() { |
||
143 | if (selftest_aes_finished) return; |
||
144 | selftest_aes_finished = true; |
||
145 | |||
146 | var errors = ""; |
||
147 | var cmp_a = CryptoJS.AES.decrypt("U2FsdGVkX19kJJkA0NL7WJRdXKrdqDcf6A2yDODaL2g=", "Secret Passphrase").toString(CryptoJS.enc.Utf8); |
||
148 | var cmp_b = "Message"; |
||
149 | if ((cmp_a !== cmp_b) || (aes_dec(aes_enc("Message")) !== "Message")) { |
||
150 | errors += "AES self test failed!\n"; |
||
151 | console.error("AES self test failed: '" + cmp_a + "' vs. '" + cmp_b + "'"); |
||
152 | } |
||
153 | |||
154 | if (errors) { |
||
155 | alert(errors+"\nYour browser seems to be buggy. Decryption of particular messages might fail."); |
||
156 | } else { |
||
157 | console.info("AES self test passed"); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | function aes_enc(msg, ver) { |
||
162 | // ver is currently not used |
||
163 | selftest_aes(); |
||
164 | var passwd = getPassword(); |
||
165 | return CryptoJS.AES.encrypt(msg, roomSalt+passwd); |
||
166 | } |
||
167 | |||
168 | function aes_dec(msg, ver) { |
||
169 | // ver is currently not used |
||
170 | selftest_aes(); |
||
171 | var passwd = getPassword(); |
||
172 | try { |
||
173 | return CryptoJS.AES.decrypt(msg, roomSalt+passwd).toString(CryptoJS.enc.Utf8); |
||
174 | } catch (e) { |
||
175 | return null; |
||
176 | } |
||
177 | } |
||
178 | |||
179 | # --- |
||
180 | |||
181 | // Alternative hash digest for compatibility issues |
||
182 | // Some browsers like Jumanji have problems using SHA1 or SHA2, but work with MD5, e.g. |
||
183 | // Jumanji 1.1.2.4 (versionsangabe nicht sicher) ist inkompatibel mit CryptoJS 3.1.2 |
||
184 | // UA = "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/534.26+ (KHTML, like Gecko) Version/5.0 Safari/534.26+ jumanji/0.0" |
||
185 | // CryptoJS.MD5("Message"): |
||
186 | // - Normal: 4c2a8fe7eaf24721cc7a9f0175115bd4 |
||
187 | // - Jumanji: 4c2a8fe7eaf24721cc7a9f0175115bd4 (OK) |
||
188 | // CryptoJS.SHA1("Message"): |
||
189 | // - Normal: 68f4145fee7dde76afceb910165924ad14cf0d00 |
||
190 | // - Jumanji: 5a5aa74ecae1d696900b034d5f1b71497c170ea0 (Error) |
||
191 | // CryptoJS.SHA256("Message"): |
||
192 | // - Normal: 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91 |
||
193 | // - Jumanji: 5a28f8b8778c15a166f7f17ebb89ce8e8381fbb5e39ddc2511239793119a649e (Error) |
||
194 | // CryptoJS.AES.encrypt("Message", "Secret Passphrase"): |
||
195 | // - Normal: U2FsdGVkX19zlzNcfljComkcU0A7XfZ+gzZbI+GyFm0= |
||
196 | // - Jumanji: U2FsdGVkX19kJJkA0NL7WJRdXKrdqDcf6A2yDODaL2g= (OK) |
||
197 | // This is a fast version (4x MD5) necessary for slow computers with ARM architecture |
||
198 | function specialMD5fast4(message) { |
||
199 | var a = md5("IuErOmVyPeL2ek6e16vkjTWjssgLmd" + message); |
||
200 | var b = md5("8wxdm3mVi8UQXdboJvCctYwm8ZxTyX" + message); |
||
201 | return md5(a+b) + md5(b+a); |
||
202 | } |
||
203 | |||
204 | function specialHash(val, entrySalt, version) { |
||
205 | var hash = null; |
||
206 | if (version == 1) { |
||
207 | hash = sha256(roomSalt+entrySalt+val); |
||
208 | } else if (version == 2) { |
||
209 | hash = specialMD5fast4(roomSalt+entrySalt+val); |
||
210 | } else { |
||
211 | console.error("Version " + version + " is unknown at specialHash()"); |
||
212 | return null; |
||
213 | } |
||
214 | return entrySalt + "_" + hash + "_ver" + version; |
||
215 | } |
||
216 | |||
217 | // -------------------------------------------- |
||
218 | |||
219 | function getPassword() { |
||
220 | return document.getElementById("key").value; |
||
221 | } |
||
222 | |||
223 | function cbLine(str, p1, p2, p3, offset, s) { |
||
224 | var ver = document.getElementById("ver").value; |
||
225 | var passwd = document.getElementById("key").value; |
||
226 | var entrySalt = randomString(20); |
||
227 | var hash = specialHash(passwd, entrySalt, ver); |
||
228 | |||
229 | return "(date: "+p1+")(user: "+p2+")(dec_"+hash+": "+aes_enc(p3,ver)+")<br>\n"; |
||
230 | } |
||
231 | |||
232 | function convert() { |
||
233 | var ses_room = document.getElementById("room").value; |
||
234 | var xsalt = document.getElementById("xsalt").value; |
||
235 | roomSalt = sha1_base16(xsalt + ses_room); |
||
236 | |||
237 | var message = document.getElementById("in").value + "\n"; |
||
238 | message = message.replace(/(.+?) - \[(.+?)\]: (.+?)\n/g, cbLine); |
||
239 | document.getElementById("out").value = message; |
||
240 | } |
||
241 | |||
242 | function initPage() { |
||
243 | document.getElementById("out").value = ""; |
||
244 | } |
||
245 | </script> |
||
246 | |||
247 | </head> |
||
248 | |||
249 | <body onload="initPage();"> |
||
250 | |||
251 | <h1>Manually encrypt chat lines</h1> |
||
252 | |||
253 | <table border="0" cellpadding="5" cellspacing="0"> |
||
254 | <tr> |
||
255 | <td>Server's X_SALT: </td> |
||
256 | <td><input style="width:500px" id="xsalt" value="<?php if (!KEEP_X_SALT_SECRET) echo X_SALT; ?>"></td> |
||
257 | </tr><tr> |
||
258 | <td>Algorithm: </td> |
||
259 | <td><select id="ver"> |
||
260 | <option value="1"<?php if (CFG_CIPHERSUITE == 1) echo ' selected'; ?>>[1] SHA256</option> |
||
261 | <option value="2"<?php if (CFG_CIPHERSUITE == 2) echo ' selected'; ?>>[2] specialMD5fast4</option> |
||
262 | </select></td> |
||
263 | </tr><tr> |
||
264 | <td>Key: </td> |
||
265 | <td><input style="width:500px" id="key"></td> |
||
266 | </tr><tr> |
||
267 | <td>Chatroom name: </td> |
||
268 | <td><input style="width:500px" id="room"></td> |
||
269 | </tr><tr> |
||
270 | <td colspan="2">Input:<br> |
||
271 | <textarea id="in" cols="100" rows="6">2014-12-31 14:21:20 - [Daniel]: Hello world! |
||
272 | 2014-12-31 14:21:22 - [Daniel]: Example!</textarea><br></td> |
||
273 | </tr><tr> |
||
274 | <td colspan="2"><input type="button" onclick="convert();" value="Convert"><br></td> |
||
275 | </tr><tr> |
||
276 | <td colspan="2">Output:<br> |
||
277 | <textarea id="out" cols="100" rows="6"></textarea></td> |
||
278 | </tr> |
||
279 | </table><br> |
||
280 | </body> |
||
281 | |||
282 | </html> |
||
283 |