Subversion Repositories cryptochat

Rev

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