├── .npmignore ├── login.png ├── chatform.png ├── src ├── client │ ├── img │ │ ├── channel.png │ │ ├── favicon.ico │ │ └── unnamed.png │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── js │ │ ├── crypto-js │ │ │ ├── enc-hex.js │ │ │ ├── enc-utf8.js │ │ │ ├── enc-latin1.js │ │ │ ├── pad-pkcs7.js │ │ │ ├── format-openssl.js │ │ │ ├── hmac-md5.js │ │ │ ├── hmac-sha1.js │ │ │ ├── hmac-sha256.js │ │ │ ├── hmac-ripemd160.js │ │ │ ├── hmac-sha224.js │ │ │ ├── hmac-sha3.js │ │ │ ├── hmac-sha512.js │ │ │ ├── hmac-sha384.js │ │ │ ├── CONTRIBUTING.md │ │ │ ├── pad-nopadding.js │ │ │ ├── bower.json │ │ │ ├── package.json │ │ │ ├── .bower.json │ │ │ ├── mode-ecb.js │ │ │ ├── pad-iso97971.js │ │ │ ├── pad-zeropadding.js │ │ │ ├── LICENSE │ │ │ ├── pad-iso10126.js │ │ │ ├── pad-ansix923.js │ │ │ ├── mode-ofb.js │ │ │ ├── index.js │ │ │ ├── mode-ctr.js │ │ │ ├── format-hex.js │ │ │ ├── sha224.js │ │ │ ├── mode-cfb.js │ │ │ ├── lib-typedarrays.js │ │ │ ├── sha384.js │ │ │ ├── mode-ctr-gladman.js │ │ │ ├── rc4.js │ │ │ ├── evpkdf.js │ │ │ ├── README.md │ │ │ ├── hmac.js │ │ │ ├── enc-base64.js │ │ │ ├── sha1.js │ │ │ ├── enc-utf16.js │ │ │ ├── pbkdf2.js │ │ │ ├── sha256.js │ │ │ ├── rabbit.js │ │ │ ├── rabbit-legacy.js │ │ │ ├── aes.js │ │ │ ├── x64-core.js │ │ │ ├── ripemd160.js │ │ │ ├── md5.js │ │ │ ├── sha3.js │ │ │ └── sha512.js │ │ ├── crypto.js │ │ └── client.js │ ├── css │ │ ├── reset.min.css │ │ └── login.css │ └── views │ │ └── chat.html ├── package.json ├── app.js └── server │ ├── manager.js │ └── server.js ├── .vscode └── launch.json ├── .gitignore └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | .nide 2 | -------------------------------------------------------------------------------- /login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/login.png -------------------------------------------------------------------------------- /chatform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/chatform.png -------------------------------------------------------------------------------- /src/client/img/channel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/img/channel.png -------------------------------------------------------------------------------- /src/client/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/img/favicon.ico -------------------------------------------------------------------------------- /src/client/img/unnamed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/img/unnamed.png -------------------------------------------------------------------------------- /src/client/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/client/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/client/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/client/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/client/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezzad/SecureChat/HEAD/src/client/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/client/js/crypto-js/enc-hex.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.enc.Hex; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/enc-utf8.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.enc.Utf8; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/enc-latin1.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.enc.Latin1; 17 | 18 | })); -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceFolder}/src\\app.js" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /src/client/js/crypto-js/pad-pkcs7.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.pad.Pkcs7; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/format-openssl.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.format.OpenSSL; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-md5.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./md5"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./md5", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacMD5; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-sha1.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./sha1", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacSHA1; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-sha256.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./sha256", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacSHA256; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-ripemd160.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./ripemd160"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./ripemd160", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacRIPEMD160; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-sha224.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./sha256"), require("./sha224"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./sha256", "./sha224", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacSHA224; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-sha3.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha3"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./x64-core", "./sha3", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacSHA3; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-sha512.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./x64-core", "./sha512", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacSHA512; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac-sha384.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./sha384"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./x64-core", "./sha512", "./sha384", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS.HmacSHA384; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution 2 | 3 | # Git Flow 4 | 5 | The crypto-js project uses [git flow](https://github.com/nvie/gitflow) to manage branches. 6 | Do your changes on the `develop` or even better on a `feature/*` branch. Don't do any changes on the `master` branch. 7 | 8 | # Pull request 9 | 10 | Target your pull request on `develop` branch. Other pull request won't be accepted. 11 | 12 | # How to build 13 | 14 | 1. Clone 15 | 16 | 2. Run 17 | 18 | ```sh 19 | npm install 20 | ``` 21 | 22 | 3. Run 23 | 24 | ```sh 25 | npm run build 26 | ``` 27 | 28 | 4. Check `build` folder -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "secure_chat", 3 | "version": "0.0.2", 4 | "description": "Realtime secure chat system", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "node", 11 | "secure", 12 | "chat", 13 | "system" 14 | ], 15 | "author": "Behzad Khosravifar ", 16 | "license": "GNU", 17 | "dependencies": { 18 | "@fortawesome/fontawesome-free": "^5.1.0", 19 | "crypto-js": "^3.1.9-1", 20 | "ejs": "^1.0.0", 21 | "express": "^4.16.3", 22 | "gravatar": "^1.0.6", 23 | "socket.io": "^2.1.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/client/js/crypto-js/pad-nopadding.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * A noop padding strategy. 18 | */ 19 | CryptoJS.pad.NoPadding = { 20 | pad: function () { 21 | }, 22 | 23 | unpad: function () { 24 | } 25 | }; 26 | 27 | 28 | return CryptoJS.pad.NoPadding; 29 | 30 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crypto-js", 3 | "version": "3.1.9", 4 | "description": "JavaScript library of crypto standards.", 5 | "license": "MIT", 6 | "homepage": "http://github.com/brix/crypto-js", 7 | "repository": { 8 | "type": "git", 9 | "url": "http://github.com/brix/crypto-js.git" 10 | }, 11 | "keywords": [ 12 | "security", 13 | "crypto", 14 | "Hash", 15 | "MD5", 16 | "SHA1", 17 | "SHA-1", 18 | "SHA256", 19 | "SHA-256", 20 | "RC4", 21 | "Rabbit", 22 | "AES", 23 | "DES", 24 | "PBKDF2", 25 | "HMAC", 26 | "OFB", 27 | "CFB", 28 | "CTR", 29 | "CBC", 30 | "Base64" 31 | ], 32 | "main": "index.js", 33 | "dependencies": {}, 34 | "ignore": [] 35 | } 36 | -------------------------------------------------------------------------------- /src/client/css/reset.min.css: -------------------------------------------------------------------------------- 1 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}table{border-collapse:collapse;border-spacing:0} -------------------------------------------------------------------------------- /src/client/js/crypto-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crypto-js", 3 | "version": "3.1.9", 4 | "description": "JavaScript library of crypto standards.", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Evan Vosberg", 8 | "url": "http://github.com/evanvosberg" 9 | }, 10 | "homepage": "http://github.com/brix/crypto-js", 11 | "repository": { 12 | "type": "git", 13 | "url": "http://github.com/brix/crypto-js.git" 14 | }, 15 | "keywords": [ 16 | "security", 17 | "crypto", 18 | "Hash", 19 | "MD5", 20 | "SHA1", 21 | "SHA-1", 22 | "SHA256", 23 | "SHA-256", 24 | "RC4", 25 | "Rabbit", 26 | "AES", 27 | "DES", 28 | "PBKDF2", 29 | "HMAC", 30 | "OFB", 31 | "CFB", 32 | "CTR", 33 | "CBC", 34 | "Base64" 35 | ], 36 | "main": "index.js", 37 | "dependencies": {} 38 | } 39 | -------------------------------------------------------------------------------- /src/client/js/crypto-js/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crypto-js", 3 | "version": "3.1.9", 4 | "description": "JavaScript library of crypto standards.", 5 | "license": "MIT", 6 | "homepage": "http://github.com/brix/crypto-js", 7 | "repository": { 8 | "type": "git", 9 | "url": "http://github.com/brix/crypto-js.git" 10 | }, 11 | "keywords": [ 12 | "security", 13 | "crypto", 14 | "Hash", 15 | "MD5", 16 | "SHA1", 17 | "SHA-1", 18 | "SHA256", 19 | "SHA-256", 20 | "RC4", 21 | "Rabbit", 22 | "AES", 23 | "DES", 24 | "PBKDF2", 25 | "HMAC", 26 | "OFB", 27 | "CFB", 28 | "CTR", 29 | "CBC", 30 | "Base64" 31 | ], 32 | "main": "index.js", 33 | "dependencies": {}, 34 | "ignore": [], 35 | "_release": "3.1.9", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "3.1.9", 39 | "commit": "c8ac779bb0f5b8c7947422e09e96c75d768b019e" 40 | }, 41 | "_source": "https://github.com/brix/crypto-js.git", 42 | "_target": "^3.1.9", 43 | "_originalSource": "crypto-js", 44 | "_direct": true 45 | } -------------------------------------------------------------------------------- /src/client/js/crypto-js/mode-ecb.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * Electronic Codebook block mode. 18 | */ 19 | CryptoJS.mode.ECB = (function () { 20 | var ECB = CryptoJS.lib.BlockCipherMode.extend(); 21 | 22 | ECB.Encryptor = ECB.extend({ 23 | processBlock: function (words, offset) { 24 | this._cipher.encryptBlock(words, offset); 25 | } 26 | }); 27 | 28 | ECB.Decryptor = ECB.extend({ 29 | processBlock: function (words, offset) { 30 | this._cipher.decryptBlock(words, offset); 31 | } 32 | }); 33 | 34 | return ECB; 35 | }()); 36 | 37 | 38 | return CryptoJS.mode.ECB; 39 | 40 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/pad-iso97971.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * ISO/IEC 9797-1 Padding Method 2. 18 | */ 19 | CryptoJS.pad.Iso97971 = { 20 | pad: function (data, blockSize) { 21 | // Add 0x80 byte 22 | data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1)); 23 | 24 | // Zero pad the rest 25 | CryptoJS.pad.ZeroPadding.pad(data, blockSize); 26 | }, 27 | 28 | unpad: function (data) { 29 | // Remove zero padding 30 | CryptoJS.pad.ZeroPadding.unpad(data); 31 | 32 | // Remove one more byte -- the 0x80 byte 33 | data.sigBytes--; 34 | } 35 | }; 36 | 37 | 38 | return CryptoJS.pad.Iso97971; 39 | 40 | })); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | -------------------------------------------------------------------------------- /src/client/js/crypto-js/pad-zeropadding.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * Zero padding strategy. 18 | */ 19 | CryptoJS.pad.ZeroPadding = { 20 | pad: function (data, blockSize) { 21 | // Shortcut 22 | var blockSizeBytes = blockSize * 4; 23 | 24 | // Pad 25 | data.clamp(); 26 | data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); 27 | }, 28 | 29 | unpad: function (data) { 30 | // Shortcut 31 | var dataWords = data.words; 32 | 33 | // Unpad 34 | var i = data.sigBytes - 1; 35 | while (!((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { 36 | i--; 37 | } 38 | data.sigBytes = i + 1; 39 | } 40 | }; 41 | 42 | 43 | return CryptoJS.pad.ZeroPadding; 44 | 45 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/LICENSE: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | [The MIT License (MIT)](http://opensource.org/licenses/MIT) 4 | 5 | Copyright (c) 2009-2013 Jeff Mott 6 | Copyright (c) 2013-2016 Evan Vosberg 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /src/client/js/crypto-js/pad-iso10126.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * ISO 10126 padding strategy. 18 | */ 19 | CryptoJS.pad.Iso10126 = { 20 | pad: function (data, blockSize) { 21 | // Shortcut 22 | var blockSizeBytes = blockSize * 4; 23 | 24 | // Count padding bytes 25 | var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; 26 | 27 | // Pad 28 | data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)). 29 | concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1)); 30 | }, 31 | 32 | unpad: function (data) { 33 | // Get number of padding bytes from last byte 34 | var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; 35 | 36 | // Remove padding 37 | data.sigBytes -= nPaddingBytes; 38 | } 39 | }; 40 | 41 | 42 | return CryptoJS.pad.Iso10126; 43 | 44 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/pad-ansix923.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * ANSI X.923 padding strategy. 18 | */ 19 | CryptoJS.pad.AnsiX923 = { 20 | pad: function (data, blockSize) { 21 | // Shortcuts 22 | var dataSigBytes = data.sigBytes; 23 | var blockSizeBytes = blockSize * 4; 24 | 25 | // Count padding bytes 26 | var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes; 27 | 28 | // Compute last byte position 29 | var lastBytePos = dataSigBytes + nPaddingBytes - 1; 30 | 31 | // Pad 32 | data.clamp(); 33 | data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); 34 | data.sigBytes += nPaddingBytes; 35 | }, 36 | 37 | unpad: function (data) { 38 | // Get number of padding bytes from last byte 39 | var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; 40 | 41 | // Remove padding 42 | data.sigBytes -= nPaddingBytes; 43 | } 44 | }; 45 | 46 | 47 | return CryptoJS.pad.Ansix923; 48 | 49 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/mode-ofb.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * Output Feedback block mode. 18 | */ 19 | CryptoJS.mode.OFB = (function () { 20 | var OFB = CryptoJS.lib.BlockCipherMode.extend(); 21 | 22 | var Encryptor = OFB.Encryptor = OFB.extend({ 23 | processBlock: function (words, offset) { 24 | // Shortcuts 25 | var cipher = this._cipher 26 | var blockSize = cipher.blockSize; 27 | var iv = this._iv; 28 | var keystream = this._keystream; 29 | 30 | // Generate keystream 31 | if (iv) { 32 | keystream = this._keystream = iv.slice(0); 33 | 34 | // Remove IV for subsequent blocks 35 | this._iv = undefined; 36 | } 37 | cipher.encryptBlock(keystream, 0); 38 | 39 | // Encrypt 40 | for (var i = 0; i < blockSize; i++) { 41 | words[offset + i] ^= keystream[i]; 42 | } 43 | } 44 | }); 45 | 46 | OFB.Decryptor = Encryptor; 47 | 48 | return OFB; 49 | }()); 50 | 51 | 52 | return CryptoJS.mode.OFB; 53 | 54 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/index.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./x64-core"), require("./lib-typedarrays"), require("./enc-utf16"), require("./enc-base64"), require("./md5"), require("./sha1"), require("./sha256"), require("./sha224"), require("./sha512"), require("./sha384"), require("./sha3"), require("./ripemd160"), require("./hmac"), require("./pbkdf2"), require("./evpkdf"), require("./cipher-core"), require("./mode-cfb"), require("./mode-ctr"), require("./mode-ctr-gladman"), require("./mode-ofb"), require("./mode-ecb"), require("./pad-ansix923"), require("./pad-iso10126"), require("./pad-iso97971"), require("./pad-zeropadding"), require("./pad-nopadding"), require("./format-hex"), require("./aes"), require("./tripledes"), require("./rc4"), require("./rabbit"), require("./rabbit-legacy")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./x64-core", "./lib-typedarrays", "./enc-utf16", "./enc-base64", "./md5", "./sha1", "./sha256", "./sha224", "./sha512", "./sha384", "./sha3", "./ripemd160", "./hmac", "./pbkdf2", "./evpkdf", "./cipher-core", "./mode-cfb", "./mode-ctr", "./mode-ctr-gladman", "./mode-ofb", "./mode-ecb", "./pad-ansix923", "./pad-iso10126", "./pad-iso97971", "./pad-zeropadding", "./pad-nopadding", "./format-hex", "./aes", "./tripledes", "./rc4", "./rabbit", "./rabbit-legacy"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | root.CryptoJS = factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | return CryptoJS; 17 | 18 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/mode-ctr.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * Counter block mode. 18 | */ 19 | CryptoJS.mode.CTR = (function () { 20 | var CTR = CryptoJS.lib.BlockCipherMode.extend(); 21 | 22 | var Encryptor = CTR.Encryptor = CTR.extend({ 23 | processBlock: function (words, offset) { 24 | // Shortcuts 25 | var cipher = this._cipher 26 | var blockSize = cipher.blockSize; 27 | var iv = this._iv; 28 | var counter = this._counter; 29 | 30 | // Generate keystream 31 | if (iv) { 32 | counter = this._counter = iv.slice(0); 33 | 34 | // Remove IV for subsequent blocks 35 | this._iv = undefined; 36 | } 37 | var keystream = counter.slice(0); 38 | cipher.encryptBlock(keystream, 0); 39 | 40 | // Increment counter 41 | counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0 42 | 43 | // Encrypt 44 | for (var i = 0; i < blockSize; i++) { 45 | words[offset + i] ^= keystream[i]; 46 | } 47 | } 48 | }); 49 | 50 | CTR.Decryptor = Encryptor; 51 | 52 | return CTR; 53 | }()); 54 | 55 | 56 | return CryptoJS.mode.CTR; 57 | 58 | })); -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | // This is the main file of our chat app. It initializes a new 2 | // express.js instance, requires the config and routes files 3 | // and listens on a port. Start the application by running 4 | // 'node app.js' in your terminal 5 | 6 | var express = require('express'); 7 | var path = require("path"); 8 | var app = express(); 9 | var port = 80; 10 | 11 | // Initialize a new socket.io object. It is bound to 12 | // the express app, which allows them to coexist. 13 | var io = require('socket.io').listen(app.listen(port)); 14 | 15 | 16 | // ------------------- Config static directories and files --------------- 17 | // 18 | // Set .html as the default template extension 19 | app.set('view engine', 'html'); 20 | 21 | // Initialize the ejs template engine 22 | app.engine('html', require('ejs').renderFile); 23 | 24 | // Tell express where it can find the templates 25 | app.set('views', path.join(__dirname, 'client/views')); 26 | 27 | // Make the files in the public folder available to the world 28 | app.use(express.static(path.join(__dirname, 'client'))); 29 | // ======================================================================= 30 | // 31 | 32 | 33 | // --------------------------- Router Config ----------------------------- 34 | // 35 | // sets up event listeners for the two main URL 36 | // endpoints of the application - / 37 | app.get('/', function (req, res) { 38 | // Render views/chat.html 39 | res.render('chat'); 40 | }); 41 | // ======================================================================= 42 | // 43 | 44 | // Require the configuration and the routes files, and pass 45 | // the app and io as arguments to the returned functions. 46 | require('./server/server')(app, io); 47 | 48 | console.log('Your application is running on http://localhost:' + port); -------------------------------------------------------------------------------- /src/client/js/crypto-js/format-hex.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function (undefined) { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var CipherParams = C_lib.CipherParams; 21 | var C_enc = C.enc; 22 | var Hex = C_enc.Hex; 23 | var C_format = C.format; 24 | 25 | var HexFormatter = C_format.Hex = { 26 | /** 27 | * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. 28 | * 29 | * @param {CipherParams} cipherParams The cipher params object. 30 | * 31 | * @return {string} The hexadecimally encoded string. 32 | * 33 | * @static 34 | * 35 | * @example 36 | * 37 | * var hexString = CryptoJS.format.Hex.stringify(cipherParams); 38 | */ 39 | stringify: function (cipherParams) { 40 | return cipherParams.ciphertext.toString(Hex); 41 | }, 42 | 43 | /** 44 | * Converts a hexadecimally encoded ciphertext string to a cipher params object. 45 | * 46 | * @param {string} input The hexadecimally encoded string. 47 | * 48 | * @return {CipherParams} The cipher params object. 49 | * 50 | * @static 51 | * 52 | * @example 53 | * 54 | * var cipherParams = CryptoJS.format.Hex.parse(hexString); 55 | */ 56 | parse: function (input) { 57 | var ciphertext = Hex.parse(input); 58 | return CipherParams.create({ ciphertext: ciphertext }); 59 | } 60 | }; 61 | }()); 62 | 63 | 64 | return CryptoJS.format.Hex; 65 | 66 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/sha224.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./sha256")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./sha256"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var WordArray = C_lib.WordArray; 21 | var C_algo = C.algo; 22 | var SHA256 = C_algo.SHA256; 23 | 24 | /** 25 | * SHA-224 hash algorithm. 26 | */ 27 | var SHA224 = C_algo.SHA224 = SHA256.extend({ 28 | _doReset: function () { 29 | this._hash = new WordArray.init([ 30 | 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 31 | 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 32 | ]); 33 | }, 34 | 35 | _doFinalize: function () { 36 | var hash = SHA256._doFinalize.call(this); 37 | 38 | hash.sigBytes -= 4; 39 | 40 | return hash; 41 | } 42 | }); 43 | 44 | /** 45 | * Shortcut function to the hasher's object interface. 46 | * 47 | * @param {WordArray|string} message The message to hash. 48 | * 49 | * @return {WordArray} The hash. 50 | * 51 | * @static 52 | * 53 | * @example 54 | * 55 | * var hash = CryptoJS.SHA224('message'); 56 | * var hash = CryptoJS.SHA224(wordArray); 57 | */ 58 | C.SHA224 = SHA256._createHelper(SHA224); 59 | 60 | /** 61 | * Shortcut function to the HMAC's object interface. 62 | * 63 | * @param {WordArray|string} message The message to hash. 64 | * @param {WordArray|string} key The secret key. 65 | * 66 | * @return {WordArray} The HMAC. 67 | * 68 | * @static 69 | * 70 | * @example 71 | * 72 | * var hmac = CryptoJS.HmacSHA224(message, key); 73 | */ 74 | C.HmacSHA224 = SHA256._createHmacHelper(SHA224); 75 | }()); 76 | 77 | 78 | return CryptoJS.SHA224; 79 | 80 | })); -------------------------------------------------------------------------------- /src/client/js/crypto.js: -------------------------------------------------------------------------------- 1 | /* Cryptology used Forge.js lib to encrypt/decrypt by symmetric or asymmetric algorithms */ 2 | "use strict"; 3 | 4 | // Create the encryption object for asymmetric RSA algorithm. 5 | var rsa = new JSEncrypt(); 6 | 7 | // define the characters to pick from 8 | var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz*&-%/!?*+=()"; 9 | 10 | // create a key for symmetric encryption 11 | // pass in the desired length of your key 12 | function generateKey(keyLength) { 13 | var randomstring = ''; 14 | 15 | for (var i = 0; i < keyLength; i++) { 16 | var rnum = Math.floor(Math.random() * chars.length); 17 | randomstring += chars.substring(rnum, rnum + 1); 18 | } 19 | return randomstring; 20 | } 21 | 22 | // create the pair public and private key for asymmetric encryption 23 | var generateKeyPair = function () { 24 | var crypt = new JSEncrypt({ default_key_size: 1024 }); 25 | crypt.getKey(); 26 | 27 | return { 28 | privateKey: crypt.getPrivateKey(), 29 | publicKey: crypt.getPublicKey() 30 | } 31 | }; 32 | 33 | // hasing text by sha-512 algorithm 34 | String.prototype.getHash = function () { 35 | return CryptoJS.SHA512(this).toString(); 36 | } 37 | 38 | // symmetric 3DES encryption 39 | String.prototype.symEncrypt = function (pass) { 40 | return CryptoJS.TripleDES.encrypt(this, pass).toString(); 41 | } 42 | 43 | // symmetric 3DES decryption 44 | String.prototype.symDecrypt = function (pass) { 45 | var bytes = CryptoJS.TripleDES.decrypt(this, pass); 46 | return bytes.toString(CryptoJS.enc.Utf8); 47 | } 48 | 49 | // asymmetric RSA encryption 50 | String.prototype.asymEncrypt = function (publicKey) { 51 | rsa.setPublicKey(publicKey); 52 | return rsa.encrypt(this); 53 | } 54 | 55 | // asymmetric RSA decryption 56 | String.prototype.asymDecrypt = function (privateKey) { 57 | rsa.setPrivateKey(privateKey); // Set the private. 58 | return rsa.decrypt(this); 59 | } 60 | 61 | function getCipherKeys() { 62 | var keys = localStorage.cipherKeys; // read keys json 63 | if (keys == null) { 64 | keys = generateKeyPair(); 65 | 66 | // store keys as json in localStorage 67 | localStorage.cipherKeys = JSON.stringify(keys); 68 | return keys; 69 | } 70 | 71 | return JSON.parse(keys); 72 | } -------------------------------------------------------------------------------- /src/client/js/crypto-js/mode-cfb.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** 17 | * Cipher Feedback block mode. 18 | */ 19 | CryptoJS.mode.CFB = (function () { 20 | var CFB = CryptoJS.lib.BlockCipherMode.extend(); 21 | 22 | CFB.Encryptor = CFB.extend({ 23 | processBlock: function (words, offset) { 24 | // Shortcuts 25 | var cipher = this._cipher; 26 | var blockSize = cipher.blockSize; 27 | 28 | generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); 29 | 30 | // Remember this block to use with next block 31 | this._prevBlock = words.slice(offset, offset + blockSize); 32 | } 33 | }); 34 | 35 | CFB.Decryptor = CFB.extend({ 36 | processBlock: function (words, offset) { 37 | // Shortcuts 38 | var cipher = this._cipher; 39 | var blockSize = cipher.blockSize; 40 | 41 | // Remember this block to use with next block 42 | var thisBlock = words.slice(offset, offset + blockSize); 43 | 44 | generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); 45 | 46 | // This block becomes the previous block 47 | this._prevBlock = thisBlock; 48 | } 49 | }); 50 | 51 | function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { 52 | // Shortcut 53 | var iv = this._iv; 54 | 55 | // Generate keystream 56 | if (iv) { 57 | var keystream = iv.slice(0); 58 | 59 | // Remove IV for subsequent blocks 60 | this._iv = undefined; 61 | } else { 62 | var keystream = this._prevBlock; 63 | } 64 | cipher.encryptBlock(keystream, 0); 65 | 66 | // Encrypt 67 | for (var i = 0; i < blockSize; i++) { 68 | words[offset + i] ^= keystream[i]; 69 | } 70 | } 71 | 72 | return CFB; 73 | }()); 74 | 75 | 76 | return CryptoJS.mode.CFB; 77 | 78 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/lib-typedarrays.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Check if typed arrays are supported 18 | if (typeof ArrayBuffer != 'function') { 19 | return; 20 | } 21 | 22 | // Shortcuts 23 | var C = CryptoJS; 24 | var C_lib = C.lib; 25 | var WordArray = C_lib.WordArray; 26 | 27 | // Reference original init 28 | var superInit = WordArray.init; 29 | 30 | // Augment WordArray.init to handle typed arrays 31 | var subInit = WordArray.init = function (typedArray) { 32 | // Convert buffers to uint8 33 | if (typedArray instanceof ArrayBuffer) { 34 | typedArray = new Uint8Array(typedArray); 35 | } 36 | 37 | // Convert other array views to uint8 38 | if ( 39 | typedArray instanceof Int8Array || 40 | (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) || 41 | typedArray instanceof Int16Array || 42 | typedArray instanceof Uint16Array || 43 | typedArray instanceof Int32Array || 44 | typedArray instanceof Uint32Array || 45 | typedArray instanceof Float32Array || 46 | typedArray instanceof Float64Array 47 | ) { 48 | typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); 49 | } 50 | 51 | // Handle Uint8Array 52 | if (typedArray instanceof Uint8Array) { 53 | // Shortcut 54 | var typedArrayByteLength = typedArray.byteLength; 55 | 56 | // Extract bytes 57 | var words = []; 58 | for (var i = 0; i < typedArrayByteLength; i++) { 59 | words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); 60 | } 61 | 62 | // Initialize this word array 63 | superInit.call(this, words, typedArrayByteLength); 64 | } else { 65 | // Else call normal init 66 | superInit.apply(this, arguments); 67 | } 68 | }; 69 | 70 | subInit.prototype = WordArray; 71 | }()); 72 | 73 | 74 | return CryptoJS.lib.WordArray; 75 | 76 | })); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Secure Chat 2 | 3 | Client side secure chat, based on [node.js](https://nodejs.org), [socket.io](https://socket.io/) and [asymmetric encryption](https://en.wikipedia.org/wiki/Public-key_cryptography) without open storage on server side. 4 | 5 | ![loginform](https://raw.githubusercontent.com/bezzad/SecureChat/master/login.png) 6 | 7 | ![chatform](https://raw.githubusercontent.com/bezzad/SecureChat/master/chatform.png) 8 | ----------------------- 9 | 10 | ## How to use 11 | 12 | * install [node.js](https://nodejs.org) 13 | * clone this repository 14 | * go to `src\` folder 15 | * run below commands in your command line: 16 | + $ npm install 17 | + $ node app.js 18 | * open your browser and enter your server url (http://localhost) 19 | 20 | ----------------------- 21 | 22 | ## References that have been used 23 | 24 | * [**Node.js®**](https://nodejs.org) is a [JavaScript](http://en.wikipedia.org/wiki/JavaScript) runtime built on [Chrome's V8 JavaScript engine](https://developers.google.com/v8/). 25 | 26 | * [**Express.js**](https://expressjs.com/) is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. 27 | 28 | * [**Socket.io**](https://socket.io) enables real-time bidirectional event-based communication. It works on every platform, browser or device, focusing equally on reliability and speed. 29 | 30 | * [**jQuery**](https://jquery.com/) is a fast, small, and feature-rich JavaScript library. 31 | 32 | * [**Crypto.js**](https://github.com/brix/crypto-js) is a JavaScript library of crypto standards. Hasing and AES algorithms. 33 | 34 | * [**JSEncrypt**](https://github.com/travist/jsencrypt) is a Javascript library to perform OpenSSL RSA Encryption, Decryption, and Key Generation. 35 | 36 | * [**Local Storage**](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) is analogous to [sessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/sessionStorage), with the same same-origin rules applied, but it is persistent across sessions. `localStorage` was introduced in Firefox 3.5. 37 | 38 | * [**Gravatar**](https://github.com/emerleite/node-gravatar) a library to generate Gravatar URLs in Node.js Based on gravatar specs - `http://en.gravatar.com/site/implement/hash/` and `http://en.gravatar.com/site/implement/images/`. 39 | 40 | * [**Tchat card**](https://bootsnipp.com/snippets/0e3Ma) a Bootstrap chat theme snippet by [evarevirus](https://bootsnipp.com/evarevirus) 41 | 42 | * [**Login form**](https://colorlib.com/wp/template/login-form-v3/) a cool login form template to be used for any website and app. Made by Colorlib. -------------------------------------------------------------------------------- /src/client/js/crypto-js/sha384.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./x64-core", "./sha512"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_x64 = C.x64; 20 | var X64Word = C_x64.Word; 21 | var X64WordArray = C_x64.WordArray; 22 | var C_algo = C.algo; 23 | var SHA512 = C_algo.SHA512; 24 | 25 | /** 26 | * SHA-384 hash algorithm. 27 | */ 28 | var SHA384 = C_algo.SHA384 = SHA512.extend({ 29 | _doReset: function () { 30 | this._hash = new X64WordArray.init([ 31 | new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507), 32 | new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939), 33 | new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511), 34 | new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4) 35 | ]); 36 | }, 37 | 38 | _doFinalize: function () { 39 | var hash = SHA512._doFinalize.call(this); 40 | 41 | hash.sigBytes -= 16; 42 | 43 | return hash; 44 | } 45 | }); 46 | 47 | /** 48 | * Shortcut function to the hasher's object interface. 49 | * 50 | * @param {WordArray|string} message The message to hash. 51 | * 52 | * @return {WordArray} The hash. 53 | * 54 | * @static 55 | * 56 | * @example 57 | * 58 | * var hash = CryptoJS.SHA384('message'); 59 | * var hash = CryptoJS.SHA384(wordArray); 60 | */ 61 | C.SHA384 = SHA512._createHelper(SHA384); 62 | 63 | /** 64 | * Shortcut function to the HMAC's object interface. 65 | * 66 | * @param {WordArray|string} message The message to hash. 67 | * @param {WordArray|string} key The secret key. 68 | * 69 | * @return {WordArray} The HMAC. 70 | * 71 | * @static 72 | * 73 | * @example 74 | * 75 | * var hmac = CryptoJS.HmacSHA384(message, key); 76 | */ 77 | C.HmacSHA384 = SHA512._createHmacHelper(SHA384); 78 | }()); 79 | 80 | 81 | return CryptoJS.SHA384; 82 | 83 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/mode-ctr-gladman.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** @preserve 17 | * Counter block mode compatible with Dr Brian Gladman fileenc.c 18 | * derived from CryptoJS.mode.CTR 19 | * Jan Hruby jhruby.web@gmail.com 20 | */ 21 | CryptoJS.mode.CTRGladman = (function () { 22 | var CTRGladman = CryptoJS.lib.BlockCipherMode.extend(); 23 | 24 | function incWord(word) 25 | { 26 | if (((word >> 24) & 0xff) === 0xff) { //overflow 27 | var b1 = (word >> 16)&0xff; 28 | var b2 = (word >> 8)&0xff; 29 | var b3 = word & 0xff; 30 | 31 | if (b1 === 0xff) // overflow b1 32 | { 33 | b1 = 0; 34 | if (b2 === 0xff) 35 | { 36 | b2 = 0; 37 | if (b3 === 0xff) 38 | { 39 | b3 = 0; 40 | } 41 | else 42 | { 43 | ++b3; 44 | } 45 | } 46 | else 47 | { 48 | ++b2; 49 | } 50 | } 51 | else 52 | { 53 | ++b1; 54 | } 55 | 56 | word = 0; 57 | word += (b1 << 16); 58 | word += (b2 << 8); 59 | word += b3; 60 | } 61 | else 62 | { 63 | word += (0x01 << 24); 64 | } 65 | return word; 66 | } 67 | 68 | function incCounter(counter) 69 | { 70 | if ((counter[0] = incWord(counter[0])) === 0) 71 | { 72 | // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 73 | counter[1] = incWord(counter[1]); 74 | } 75 | return counter; 76 | } 77 | 78 | var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({ 79 | processBlock: function (words, offset) { 80 | // Shortcuts 81 | var cipher = this._cipher 82 | var blockSize = cipher.blockSize; 83 | var iv = this._iv; 84 | var counter = this._counter; 85 | 86 | // Generate keystream 87 | if (iv) { 88 | counter = this._counter = iv.slice(0); 89 | 90 | // Remove IV for subsequent blocks 91 | this._iv = undefined; 92 | } 93 | 94 | incCounter(counter); 95 | 96 | var keystream = counter.slice(0); 97 | cipher.encryptBlock(keystream, 0); 98 | 99 | // Encrypt 100 | for (var i = 0; i < blockSize; i++) { 101 | words[offset + i] ^= keystream[i]; 102 | } 103 | } 104 | }); 105 | 106 | CTRGladman.Decryptor = Encryptor; 107 | 108 | return CTRGladman; 109 | }()); 110 | 111 | 112 | 113 | 114 | return CryptoJS.mode.CTRGladman; 115 | 116 | })); -------------------------------------------------------------------------------- /src/server/manager.js: -------------------------------------------------------------------------------- 1 | var e = {} 2 | module.exports = e; 3 | 4 | e.clients = {}; // property: id, value: { socketid, id, username, email, pubKey, password, avatar, status } 5 | e.messageTypes = ["ack", "request", "message", "symmetricKey"]; 6 | e.messages = {}; // property: channelName, value { from, to, date, type } 7 | e.channels = {}; // property: channelName, value: { name, p2p, adminUserId, users[] } 8 | 9 | // generate 16 char length GUID 10 | e.generateGuid = function () { 11 | return Math.random().toString(36).substring(2, 10) + 12 | Math.random().toString(36).substring(2, 10); 13 | } 14 | 15 | e.getHashCode = String.prototype.hashCode = function () { 16 | var hash = 0, i, chr; 17 | if (this.length == 0) return hash; 18 | for (i = 0; i < this.length; i++) { 19 | chr = this.charCodeAt(i); 20 | hash = ((hash << 5) - hash) + chr; 21 | hash |= 0; // Convert to 32bit integer 22 | } 23 | return hash.toString(32); // to base 32 24 | } 25 | 26 | e.getUsers = function () { 27 | var users = {}; 28 | for (prop in e.clients) { 29 | var u = e.clients[prop]; 30 | users[prop] = { 31 | id: u.id, 32 | email: u.email, 33 | username: u.username, 34 | avatar: u.avatar, 35 | status: u.status 36 | }; 37 | } 38 | return users; 39 | } 40 | 41 | e.getUserChannels = function (userId, byP2p = false) { 42 | var userChannels = {}; 43 | if (userId) { 44 | for (prop in e.channels) { 45 | var r = e.channels[prop]; 46 | if (r.users.indexOf(userId) !== -1) { 47 | if ((byP2p === false && r.p2p === false) || byP2p === true) 48 | userChannels[prop] = r; 49 | } 50 | } 51 | } 52 | return userChannels; 53 | } 54 | 55 | e.getChannels = function () { 56 | var lstChannels = {}; 57 | for (prop in e.channels) { 58 | var r = e.channels[prop]; 59 | if (r.p2p === false) { 60 | lstChannels[prop] = r; 61 | } 62 | } 63 | return lstChannels; 64 | } 65 | 66 | e.findUser = function (socketid) { 67 | for (prop in e.clients) { 68 | var u = e.clients[prop]; 69 | if (u.socketid === socketid) { 70 | return u; 71 | } 72 | } 73 | return null; // user not found 74 | } 75 | 76 | e.generateChannelName = function (uid0, uid1) { 77 | var ids = [uid0, uid1].sort(); 78 | return ids[0] + "_" + ids[1]; // unique name for this users private 79 | } 80 | 81 | e.getAdminFromChannelName = function (channelName, userid) { 82 | var admin = null; 83 | 84 | // find channel to send client request 85 | var channel = e.channels[channelName]; 86 | 87 | if (channel == null) { // requested to new p2p channel 88 | var halfIndex = channelName.indexOf("_"); 89 | if (halfIndex < 1) 90 | return null; // p2p channel name incorrect 91 | 92 | var u0 = channelName.substring(0, halfIndex); 93 | var u1 = channelName.substring(halfIndex + 1); 94 | 95 | admin = (u0 === userid) 96 | ? e.clients[u1] // u1 is admin id 97 | : admin = e.clients[u0]; // u0 is admin id 98 | } 99 | else 100 | admin = e.clients[channel.adminUserId]; 101 | 102 | return admin; 103 | } -------------------------------------------------------------------------------- /src/client/js/crypto-js/rc4.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var StreamCipher = C_lib.StreamCipher; 21 | var C_algo = C.algo; 22 | 23 | /** 24 | * RC4 stream cipher algorithm. 25 | */ 26 | var RC4 = C_algo.RC4 = StreamCipher.extend({ 27 | _doReset: function () { 28 | // Shortcuts 29 | var key = this._key; 30 | var keyWords = key.words; 31 | var keySigBytes = key.sigBytes; 32 | 33 | // Init sbox 34 | var S = this._S = []; 35 | for (var i = 0; i < 256; i++) { 36 | S[i] = i; 37 | } 38 | 39 | // Key setup 40 | for (var i = 0, j = 0; i < 256; i++) { 41 | var keyByteIndex = i % keySigBytes; 42 | var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; 43 | 44 | j = (j + S[i] + keyByte) % 256; 45 | 46 | // Swap 47 | var t = S[i]; 48 | S[i] = S[j]; 49 | S[j] = t; 50 | } 51 | 52 | // Counters 53 | this._i = this._j = 0; 54 | }, 55 | 56 | _doProcessBlock: function (M, offset) { 57 | M[offset] ^= generateKeystreamWord.call(this); 58 | }, 59 | 60 | keySize: 256/32, 61 | 62 | ivSize: 0 63 | }); 64 | 65 | function generateKeystreamWord() { 66 | // Shortcuts 67 | var S = this._S; 68 | var i = this._i; 69 | var j = this._j; 70 | 71 | // Generate keystream word 72 | var keystreamWord = 0; 73 | for (var n = 0; n < 4; n++) { 74 | i = (i + 1) % 256; 75 | j = (j + S[i]) % 256; 76 | 77 | // Swap 78 | var t = S[i]; 79 | S[i] = S[j]; 80 | S[j] = t; 81 | 82 | keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); 83 | } 84 | 85 | // Update counters 86 | this._i = i; 87 | this._j = j; 88 | 89 | return keystreamWord; 90 | } 91 | 92 | /** 93 | * Shortcut functions to the cipher's object interface. 94 | * 95 | * @example 96 | * 97 | * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); 98 | * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); 99 | */ 100 | C.RC4 = StreamCipher._createHelper(RC4); 101 | 102 | /** 103 | * Modified RC4 stream cipher algorithm. 104 | */ 105 | var RC4Drop = C_algo.RC4Drop = RC4.extend({ 106 | /** 107 | * Configuration options. 108 | * 109 | * @property {number} drop The number of keystream words to drop. Default 192 110 | */ 111 | cfg: RC4.cfg.extend({ 112 | drop: 192 113 | }), 114 | 115 | _doReset: function () { 116 | RC4._doReset.call(this); 117 | 118 | // Drop 119 | for (var i = this.cfg.drop; i > 0; i--) { 120 | generateKeystreamWord.call(this); 121 | } 122 | } 123 | }); 124 | 125 | /** 126 | * Shortcut functions to the cipher's object interface. 127 | * 128 | * @example 129 | * 130 | * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); 131 | * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); 132 | */ 133 | C.RC4Drop = StreamCipher._createHelper(RC4Drop); 134 | }()); 135 | 136 | 137 | return CryptoJS.RC4; 138 | 139 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/evpkdf.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./sha1", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var Base = C_lib.Base; 21 | var WordArray = C_lib.WordArray; 22 | var C_algo = C.algo; 23 | var MD5 = C_algo.MD5; 24 | 25 | /** 26 | * This key derivation function is meant to conform with EVP_BytesToKey. 27 | * www.openssl.org/docs/crypto/EVP_BytesToKey.html 28 | */ 29 | var EvpKDF = C_algo.EvpKDF = Base.extend({ 30 | /** 31 | * Configuration options. 32 | * 33 | * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) 34 | * @property {Hasher} hasher The hash algorithm to use. Default: MD5 35 | * @property {number} iterations The number of iterations to perform. Default: 1 36 | */ 37 | cfg: Base.extend({ 38 | keySize: 128/32, 39 | hasher: MD5, 40 | iterations: 1 41 | }), 42 | 43 | /** 44 | * Initializes a newly created key derivation function. 45 | * 46 | * @param {Object} cfg (Optional) The configuration options to use for the derivation. 47 | * 48 | * @example 49 | * 50 | * var kdf = CryptoJS.algo.EvpKDF.create(); 51 | * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); 52 | * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); 53 | */ 54 | init: function (cfg) { 55 | this.cfg = this.cfg.extend(cfg); 56 | }, 57 | 58 | /** 59 | * Derives a key from a password. 60 | * 61 | * @param {WordArray|string} password The password. 62 | * @param {WordArray|string} salt A salt. 63 | * 64 | * @return {WordArray} The derived key. 65 | * 66 | * @example 67 | * 68 | * var key = kdf.compute(password, salt); 69 | */ 70 | compute: function (password, salt) { 71 | // Shortcut 72 | var cfg = this.cfg; 73 | 74 | // Init hasher 75 | var hasher = cfg.hasher.create(); 76 | 77 | // Initial values 78 | var derivedKey = WordArray.create(); 79 | 80 | // Shortcuts 81 | var derivedKeyWords = derivedKey.words; 82 | var keySize = cfg.keySize; 83 | var iterations = cfg.iterations; 84 | 85 | // Generate key 86 | while (derivedKeyWords.length < keySize) { 87 | if (block) { 88 | hasher.update(block); 89 | } 90 | var block = hasher.update(password).finalize(salt); 91 | hasher.reset(); 92 | 93 | // Iterations 94 | for (var i = 1; i < iterations; i++) { 95 | block = hasher.finalize(block); 96 | hasher.reset(); 97 | } 98 | 99 | derivedKey.concat(block); 100 | } 101 | derivedKey.sigBytes = keySize * 4; 102 | 103 | return derivedKey; 104 | } 105 | }); 106 | 107 | /** 108 | * Derives a key from a password. 109 | * 110 | * @param {WordArray|string} password The password. 111 | * @param {WordArray|string} salt A salt. 112 | * @param {Object} cfg (Optional) The configuration options to use for this computation. 113 | * 114 | * @return {WordArray} The derived key. 115 | * 116 | * @static 117 | * 118 | * @example 119 | * 120 | * var key = CryptoJS.EvpKDF(password, salt); 121 | * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); 122 | * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); 123 | */ 124 | C.EvpKDF = function (password, salt, cfg) { 125 | return EvpKDF.create(cfg).compute(password, salt); 126 | }; 127 | }()); 128 | 129 | 130 | return CryptoJS.EvpKDF; 131 | 132 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/README.md: -------------------------------------------------------------------------------- 1 | # crypto-js 2 | 3 | JavaScript library of crypto standards. 4 | 5 | ## Node.js (Install) 6 | 7 | Requirements: 8 | 9 | - Node.js 10 | - npm (Node.js package manager) 11 | 12 | ```bash 13 | npm install crypto-js 14 | ``` 15 | 16 | ### Usage 17 | 18 | Modular include: 19 | 20 | ```javascript 21 | var AES = require("crypto-js/aes"); 22 | var SHA256 = require("crypto-js/sha256"); 23 | ... 24 | console.log(SHA256("Message")); 25 | ``` 26 | 27 | Including all libraries, for access to extra methods: 28 | 29 | ```javascript 30 | var CryptoJS = require("crypto-js"); 31 | console.log(CryptoJS.HmacSHA1("Message", "Key")); 32 | ``` 33 | 34 | ## Client (browser) 35 | 36 | Requirements: 37 | 38 | - Node.js 39 | - Bower (package manager for frontend) 40 | 41 | ```bash 42 | bower install crypto-js 43 | ``` 44 | 45 | ### Usage 46 | 47 | Modular include: 48 | 49 | ```javascript 50 | require.config({ 51 | packages: [ 52 | { 53 | name: 'crypto-js', 54 | location: 'path-to/bower_components/crypto-js', 55 | main: 'index' 56 | } 57 | ] 58 | }); 59 | 60 | require(["crypto-js/aes", "crypto-js/sha256"], function (AES, SHA256) { 61 | console.log(SHA256("Message")); 62 | }); 63 | ``` 64 | 65 | Including all libraries, for access to extra methods: 66 | 67 | ```javascript 68 | // Above-mentioned will work or use this simple form 69 | require.config({ 70 | paths: { 71 | 'crypto-js': 'path-to/bower_components/crypto-js/crypto-js' 72 | } 73 | }); 74 | 75 | require(["crypto-js"], function (CryptoJS) { 76 | console.log(CryptoJS.HmacSHA1("Message", "Key")); 77 | }); 78 | ``` 79 | 80 | ### Usage without RequireJS 81 | 82 | ```html 83 | 84 | 88 | ``` 89 | 90 | ## API 91 | 92 | See: https://code.google.com/p/crypto-js 93 | 94 | ### AES Encryption 95 | 96 | #### Plain text encryption 97 | 98 | ```javascript 99 | var CryptoJS = require("crypto-js"); 100 | 101 | // Encrypt 102 | var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123'); 103 | 104 | // Decrypt 105 | var bytes = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123'); 106 | var plaintext = bytes.toString(CryptoJS.enc.Utf8); 107 | 108 | console.log(plaintext); 109 | ``` 110 | 111 | #### Object encryption 112 | 113 | ```javascript 114 | var CryptoJS = require("crypto-js"); 115 | 116 | var data = [{id: 1}, {id: 2}] 117 | 118 | // Encrypt 119 | var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123'); 120 | 121 | // Decrypt 122 | var bytes = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123'); 123 | var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); 124 | 125 | console.log(decryptedData); 126 | ``` 127 | 128 | ### List of modules 129 | 130 | 131 | - ```crypto-js/core``` 132 | - ```crypto-js/x64-core``` 133 | - ```crypto-js/lib-typedarrays``` 134 | 135 | --- 136 | 137 | - ```crypto-js/md5``` 138 | - ```crypto-js/sha1``` 139 | - ```crypto-js/sha256``` 140 | - ```crypto-js/sha224``` 141 | - ```crypto-js/sha512``` 142 | - ```crypto-js/sha384``` 143 | - ```crypto-js/sha3``` 144 | - ```crypto-js/ripemd160``` 145 | 146 | --- 147 | 148 | - ```crypto-js/hmac-md5``` 149 | - ```crypto-js/hmac-sha1``` 150 | - ```crypto-js/hmac-sha256``` 151 | - ```crypto-js/hmac-sha224``` 152 | - ```crypto-js/hmac-sha512``` 153 | - ```crypto-js/hmac-sha384``` 154 | - ```crypto-js/hmac-sha3``` 155 | - ```crypto-js/hmac-ripemd160``` 156 | 157 | --- 158 | 159 | - ```crypto-js/pbkdf2``` 160 | 161 | --- 162 | 163 | - ```crypto-js/aes``` 164 | - ```crypto-js/tripledes``` 165 | - ```crypto-js/rc4``` 166 | - ```crypto-js/rabbit``` 167 | - ```crypto-js/rabbit-legacy``` 168 | - ```crypto-js/evpkdf``` 169 | 170 | --- 171 | 172 | - ```crypto-js/format-openssl``` 173 | - ```crypto-js/format-hex``` 174 | 175 | --- 176 | 177 | - ```crypto-js/enc-latin1``` 178 | - ```crypto-js/enc-utf8``` 179 | - ```crypto-js/enc-hex``` 180 | - ```crypto-js/enc-utf16``` 181 | - ```crypto-js/enc-base64``` 182 | 183 | --- 184 | 185 | - ```crypto-js/mode-cfb``` 186 | - ```crypto-js/mode-ctr``` 187 | - ```crypto-js/mode-ctr-gladman``` 188 | - ```crypto-js/mode-ofb``` 189 | - ```crypto-js/mode-ecb``` 190 | 191 | --- 192 | 193 | - ```crypto-js/pad-pkcs7``` 194 | - ```crypto-js/pad-ansix923``` 195 | - ```crypto-js/pad-iso10126``` 196 | - ```crypto-js/pad-iso97971``` 197 | - ```crypto-js/pad-zeropadding``` 198 | - ```crypto-js/pad-nopadding``` 199 | -------------------------------------------------------------------------------- /src/client/js/crypto-js/hmac.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var Base = C_lib.Base; 21 | var C_enc = C.enc; 22 | var Utf8 = C_enc.Utf8; 23 | var C_algo = C.algo; 24 | 25 | /** 26 | * HMAC algorithm. 27 | */ 28 | var HMAC = C_algo.HMAC = Base.extend({ 29 | /** 30 | * Initializes a newly created HMAC. 31 | * 32 | * @param {Hasher} hasher The hash algorithm to use. 33 | * @param {WordArray|string} key The secret key. 34 | * 35 | * @example 36 | * 37 | * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); 38 | */ 39 | init: function (hasher, key) { 40 | // Init hasher 41 | hasher = this._hasher = new hasher.init(); 42 | 43 | // Convert string to WordArray, else assume WordArray already 44 | if (typeof key == 'string') { 45 | key = Utf8.parse(key); 46 | } 47 | 48 | // Shortcuts 49 | var hasherBlockSize = hasher.blockSize; 50 | var hasherBlockSizeBytes = hasherBlockSize * 4; 51 | 52 | // Allow arbitrary length keys 53 | if (key.sigBytes > hasherBlockSizeBytes) { 54 | key = hasher.finalize(key); 55 | } 56 | 57 | // Clamp excess bits 58 | key.clamp(); 59 | 60 | // Clone key for inner and outer pads 61 | var oKey = this._oKey = key.clone(); 62 | var iKey = this._iKey = key.clone(); 63 | 64 | // Shortcuts 65 | var oKeyWords = oKey.words; 66 | var iKeyWords = iKey.words; 67 | 68 | // XOR keys with pad constants 69 | for (var i = 0; i < hasherBlockSize; i++) { 70 | oKeyWords[i] ^= 0x5c5c5c5c; 71 | iKeyWords[i] ^= 0x36363636; 72 | } 73 | oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes; 74 | 75 | // Set initial values 76 | this.reset(); 77 | }, 78 | 79 | /** 80 | * Resets this HMAC to its initial state. 81 | * 82 | * @example 83 | * 84 | * hmacHasher.reset(); 85 | */ 86 | reset: function () { 87 | // Shortcut 88 | var hasher = this._hasher; 89 | 90 | // Reset 91 | hasher.reset(); 92 | hasher.update(this._iKey); 93 | }, 94 | 95 | /** 96 | * Updates this HMAC with a message. 97 | * 98 | * @param {WordArray|string} messageUpdate The message to append. 99 | * 100 | * @return {HMAC} This HMAC instance. 101 | * 102 | * @example 103 | * 104 | * hmacHasher.update('message'); 105 | * hmacHasher.update(wordArray); 106 | */ 107 | update: function (messageUpdate) { 108 | this._hasher.update(messageUpdate); 109 | 110 | // Chainable 111 | return this; 112 | }, 113 | 114 | /** 115 | * Finalizes the HMAC computation. 116 | * Note that the finalize operation is effectively a destructive, read-once operation. 117 | * 118 | * @param {WordArray|string} messageUpdate (Optional) A final message update. 119 | * 120 | * @return {WordArray} The HMAC. 121 | * 122 | * @example 123 | * 124 | * var hmac = hmacHasher.finalize(); 125 | * var hmac = hmacHasher.finalize('message'); 126 | * var hmac = hmacHasher.finalize(wordArray); 127 | */ 128 | finalize: function (messageUpdate) { 129 | // Shortcut 130 | var hasher = this._hasher; 131 | 132 | // Compute HMAC 133 | var innerHash = hasher.finalize(messageUpdate); 134 | hasher.reset(); 135 | var hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); 136 | 137 | return hmac; 138 | } 139 | }); 140 | }()); 141 | 142 | 143 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/enc-base64.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var WordArray = C_lib.WordArray; 21 | var C_enc = C.enc; 22 | 23 | /** 24 | * Base64 encoding strategy. 25 | */ 26 | var Base64 = C_enc.Base64 = { 27 | /** 28 | * Converts a word array to a Base64 string. 29 | * 30 | * @param {WordArray} wordArray The word array. 31 | * 32 | * @return {string} The Base64 string. 33 | * 34 | * @static 35 | * 36 | * @example 37 | * 38 | * var base64String = CryptoJS.enc.Base64.stringify(wordArray); 39 | */ 40 | stringify: function (wordArray) { 41 | // Shortcuts 42 | var words = wordArray.words; 43 | var sigBytes = wordArray.sigBytes; 44 | var map = this._map; 45 | 46 | // Clamp excess bits 47 | wordArray.clamp(); 48 | 49 | // Convert 50 | var base64Chars = []; 51 | for (var i = 0; i < sigBytes; i += 3) { 52 | var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; 53 | var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; 54 | var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; 55 | 56 | var triplet = (byte1 << 16) | (byte2 << 8) | byte3; 57 | 58 | for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { 59 | base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); 60 | } 61 | } 62 | 63 | // Add padding 64 | var paddingChar = map.charAt(64); 65 | if (paddingChar) { 66 | while (base64Chars.length % 4) { 67 | base64Chars.push(paddingChar); 68 | } 69 | } 70 | 71 | return base64Chars.join(''); 72 | }, 73 | 74 | /** 75 | * Converts a Base64 string to a word array. 76 | * 77 | * @param {string} base64Str The Base64 string. 78 | * 79 | * @return {WordArray} The word array. 80 | * 81 | * @static 82 | * 83 | * @example 84 | * 85 | * var wordArray = CryptoJS.enc.Base64.parse(base64String); 86 | */ 87 | parse: function (base64Str) { 88 | // Shortcuts 89 | var base64StrLength = base64Str.length; 90 | var map = this._map; 91 | var reverseMap = this._reverseMap; 92 | 93 | if (!reverseMap) { 94 | reverseMap = this._reverseMap = []; 95 | for (var j = 0; j < map.length; j++) { 96 | reverseMap[map.charCodeAt(j)] = j; 97 | } 98 | } 99 | 100 | // Ignore padding 101 | var paddingChar = map.charAt(64); 102 | if (paddingChar) { 103 | var paddingIndex = base64Str.indexOf(paddingChar); 104 | if (paddingIndex !== -1) { 105 | base64StrLength = paddingIndex; 106 | } 107 | } 108 | 109 | // Convert 110 | return parseLoop(base64Str, base64StrLength, reverseMap); 111 | 112 | }, 113 | 114 | _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' 115 | }; 116 | 117 | function parseLoop(base64Str, base64StrLength, reverseMap) { 118 | var words = []; 119 | var nBytes = 0; 120 | for (var i = 0; i < base64StrLength; i++) { 121 | if (i % 4) { 122 | var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); 123 | var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); 124 | words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8); 125 | nBytes++; 126 | } 127 | } 128 | return WordArray.create(words, nBytes); 129 | } 130 | }()); 131 | 132 | 133 | return CryptoJS.enc.Base64; 134 | 135 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/sha1.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var WordArray = C_lib.WordArray; 21 | var Hasher = C_lib.Hasher; 22 | var C_algo = C.algo; 23 | 24 | // Reusable object 25 | var W = []; 26 | 27 | /** 28 | * SHA-1 hash algorithm. 29 | */ 30 | var SHA1 = C_algo.SHA1 = Hasher.extend({ 31 | _doReset: function () { 32 | this._hash = new WordArray.init([ 33 | 0x67452301, 0xefcdab89, 34 | 0x98badcfe, 0x10325476, 35 | 0xc3d2e1f0 36 | ]); 37 | }, 38 | 39 | _doProcessBlock: function (M, offset) { 40 | // Shortcut 41 | var H = this._hash.words; 42 | 43 | // Working variables 44 | var a = H[0]; 45 | var b = H[1]; 46 | var c = H[2]; 47 | var d = H[3]; 48 | var e = H[4]; 49 | 50 | // Computation 51 | for (var i = 0; i < 80; i++) { 52 | if (i < 16) { 53 | W[i] = M[offset + i] | 0; 54 | } else { 55 | var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; 56 | W[i] = (n << 1) | (n >>> 31); 57 | } 58 | 59 | var t = ((a << 5) | (a >>> 27)) + e + W[i]; 60 | if (i < 20) { 61 | t += ((b & c) | (~b & d)) + 0x5a827999; 62 | } else if (i < 40) { 63 | t += (b ^ c ^ d) + 0x6ed9eba1; 64 | } else if (i < 60) { 65 | t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; 66 | } else /* if (i < 80) */ { 67 | t += (b ^ c ^ d) - 0x359d3e2a; 68 | } 69 | 70 | e = d; 71 | d = c; 72 | c = (b << 30) | (b >>> 2); 73 | b = a; 74 | a = t; 75 | } 76 | 77 | // Intermediate hash value 78 | H[0] = (H[0] + a) | 0; 79 | H[1] = (H[1] + b) | 0; 80 | H[2] = (H[2] + c) | 0; 81 | H[3] = (H[3] + d) | 0; 82 | H[4] = (H[4] + e) | 0; 83 | }, 84 | 85 | _doFinalize: function () { 86 | // Shortcuts 87 | var data = this._data; 88 | var dataWords = data.words; 89 | 90 | var nBitsTotal = this._nDataBytes * 8; 91 | var nBitsLeft = data.sigBytes * 8; 92 | 93 | // Add padding 94 | dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); 95 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); 96 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; 97 | data.sigBytes = dataWords.length * 4; 98 | 99 | // Hash final blocks 100 | this._process(); 101 | 102 | // Return final computed hash 103 | return this._hash; 104 | }, 105 | 106 | clone: function () { 107 | var clone = Hasher.clone.call(this); 108 | clone._hash = this._hash.clone(); 109 | 110 | return clone; 111 | } 112 | }); 113 | 114 | /** 115 | * Shortcut function to the hasher's object interface. 116 | * 117 | * @param {WordArray|string} message The message to hash. 118 | * 119 | * @return {WordArray} The hash. 120 | * 121 | * @static 122 | * 123 | * @example 124 | * 125 | * var hash = CryptoJS.SHA1('message'); 126 | * var hash = CryptoJS.SHA1(wordArray); 127 | */ 128 | C.SHA1 = Hasher._createHelper(SHA1); 129 | 130 | /** 131 | * Shortcut function to the HMAC's object interface. 132 | * 133 | * @param {WordArray|string} message The message to hash. 134 | * @param {WordArray|string} key The secret key. 135 | * 136 | * @return {WordArray} The HMAC. 137 | * 138 | * @static 139 | * 140 | * @example 141 | * 142 | * var hmac = CryptoJS.HmacSHA1(message, key); 143 | */ 144 | C.HmacSHA1 = Hasher._createHmacHelper(SHA1); 145 | }()); 146 | 147 | 148 | return CryptoJS.SHA1; 149 | 150 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/enc-utf16.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var WordArray = C_lib.WordArray; 21 | var C_enc = C.enc; 22 | 23 | /** 24 | * UTF-16 BE encoding strategy. 25 | */ 26 | var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = { 27 | /** 28 | * Converts a word array to a UTF-16 BE string. 29 | * 30 | * @param {WordArray} wordArray The word array. 31 | * 32 | * @return {string} The UTF-16 BE string. 33 | * 34 | * @static 35 | * 36 | * @example 37 | * 38 | * var utf16String = CryptoJS.enc.Utf16.stringify(wordArray); 39 | */ 40 | stringify: function (wordArray) { 41 | // Shortcuts 42 | var words = wordArray.words; 43 | var sigBytes = wordArray.sigBytes; 44 | 45 | // Convert 46 | var utf16Chars = []; 47 | for (var i = 0; i < sigBytes; i += 2) { 48 | var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; 49 | utf16Chars.push(String.fromCharCode(codePoint)); 50 | } 51 | 52 | return utf16Chars.join(''); 53 | }, 54 | 55 | /** 56 | * Converts a UTF-16 BE string to a word array. 57 | * 58 | * @param {string} utf16Str The UTF-16 BE string. 59 | * 60 | * @return {WordArray} The word array. 61 | * 62 | * @static 63 | * 64 | * @example 65 | * 66 | * var wordArray = CryptoJS.enc.Utf16.parse(utf16String); 67 | */ 68 | parse: function (utf16Str) { 69 | // Shortcut 70 | var utf16StrLength = utf16Str.length; 71 | 72 | // Convert 73 | var words = []; 74 | for (var i = 0; i < utf16StrLength; i++) { 75 | words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); 76 | } 77 | 78 | return WordArray.create(words, utf16StrLength * 2); 79 | } 80 | }; 81 | 82 | /** 83 | * UTF-16 LE encoding strategy. 84 | */ 85 | C_enc.Utf16LE = { 86 | /** 87 | * Converts a word array to a UTF-16 LE string. 88 | * 89 | * @param {WordArray} wordArray The word array. 90 | * 91 | * @return {string} The UTF-16 LE string. 92 | * 93 | * @static 94 | * 95 | * @example 96 | * 97 | * var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); 98 | */ 99 | stringify: function (wordArray) { 100 | // Shortcuts 101 | var words = wordArray.words; 102 | var sigBytes = wordArray.sigBytes; 103 | 104 | // Convert 105 | var utf16Chars = []; 106 | for (var i = 0; i < sigBytes; i += 2) { 107 | var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); 108 | utf16Chars.push(String.fromCharCode(codePoint)); 109 | } 110 | 111 | return utf16Chars.join(''); 112 | }, 113 | 114 | /** 115 | * Converts a UTF-16 LE string to a word array. 116 | * 117 | * @param {string} utf16Str The UTF-16 LE string. 118 | * 119 | * @return {WordArray} The word array. 120 | * 121 | * @static 122 | * 123 | * @example 124 | * 125 | * var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); 126 | */ 127 | parse: function (utf16Str) { 128 | // Shortcut 129 | var utf16StrLength = utf16Str.length; 130 | 131 | // Convert 132 | var words = []; 133 | for (var i = 0; i < utf16StrLength; i++) { 134 | words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); 135 | } 136 | 137 | return WordArray.create(words, utf16StrLength * 2); 138 | } 139 | }; 140 | 141 | function swapEndian(word) { 142 | return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); 143 | } 144 | }()); 145 | 146 | 147 | return CryptoJS.enc.Utf16; 148 | 149 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/pbkdf2.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./sha1", "./hmac"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var Base = C_lib.Base; 21 | var WordArray = C_lib.WordArray; 22 | var C_algo = C.algo; 23 | var SHA1 = C_algo.SHA1; 24 | var HMAC = C_algo.HMAC; 25 | 26 | /** 27 | * Password-Based Key Derivation Function 2 algorithm. 28 | */ 29 | var PBKDF2 = C_algo.PBKDF2 = Base.extend({ 30 | /** 31 | * Configuration options. 32 | * 33 | * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) 34 | * @property {Hasher} hasher The hasher to use. Default: SHA1 35 | * @property {number} iterations The number of iterations to perform. Default: 1 36 | */ 37 | cfg: Base.extend({ 38 | keySize: 128/32, 39 | hasher: SHA1, 40 | iterations: 1 41 | }), 42 | 43 | /** 44 | * Initializes a newly created key derivation function. 45 | * 46 | * @param {Object} cfg (Optional) The configuration options to use for the derivation. 47 | * 48 | * @example 49 | * 50 | * var kdf = CryptoJS.algo.PBKDF2.create(); 51 | * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); 52 | * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); 53 | */ 54 | init: function (cfg) { 55 | this.cfg = this.cfg.extend(cfg); 56 | }, 57 | 58 | /** 59 | * Computes the Password-Based Key Derivation Function 2. 60 | * 61 | * @param {WordArray|string} password The password. 62 | * @param {WordArray|string} salt A salt. 63 | * 64 | * @return {WordArray} The derived key. 65 | * 66 | * @example 67 | * 68 | * var key = kdf.compute(password, salt); 69 | */ 70 | compute: function (password, salt) { 71 | // Shortcut 72 | var cfg = this.cfg; 73 | 74 | // Init HMAC 75 | var hmac = HMAC.create(cfg.hasher, password); 76 | 77 | // Initial values 78 | var derivedKey = WordArray.create(); 79 | var blockIndex = WordArray.create([0x00000001]); 80 | 81 | // Shortcuts 82 | var derivedKeyWords = derivedKey.words; 83 | var blockIndexWords = blockIndex.words; 84 | var keySize = cfg.keySize; 85 | var iterations = cfg.iterations; 86 | 87 | // Generate key 88 | while (derivedKeyWords.length < keySize) { 89 | var block = hmac.update(salt).finalize(blockIndex); 90 | hmac.reset(); 91 | 92 | // Shortcuts 93 | var blockWords = block.words; 94 | var blockWordsLength = blockWords.length; 95 | 96 | // Iterations 97 | var intermediate = block; 98 | for (var i = 1; i < iterations; i++) { 99 | intermediate = hmac.finalize(intermediate); 100 | hmac.reset(); 101 | 102 | // Shortcut 103 | var intermediateWords = intermediate.words; 104 | 105 | // XOR intermediate with block 106 | for (var j = 0; j < blockWordsLength; j++) { 107 | blockWords[j] ^= intermediateWords[j]; 108 | } 109 | } 110 | 111 | derivedKey.concat(block); 112 | blockIndexWords[0]++; 113 | } 114 | derivedKey.sigBytes = keySize * 4; 115 | 116 | return derivedKey; 117 | } 118 | }); 119 | 120 | /** 121 | * Computes the Password-Based Key Derivation Function 2. 122 | * 123 | * @param {WordArray|string} password The password. 124 | * @param {WordArray|string} salt A salt. 125 | * @param {Object} cfg (Optional) The configuration options to use for this computation. 126 | * 127 | * @return {WordArray} The derived key. 128 | * 129 | * @static 130 | * 131 | * @example 132 | * 133 | * var key = CryptoJS.PBKDF2(password, salt); 134 | * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); 135 | * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); 136 | */ 137 | C.PBKDF2 = function (password, salt, cfg) { 138 | return PBKDF2.create(cfg).compute(password, salt); 139 | }; 140 | }()); 141 | 142 | 143 | return CryptoJS.PBKDF2; 144 | 145 | })); -------------------------------------------------------------------------------- /src/client/views/chat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | Secure Chat 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 |
35 | 38 | 39 | Register 40 | 41 |
42 | 43 | 44 |
45 | 46 |
47 | 48 | 49 |
50 | 51 |
52 | 53 | 54 |
55 | 56 |
57 | 60 |
61 | 62 |
63 |
64 |
65 |
66 | 67 | 68 | 69 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /src/client/js/crypto-js/sha256.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function (Math) { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var WordArray = C_lib.WordArray; 21 | var Hasher = C_lib.Hasher; 22 | var C_algo = C.algo; 23 | 24 | // Initialization and round constants tables 25 | var H = []; 26 | var K = []; 27 | 28 | // Compute constants 29 | (function () { 30 | function isPrime(n) { 31 | var sqrtN = Math.sqrt(n); 32 | for (var factor = 2; factor <= sqrtN; factor++) { 33 | if (!(n % factor)) { 34 | return false; 35 | } 36 | } 37 | 38 | return true; 39 | } 40 | 41 | function getFractionalBits(n) { 42 | return ((n - (n | 0)) * 0x100000000) | 0; 43 | } 44 | 45 | var n = 2; 46 | var nPrime = 0; 47 | while (nPrime < 64) { 48 | if (isPrime(n)) { 49 | if (nPrime < 8) { 50 | H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); 51 | } 52 | K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); 53 | 54 | nPrime++; 55 | } 56 | 57 | n++; 58 | } 59 | }()); 60 | 61 | // Reusable object 62 | var W = []; 63 | 64 | /** 65 | * SHA-256 hash algorithm. 66 | */ 67 | var SHA256 = C_algo.SHA256 = Hasher.extend({ 68 | _doReset: function () { 69 | this._hash = new WordArray.init(H.slice(0)); 70 | }, 71 | 72 | _doProcessBlock: function (M, offset) { 73 | // Shortcut 74 | var H = this._hash.words; 75 | 76 | // Working variables 77 | var a = H[0]; 78 | var b = H[1]; 79 | var c = H[2]; 80 | var d = H[3]; 81 | var e = H[4]; 82 | var f = H[5]; 83 | var g = H[6]; 84 | var h = H[7]; 85 | 86 | // Computation 87 | for (var i = 0; i < 64; i++) { 88 | if (i < 16) { 89 | W[i] = M[offset + i] | 0; 90 | } else { 91 | var gamma0x = W[i - 15]; 92 | var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ 93 | ((gamma0x << 14) | (gamma0x >>> 18)) ^ 94 | (gamma0x >>> 3); 95 | 96 | var gamma1x = W[i - 2]; 97 | var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ 98 | ((gamma1x << 13) | (gamma1x >>> 19)) ^ 99 | (gamma1x >>> 10); 100 | 101 | W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; 102 | } 103 | 104 | var ch = (e & f) ^ (~e & g); 105 | var maj = (a & b) ^ (a & c) ^ (b & c); 106 | 107 | var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); 108 | var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); 109 | 110 | var t1 = h + sigma1 + ch + K[i] + W[i]; 111 | var t2 = sigma0 + maj; 112 | 113 | h = g; 114 | g = f; 115 | f = e; 116 | e = (d + t1) | 0; 117 | d = c; 118 | c = b; 119 | b = a; 120 | a = (t1 + t2) | 0; 121 | } 122 | 123 | // Intermediate hash value 124 | H[0] = (H[0] + a) | 0; 125 | H[1] = (H[1] + b) | 0; 126 | H[2] = (H[2] + c) | 0; 127 | H[3] = (H[3] + d) | 0; 128 | H[4] = (H[4] + e) | 0; 129 | H[5] = (H[5] + f) | 0; 130 | H[6] = (H[6] + g) | 0; 131 | H[7] = (H[7] + h) | 0; 132 | }, 133 | 134 | _doFinalize: function () { 135 | // Shortcuts 136 | var data = this._data; 137 | var dataWords = data.words; 138 | 139 | var nBitsTotal = this._nDataBytes * 8; 140 | var nBitsLeft = data.sigBytes * 8; 141 | 142 | // Add padding 143 | dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); 144 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); 145 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; 146 | data.sigBytes = dataWords.length * 4; 147 | 148 | // Hash final blocks 149 | this._process(); 150 | 151 | // Return final computed hash 152 | return this._hash; 153 | }, 154 | 155 | clone: function () { 156 | var clone = Hasher.clone.call(this); 157 | clone._hash = this._hash.clone(); 158 | 159 | return clone; 160 | } 161 | }); 162 | 163 | /** 164 | * Shortcut function to the hasher's object interface. 165 | * 166 | * @param {WordArray|string} message The message to hash. 167 | * 168 | * @return {WordArray} The hash. 169 | * 170 | * @static 171 | * 172 | * @example 173 | * 174 | * var hash = CryptoJS.SHA256('message'); 175 | * var hash = CryptoJS.SHA256(wordArray); 176 | */ 177 | C.SHA256 = Hasher._createHelper(SHA256); 178 | 179 | /** 180 | * Shortcut function to the HMAC's object interface. 181 | * 182 | * @param {WordArray|string} message The message to hash. 183 | * @param {WordArray|string} key The secret key. 184 | * 185 | * @return {WordArray} The HMAC. 186 | * 187 | * @static 188 | * 189 | * @example 190 | * 191 | * var hmac = CryptoJS.HmacSHA256(message, key); 192 | */ 193 | C.HmacSHA256 = Hasher._createHmacHelper(SHA256); 194 | }(Math)); 195 | 196 | 197 | return CryptoJS.SHA256; 198 | 199 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/rabbit.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var StreamCipher = C_lib.StreamCipher; 21 | var C_algo = C.algo; 22 | 23 | // Reusable objects 24 | var S = []; 25 | var C_ = []; 26 | var G = []; 27 | 28 | /** 29 | * Rabbit stream cipher algorithm 30 | */ 31 | var Rabbit = C_algo.Rabbit = StreamCipher.extend({ 32 | _doReset: function () { 33 | // Shortcuts 34 | var K = this._key.words; 35 | var iv = this.cfg.iv; 36 | 37 | // Swap endian 38 | for (var i = 0; i < 4; i++) { 39 | K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) | 40 | (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); 41 | } 42 | 43 | // Generate initial state values 44 | var X = this._X = [ 45 | K[0], (K[3] << 16) | (K[2] >>> 16), 46 | K[1], (K[0] << 16) | (K[3] >>> 16), 47 | K[2], (K[1] << 16) | (K[0] >>> 16), 48 | K[3], (K[2] << 16) | (K[1] >>> 16) 49 | ]; 50 | 51 | // Generate initial counter values 52 | var C = this._C = [ 53 | (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), 54 | (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), 55 | (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), 56 | (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) 57 | ]; 58 | 59 | // Carry bit 60 | this._b = 0; 61 | 62 | // Iterate the system four times 63 | for (var i = 0; i < 4; i++) { 64 | nextState.call(this); 65 | } 66 | 67 | // Modify the counters 68 | for (var i = 0; i < 8; i++) { 69 | C[i] ^= X[(i + 4) & 7]; 70 | } 71 | 72 | // IV setup 73 | if (iv) { 74 | // Shortcuts 75 | var IV = iv.words; 76 | var IV_0 = IV[0]; 77 | var IV_1 = IV[1]; 78 | 79 | // Generate four subvectors 80 | var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); 81 | var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); 82 | var i1 = (i0 >>> 16) | (i2 & 0xffff0000); 83 | var i3 = (i2 << 16) | (i0 & 0x0000ffff); 84 | 85 | // Modify counter values 86 | C[0] ^= i0; 87 | C[1] ^= i1; 88 | C[2] ^= i2; 89 | C[3] ^= i3; 90 | C[4] ^= i0; 91 | C[5] ^= i1; 92 | C[6] ^= i2; 93 | C[7] ^= i3; 94 | 95 | // Iterate the system four times 96 | for (var i = 0; i < 4; i++) { 97 | nextState.call(this); 98 | } 99 | } 100 | }, 101 | 102 | _doProcessBlock: function (M, offset) { 103 | // Shortcut 104 | var X = this._X; 105 | 106 | // Iterate the system 107 | nextState.call(this); 108 | 109 | // Generate four keystream words 110 | S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); 111 | S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); 112 | S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); 113 | S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); 114 | 115 | for (var i = 0; i < 4; i++) { 116 | // Swap endian 117 | S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | 118 | (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); 119 | 120 | // Encrypt 121 | M[offset + i] ^= S[i]; 122 | } 123 | }, 124 | 125 | blockSize: 128/32, 126 | 127 | ivSize: 64/32 128 | }); 129 | 130 | function nextState() { 131 | // Shortcuts 132 | var X = this._X; 133 | var C = this._C; 134 | 135 | // Save old counter values 136 | for (var i = 0; i < 8; i++) { 137 | C_[i] = C[i]; 138 | } 139 | 140 | // Calculate new counter values 141 | C[0] = (C[0] + 0x4d34d34d + this._b) | 0; 142 | C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; 143 | C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; 144 | C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; 145 | C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; 146 | C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; 147 | C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; 148 | C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; 149 | this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; 150 | 151 | // Calculate the g-values 152 | for (var i = 0; i < 8; i++) { 153 | var gx = X[i] + C[i]; 154 | 155 | // Construct high and low argument for squaring 156 | var ga = gx & 0xffff; 157 | var gb = gx >>> 16; 158 | 159 | // Calculate high and low result of squaring 160 | var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; 161 | var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); 162 | 163 | // High XOR low 164 | G[i] = gh ^ gl; 165 | } 166 | 167 | // Calculate new state values 168 | X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; 169 | X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; 170 | X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; 171 | X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; 172 | X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; 173 | X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; 174 | X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; 175 | X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; 176 | } 177 | 178 | /** 179 | * Shortcut functions to the cipher's object interface. 180 | * 181 | * @example 182 | * 183 | * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); 184 | * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); 185 | */ 186 | C.Rabbit = StreamCipher._createHelper(Rabbit); 187 | }()); 188 | 189 | 190 | return CryptoJS.Rabbit; 191 | 192 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/rabbit-legacy.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var StreamCipher = C_lib.StreamCipher; 21 | var C_algo = C.algo; 22 | 23 | // Reusable objects 24 | var S = []; 25 | var C_ = []; 26 | var G = []; 27 | 28 | /** 29 | * Rabbit stream cipher algorithm. 30 | * 31 | * This is a legacy version that neglected to convert the key to little-endian. 32 | * This error doesn't affect the cipher's security, 33 | * but it does affect its compatibility with other implementations. 34 | */ 35 | var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({ 36 | _doReset: function () { 37 | // Shortcuts 38 | var K = this._key.words; 39 | var iv = this.cfg.iv; 40 | 41 | // Generate initial state values 42 | var X = this._X = [ 43 | K[0], (K[3] << 16) | (K[2] >>> 16), 44 | K[1], (K[0] << 16) | (K[3] >>> 16), 45 | K[2], (K[1] << 16) | (K[0] >>> 16), 46 | K[3], (K[2] << 16) | (K[1] >>> 16) 47 | ]; 48 | 49 | // Generate initial counter values 50 | var C = this._C = [ 51 | (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), 52 | (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), 53 | (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), 54 | (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) 55 | ]; 56 | 57 | // Carry bit 58 | this._b = 0; 59 | 60 | // Iterate the system four times 61 | for (var i = 0; i < 4; i++) { 62 | nextState.call(this); 63 | } 64 | 65 | // Modify the counters 66 | for (var i = 0; i < 8; i++) { 67 | C[i] ^= X[(i + 4) & 7]; 68 | } 69 | 70 | // IV setup 71 | if (iv) { 72 | // Shortcuts 73 | var IV = iv.words; 74 | var IV_0 = IV[0]; 75 | var IV_1 = IV[1]; 76 | 77 | // Generate four subvectors 78 | var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); 79 | var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); 80 | var i1 = (i0 >>> 16) | (i2 & 0xffff0000); 81 | var i3 = (i2 << 16) | (i0 & 0x0000ffff); 82 | 83 | // Modify counter values 84 | C[0] ^= i0; 85 | C[1] ^= i1; 86 | C[2] ^= i2; 87 | C[3] ^= i3; 88 | C[4] ^= i0; 89 | C[5] ^= i1; 90 | C[6] ^= i2; 91 | C[7] ^= i3; 92 | 93 | // Iterate the system four times 94 | for (var i = 0; i < 4; i++) { 95 | nextState.call(this); 96 | } 97 | } 98 | }, 99 | 100 | _doProcessBlock: function (M, offset) { 101 | // Shortcut 102 | var X = this._X; 103 | 104 | // Iterate the system 105 | nextState.call(this); 106 | 107 | // Generate four keystream words 108 | S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); 109 | S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); 110 | S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); 111 | S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); 112 | 113 | for (var i = 0; i < 4; i++) { 114 | // Swap endian 115 | S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | 116 | (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); 117 | 118 | // Encrypt 119 | M[offset + i] ^= S[i]; 120 | } 121 | }, 122 | 123 | blockSize: 128/32, 124 | 125 | ivSize: 64/32 126 | }); 127 | 128 | function nextState() { 129 | // Shortcuts 130 | var X = this._X; 131 | var C = this._C; 132 | 133 | // Save old counter values 134 | for (var i = 0; i < 8; i++) { 135 | C_[i] = C[i]; 136 | } 137 | 138 | // Calculate new counter values 139 | C[0] = (C[0] + 0x4d34d34d + this._b) | 0; 140 | C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; 141 | C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; 142 | C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; 143 | C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; 144 | C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; 145 | C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; 146 | C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; 147 | this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; 148 | 149 | // Calculate the g-values 150 | for (var i = 0; i < 8; i++) { 151 | var gx = X[i] + C[i]; 152 | 153 | // Construct high and low argument for squaring 154 | var ga = gx & 0xffff; 155 | var gb = gx >>> 16; 156 | 157 | // Calculate high and low result of squaring 158 | var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; 159 | var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); 160 | 161 | // High XOR low 162 | G[i] = gh ^ gl; 163 | } 164 | 165 | // Calculate new state values 166 | X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; 167 | X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; 168 | X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; 169 | X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; 170 | X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; 171 | X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; 172 | X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; 173 | X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; 174 | } 175 | 176 | /** 177 | * Shortcut functions to the cipher's object interface. 178 | * 179 | * @example 180 | * 181 | * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); 182 | * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); 183 | */ 184 | C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy); 185 | }()); 186 | 187 | 188 | return CryptoJS.RabbitLegacy; 189 | 190 | })); -------------------------------------------------------------------------------- /src/client/css/login.css: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------*/ 2 | 3 | a { 4 | font-size: 14px; 5 | line-height: 1.7; 6 | color: #666666; 7 | margin: 0px; 8 | transition: all 0.4s; 9 | -webkit-transition: all 0.4s; 10 | -o-transition: all 0.4s; 11 | -moz-transition: all 0.4s; 12 | } 13 | 14 | a:focus { 15 | outline: none !important; 16 | } 17 | 18 | a:hover { 19 | text-decoration: none; 20 | color: #fff; 21 | } 22 | 23 | /*---------------------------------------------*/ 24 | 25 | h1, h2, h3, h4, h5, h6 { 26 | margin: 0px; 27 | } 28 | 29 | /*---------------------------------------------*/ 30 | 31 | input.input100 { 32 | outline: none; 33 | border: none; 34 | } 35 | 36 | input.input100:focus::-webkit-input-placeholder { 37 | color: transparent; 38 | } 39 | 40 | input.input100:focus:-moz-placeholder { 41 | color: transparent; 42 | } 43 | 44 | input.input100:focus::-moz-placeholder { 45 | color: transparent; 46 | } 47 | 48 | input.input100:focus:-ms-input-placeholder { 49 | color: transparent; 50 | } 51 | 52 | input.input100::-webkit-input-placeholder { 53 | color: #fff; 54 | } 55 | 56 | input.input100:-moz-placeholder { 57 | color: #fff; 58 | } 59 | 60 | input.input100::-moz-placeholder { 61 | color: #fff; 62 | } 63 | 64 | input.input100:-ms-input-placeholder { 65 | color: #fff; 66 | } 67 | 68 | /*---------------------------------------------*/ 69 | 70 | button.login100-form-btn { 71 | outline: none !important; 72 | border: none; 73 | background: transparent; 74 | } 75 | 76 | button.login100-form-btn:hover { 77 | cursor: pointer; 78 | } 79 | 80 | /*////////////////////////////////////////////////////////////////// 81 | [ login ]*/ 82 | 83 | .limiter { 84 | width: 100%; 85 | margin: 0 auto; 86 | } 87 | 88 | .container-login100 { 89 | width: 100%; 90 | min-height: 100vh; 91 | display: -webkit-box; 92 | display: -webkit-flex; 93 | display: -moz-box; 94 | display: -ms-flexbox; 95 | display: flex; 96 | flex-wrap: wrap; 97 | justify-content: center; 98 | align-items: center; 99 | padding: 15px; 100 | background-repeat: no-repeat; 101 | background-position: center; 102 | background-size: cover; 103 | position: relative; 104 | z-index: 1; 105 | } 106 | 107 | .container-login100::before { 108 | content: ""; 109 | display: block; 110 | position: absolute; 111 | z-index: -1; 112 | width: 100%; 113 | height: 100%; 114 | top: 0; 115 | left: 0; 116 | background-color: rgba(255, 255, 255, 0.9); 117 | } 118 | 119 | .wrap-login100 { 120 | width: 500px; 121 | border-radius: 10px; 122 | overflow: hidden; 123 | padding: 55px 55px 37px 55px; 124 | background: #9152f8; 125 | background: -webkit-linear-gradient(top, #7579ff, #b224ef); 126 | background: -o-linear-gradient(top, #7579ff, #b224ef); 127 | background: -moz-linear-gradient(top, #7579ff, #b224ef); 128 | background: linear-gradient(top, #7579ff, #b224ef); 129 | } 130 | 131 | /*------------------------------------------------------------------ 132 | [ Form ]*/ 133 | 134 | .login100-form { 135 | width: 100%; 136 | } 137 | 138 | .login100-form-logo { 139 | font-size: 60px; 140 | color: #333333; 141 | display: -webkit-box; 142 | display: -webkit-flex; 143 | display: -moz-box; 144 | display: -ms-flexbox; 145 | display: flex; 146 | justify-content: center; 147 | align-items: center; 148 | width: 120px; 149 | height: 120px; 150 | border-radius: 50%; 151 | background-color: #fff; 152 | margin: 0 auto; 153 | } 154 | 155 | .login100-form-logo img { 156 | border-radius: 50%; 157 | } 158 | 159 | .login100-form-title { 160 | font-size: 30px; 161 | color: #fff; 162 | line-height: 1.2; 163 | text-align: center; 164 | text-transform: uppercase; 165 | padding-top: 27px; 166 | padding-bottom: 34px; 167 | display: block; 168 | } 169 | 170 | /*------------------------------------------------------------------ 171 | [ Input ]*/ 172 | 173 | .wrap-input100 { 174 | width: 100%; 175 | position: relative; 176 | border-bottom: 2px solid rgba(255, 255, 255, 0.24); 177 | margin-bottom: 30px; 178 | } 179 | 180 | .input100 { 181 | font-size: 16px; 182 | color: #fff; 183 | line-height: 1.2; 184 | display: block; 185 | width: 100%; 186 | height: 45px; 187 | background: transparent; 188 | padding: 0 5px 0 10px; 189 | } 190 | 191 | /*---------------------------------------------*/ 192 | 193 | .focus-input100 { 194 | position: absolute; 195 | display: block; 196 | width: 100%; 197 | height: 100%; 198 | top: 0; 199 | left: 0; 200 | pointer-events: none; 201 | } 202 | 203 | .focus-input100::before { 204 | content: ""; 205 | display: block; 206 | position: absolute; 207 | bottom: -2px; 208 | left: 0; 209 | width: 0; 210 | height: 2px; 211 | -webkit-transition: all 0.4s; 212 | -o-transition: all 0.4s; 213 | -moz-transition: all 0.4s; 214 | transition: all 0.4s; 215 | background: #fff; 216 | } 217 | 218 | .focus-input100::after { 219 | font-size: 22px; 220 | color: #fff; 221 | content: attr(data-placeholder); 222 | display: block; 223 | width: 100%; 224 | position: absolute; 225 | top: 6px; 226 | left: 0px; 227 | padding-left: 5px; 228 | -webkit-transition: all 0.4s; 229 | -o-transition: all 0.4s; 230 | -moz-transition: all 0.4s; 231 | transition: all 0.4s; 232 | } 233 | 234 | .input100:focus { 235 | padding-left: 5px; 236 | } 237 | 238 | .input100:focus+.focus-input100::after { 239 | top: -22px; 240 | font-size: 18px; 241 | } 242 | 243 | .input100:focus+.focus-input100::before { 244 | width: 100%; 245 | } 246 | 247 | .has-val.input100+.focus-input100::after { 248 | top: -22px; 249 | font-size: 18px; 250 | } 251 | 252 | .has-val.input100+.focus-input100::before { 253 | width: 100%; 254 | } 255 | 256 | .has-val.input100 { 257 | padding-left: 5px; 258 | } 259 | 260 | /*------------------------------------------------------------------ 261 | [ Button ]*/ 262 | 263 | .container-login100-form-btn { 264 | width: 100%; 265 | display: -webkit-box; 266 | display: -webkit-flex; 267 | display: -moz-box; 268 | display: -ms-flexbox; 269 | display: flex; 270 | flex-wrap: wrap; 271 | justify-content: center; 272 | } 273 | 274 | .login100-form-btn { 275 | font-size: 16px; 276 | color: #555555; 277 | line-height: 1.2; 278 | display: -webkit-box; 279 | display: -webkit-flex; 280 | display: -moz-box; 281 | display: -ms-flexbox; 282 | display: flex; 283 | justify-content: center; 284 | align-items: center; 285 | padding: 0 20px; 286 | min-width: 120px; 287 | height: 50px; 288 | border-radius: 25px; 289 | background: #9152f8; 290 | background: -webkit-linear-gradient(bottom, #7579ff, #b224ef); 291 | background: -o-linear-gradient(bottom, #7579ff, #b224ef); 292 | background: -moz-linear-gradient(bottom, #7579ff, #b224ef); 293 | background: linear-gradient(bottom, #7579ff, #b224ef); 294 | position: relative; 295 | z-index: 1; 296 | -webkit-transition: all 0.4s; 297 | -o-transition: all 0.4s; 298 | -moz-transition: all 0.4s; 299 | transition: all 0.4s; 300 | } 301 | 302 | .login100-form-btn::before { 303 | content: ""; 304 | display: block; 305 | position: absolute; 306 | z-index: -1; 307 | width: 100%; 308 | height: 100%; 309 | border-radius: 25px; 310 | background-color: #fff; 311 | top: 0; 312 | left: 0; 313 | opacity: 1; 314 | -webkit-transition: all 0.4s; 315 | -o-transition: all 0.4s; 316 | -moz-transition: all 0.4s; 317 | transition: all 0.4s; 318 | } 319 | 320 | .login100-form-btn:hover { 321 | color: #fff; 322 | } 323 | 324 | .login100-form-btn:hover:before { 325 | opacity: 0; 326 | } 327 | 328 | /*------------------------------------------------------------------ 329 | [ Responsive ]*/ 330 | 331 | @media (max-width: 576px) { 332 | .wrap-login100 { 333 | padding: 55px 15px 37px 15px; 334 | } 335 | } 336 | 337 | /*------------------------------------------------------------------ 338 | [ Alert validate ]*/ 339 | 340 | .validate-input { 341 | position: relative; 342 | } 343 | 344 | .alert-validate::before { 345 | content: attr(data-validate); 346 | position: absolute; 347 | max-width: 70%; 348 | background-color: #fff; 349 | border: 1px solid #c80000; 350 | border-radius: 2px; 351 | padding: 4px 25px 4px 10px; 352 | top: 50%; 353 | -webkit-transform: translateY(-50%); 354 | -moz-transform: translateY(-50%); 355 | -ms-transform: translateY(-50%); 356 | -o-transform: translateY(-50%); 357 | transform: translateY(-50%); 358 | right: 0px; 359 | pointer-events: none; 360 | color: #c80000; 361 | font-size: 13px; 362 | line-height: 1.4; 363 | text-align: left; 364 | visibility: hidden; 365 | opacity: 0; 366 | -webkit-transition: opacity 0.4s; 367 | -o-transition: opacity 0.4s; 368 | -moz-transition: opacity 0.4s; 369 | transition: opacity 0.4s; 370 | } 371 | 372 | .alert-validate::after { 373 | content: "\f12a"; 374 | font-family: FontAwesome; 375 | font-size: 16px; 376 | color: #c80000; 377 | display: block; 378 | position: absolute; 379 | top: 50%; 380 | -webkit-transform: translateY(-50%); 381 | -moz-transform: translateY(-50%); 382 | -ms-transform: translateY(-50%); 383 | -o-transform: translateY(-50%); 384 | transform: translateY(-50%); 385 | right: 5px; 386 | } 387 | 388 | .alert-validate:hover:before { 389 | visibility: visible; 390 | opacity: 1; 391 | } 392 | 393 | @media (max-width: 992px) { 394 | .alert-validate::before { 395 | visibility: visible; 396 | opacity: 1; 397 | } 398 | } -------------------------------------------------------------------------------- /src/client/js/crypto-js/aes.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var BlockCipher = C_lib.BlockCipher; 21 | var C_algo = C.algo; 22 | 23 | // Lookup tables 24 | var SBOX = []; 25 | var INV_SBOX = []; 26 | var SUB_MIX_0 = []; 27 | var SUB_MIX_1 = []; 28 | var SUB_MIX_2 = []; 29 | var SUB_MIX_3 = []; 30 | var INV_SUB_MIX_0 = []; 31 | var INV_SUB_MIX_1 = []; 32 | var INV_SUB_MIX_2 = []; 33 | var INV_SUB_MIX_3 = []; 34 | 35 | // Compute lookup tables 36 | (function () { 37 | // Compute double table 38 | var d = []; 39 | for (var i = 0; i < 256; i++) { 40 | if (i < 128) { 41 | d[i] = i << 1; 42 | } else { 43 | d[i] = (i << 1) ^ 0x11b; 44 | } 45 | } 46 | 47 | // Walk GF(2^8) 48 | var x = 0; 49 | var xi = 0; 50 | for (var i = 0; i < 256; i++) { 51 | // Compute sbox 52 | var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); 53 | sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; 54 | SBOX[x] = sx; 55 | INV_SBOX[sx] = x; 56 | 57 | // Compute multiplication 58 | var x2 = d[x]; 59 | var x4 = d[x2]; 60 | var x8 = d[x4]; 61 | 62 | // Compute sub bytes, mix columns tables 63 | var t = (d[sx] * 0x101) ^ (sx * 0x1010100); 64 | SUB_MIX_0[x] = (t << 24) | (t >>> 8); 65 | SUB_MIX_1[x] = (t << 16) | (t >>> 16); 66 | SUB_MIX_2[x] = (t << 8) | (t >>> 24); 67 | SUB_MIX_3[x] = t; 68 | 69 | // Compute inv sub bytes, inv mix columns tables 70 | var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); 71 | INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); 72 | INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); 73 | INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); 74 | INV_SUB_MIX_3[sx] = t; 75 | 76 | // Compute next counter 77 | if (!x) { 78 | x = xi = 1; 79 | } else { 80 | x = x2 ^ d[d[d[x8 ^ x2]]]; 81 | xi ^= d[d[xi]]; 82 | } 83 | } 84 | }()); 85 | 86 | // Precomputed Rcon lookup 87 | var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; 88 | 89 | /** 90 | * AES block cipher algorithm. 91 | */ 92 | var AES = C_algo.AES = BlockCipher.extend({ 93 | _doReset: function () { 94 | // Skip reset of nRounds has been set before and key did not change 95 | if (this._nRounds && this._keyPriorReset === this._key) { 96 | return; 97 | } 98 | 99 | // Shortcuts 100 | var key = this._keyPriorReset = this._key; 101 | var keyWords = key.words; 102 | var keySize = key.sigBytes / 4; 103 | 104 | // Compute number of rounds 105 | var nRounds = this._nRounds = keySize + 6; 106 | 107 | // Compute number of key schedule rows 108 | var ksRows = (nRounds + 1) * 4; 109 | 110 | // Compute key schedule 111 | var keySchedule = this._keySchedule = []; 112 | for (var ksRow = 0; ksRow < ksRows; ksRow++) { 113 | if (ksRow < keySize) { 114 | keySchedule[ksRow] = keyWords[ksRow]; 115 | } else { 116 | var t = keySchedule[ksRow - 1]; 117 | 118 | if (!(ksRow % keySize)) { 119 | // Rot word 120 | t = (t << 8) | (t >>> 24); 121 | 122 | // Sub word 123 | t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; 124 | 125 | // Mix Rcon 126 | t ^= RCON[(ksRow / keySize) | 0] << 24; 127 | } else if (keySize > 6 && ksRow % keySize == 4) { 128 | // Sub word 129 | t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; 130 | } 131 | 132 | keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; 133 | } 134 | } 135 | 136 | // Compute inv key schedule 137 | var invKeySchedule = this._invKeySchedule = []; 138 | for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { 139 | var ksRow = ksRows - invKsRow; 140 | 141 | if (invKsRow % 4) { 142 | var t = keySchedule[ksRow]; 143 | } else { 144 | var t = keySchedule[ksRow - 4]; 145 | } 146 | 147 | if (invKsRow < 4 || ksRow <= 4) { 148 | invKeySchedule[invKsRow] = t; 149 | } else { 150 | invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ 151 | INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; 152 | } 153 | } 154 | }, 155 | 156 | encryptBlock: function (M, offset) { 157 | this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); 158 | }, 159 | 160 | decryptBlock: function (M, offset) { 161 | // Swap 2nd and 4th rows 162 | var t = M[offset + 1]; 163 | M[offset + 1] = M[offset + 3]; 164 | M[offset + 3] = t; 165 | 166 | this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); 167 | 168 | // Inv swap 2nd and 4th rows 169 | var t = M[offset + 1]; 170 | M[offset + 1] = M[offset + 3]; 171 | M[offset + 3] = t; 172 | }, 173 | 174 | _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { 175 | // Shortcut 176 | var nRounds = this._nRounds; 177 | 178 | // Get input, add round key 179 | var s0 = M[offset] ^ keySchedule[0]; 180 | var s1 = M[offset + 1] ^ keySchedule[1]; 181 | var s2 = M[offset + 2] ^ keySchedule[2]; 182 | var s3 = M[offset + 3] ^ keySchedule[3]; 183 | 184 | // Key schedule row counter 185 | var ksRow = 4; 186 | 187 | // Rounds 188 | for (var round = 1; round < nRounds; round++) { 189 | // Shift rows, sub bytes, mix columns, add round key 190 | var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; 191 | var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; 192 | var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; 193 | var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; 194 | 195 | // Update state 196 | s0 = t0; 197 | s1 = t1; 198 | s2 = t2; 199 | s3 = t3; 200 | } 201 | 202 | // Shift rows, sub bytes, add round key 203 | var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; 204 | var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; 205 | var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; 206 | var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; 207 | 208 | // Set output 209 | M[offset] = t0; 210 | M[offset + 1] = t1; 211 | M[offset + 2] = t2; 212 | M[offset + 3] = t3; 213 | }, 214 | 215 | keySize: 256/32 216 | }); 217 | 218 | /** 219 | * Shortcut functions to the cipher's object interface. 220 | * 221 | * @example 222 | * 223 | * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); 224 | * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); 225 | */ 226 | C.AES = BlockCipher._createHelper(AES); 227 | }()); 228 | 229 | 230 | return CryptoJS.AES; 231 | 232 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/x64-core.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function (undefined) { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var Base = C_lib.Base; 21 | var X32WordArray = C_lib.WordArray; 22 | 23 | /** 24 | * x64 namespace. 25 | */ 26 | var C_x64 = C.x64 = {}; 27 | 28 | /** 29 | * A 64-bit word. 30 | */ 31 | var X64Word = C_x64.Word = Base.extend({ 32 | /** 33 | * Initializes a newly created 64-bit word. 34 | * 35 | * @param {number} high The high 32 bits. 36 | * @param {number} low The low 32 bits. 37 | * 38 | * @example 39 | * 40 | * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); 41 | */ 42 | init: function (high, low) { 43 | this.high = high; 44 | this.low = low; 45 | } 46 | 47 | /** 48 | * Bitwise NOTs this word. 49 | * 50 | * @return {X64Word} A new x64-Word object after negating. 51 | * 52 | * @example 53 | * 54 | * var negated = x64Word.not(); 55 | */ 56 | // not: function () { 57 | // var high = ~this.high; 58 | // var low = ~this.low; 59 | 60 | // return X64Word.create(high, low); 61 | // }, 62 | 63 | /** 64 | * Bitwise ANDs this word with the passed word. 65 | * 66 | * @param {X64Word} word The x64-Word to AND with this word. 67 | * 68 | * @return {X64Word} A new x64-Word object after ANDing. 69 | * 70 | * @example 71 | * 72 | * var anded = x64Word.and(anotherX64Word); 73 | */ 74 | // and: function (word) { 75 | // var high = this.high & word.high; 76 | // var low = this.low & word.low; 77 | 78 | // return X64Word.create(high, low); 79 | // }, 80 | 81 | /** 82 | * Bitwise ORs this word with the passed word. 83 | * 84 | * @param {X64Word} word The x64-Word to OR with this word. 85 | * 86 | * @return {X64Word} A new x64-Word object after ORing. 87 | * 88 | * @example 89 | * 90 | * var ored = x64Word.or(anotherX64Word); 91 | */ 92 | // or: function (word) { 93 | // var high = this.high | word.high; 94 | // var low = this.low | word.low; 95 | 96 | // return X64Word.create(high, low); 97 | // }, 98 | 99 | /** 100 | * Bitwise XORs this word with the passed word. 101 | * 102 | * @param {X64Word} word The x64-Word to XOR with this word. 103 | * 104 | * @return {X64Word} A new x64-Word object after XORing. 105 | * 106 | * @example 107 | * 108 | * var xored = x64Word.xor(anotherX64Word); 109 | */ 110 | // xor: function (word) { 111 | // var high = this.high ^ word.high; 112 | // var low = this.low ^ word.low; 113 | 114 | // return X64Word.create(high, low); 115 | // }, 116 | 117 | /** 118 | * Shifts this word n bits to the left. 119 | * 120 | * @param {number} n The number of bits to shift. 121 | * 122 | * @return {X64Word} A new x64-Word object after shifting. 123 | * 124 | * @example 125 | * 126 | * var shifted = x64Word.shiftL(25); 127 | */ 128 | // shiftL: function (n) { 129 | // if (n < 32) { 130 | // var high = (this.high << n) | (this.low >>> (32 - n)); 131 | // var low = this.low << n; 132 | // } else { 133 | // var high = this.low << (n - 32); 134 | // var low = 0; 135 | // } 136 | 137 | // return X64Word.create(high, low); 138 | // }, 139 | 140 | /** 141 | * Shifts this word n bits to the right. 142 | * 143 | * @param {number} n The number of bits to shift. 144 | * 145 | * @return {X64Word} A new x64-Word object after shifting. 146 | * 147 | * @example 148 | * 149 | * var shifted = x64Word.shiftR(7); 150 | */ 151 | // shiftR: function (n) { 152 | // if (n < 32) { 153 | // var low = (this.low >>> n) | (this.high << (32 - n)); 154 | // var high = this.high >>> n; 155 | // } else { 156 | // var low = this.high >>> (n - 32); 157 | // var high = 0; 158 | // } 159 | 160 | // return X64Word.create(high, low); 161 | // }, 162 | 163 | /** 164 | * Rotates this word n bits to the left. 165 | * 166 | * @param {number} n The number of bits to rotate. 167 | * 168 | * @return {X64Word} A new x64-Word object after rotating. 169 | * 170 | * @example 171 | * 172 | * var rotated = x64Word.rotL(25); 173 | */ 174 | // rotL: function (n) { 175 | // return this.shiftL(n).or(this.shiftR(64 - n)); 176 | // }, 177 | 178 | /** 179 | * Rotates this word n bits to the right. 180 | * 181 | * @param {number} n The number of bits to rotate. 182 | * 183 | * @return {X64Word} A new x64-Word object after rotating. 184 | * 185 | * @example 186 | * 187 | * var rotated = x64Word.rotR(7); 188 | */ 189 | // rotR: function (n) { 190 | // return this.shiftR(n).or(this.shiftL(64 - n)); 191 | // }, 192 | 193 | /** 194 | * Adds this word with the passed word. 195 | * 196 | * @param {X64Word} word The x64-Word to add with this word. 197 | * 198 | * @return {X64Word} A new x64-Word object after adding. 199 | * 200 | * @example 201 | * 202 | * var added = x64Word.add(anotherX64Word); 203 | */ 204 | // add: function (word) { 205 | // var low = (this.low + word.low) | 0; 206 | // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0; 207 | // var high = (this.high + word.high + carry) | 0; 208 | 209 | // return X64Word.create(high, low); 210 | // } 211 | }); 212 | 213 | /** 214 | * An array of 64-bit words. 215 | * 216 | * @property {Array} words The array of CryptoJS.x64.Word objects. 217 | * @property {number} sigBytes The number of significant bytes in this word array. 218 | */ 219 | var X64WordArray = C_x64.WordArray = Base.extend({ 220 | /** 221 | * Initializes a newly created word array. 222 | * 223 | * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. 224 | * @param {number} sigBytes (Optional) The number of significant bytes in the words. 225 | * 226 | * @example 227 | * 228 | * var wordArray = CryptoJS.x64.WordArray.create(); 229 | * 230 | * var wordArray = CryptoJS.x64.WordArray.create([ 231 | * CryptoJS.x64.Word.create(0x00010203, 0x04050607), 232 | * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) 233 | * ]); 234 | * 235 | * var wordArray = CryptoJS.x64.WordArray.create([ 236 | * CryptoJS.x64.Word.create(0x00010203, 0x04050607), 237 | * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) 238 | * ], 10); 239 | */ 240 | init: function (words, sigBytes) { 241 | words = this.words = words || []; 242 | 243 | if (sigBytes != undefined) { 244 | this.sigBytes = sigBytes; 245 | } else { 246 | this.sigBytes = words.length * 8; 247 | } 248 | }, 249 | 250 | /** 251 | * Converts this 64-bit word array to a 32-bit word array. 252 | * 253 | * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. 254 | * 255 | * @example 256 | * 257 | * var x32WordArray = x64WordArray.toX32(); 258 | */ 259 | toX32: function () { 260 | // Shortcuts 261 | var x64Words = this.words; 262 | var x64WordsLength = x64Words.length; 263 | 264 | // Convert 265 | var x32Words = []; 266 | for (var i = 0; i < x64WordsLength; i++) { 267 | var x64Word = x64Words[i]; 268 | x32Words.push(x64Word.high); 269 | x32Words.push(x64Word.low); 270 | } 271 | 272 | return X32WordArray.create(x32Words, this.sigBytes); 273 | }, 274 | 275 | /** 276 | * Creates a copy of this word array. 277 | * 278 | * @return {X64WordArray} The clone. 279 | * 280 | * @example 281 | * 282 | * var clone = x64WordArray.clone(); 283 | */ 284 | clone: function () { 285 | var clone = Base.clone.call(this); 286 | 287 | // Clone "words" array 288 | var words = clone.words = this.words.slice(0); 289 | 290 | // Clone each X64Word object 291 | var wordsLength = words.length; 292 | for (var i = 0; i < wordsLength; i++) { 293 | words[i] = words[i].clone(); 294 | } 295 | 296 | return clone; 297 | } 298 | }); 299 | }()); 300 | 301 | 302 | return CryptoJS; 303 | 304 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/ripemd160.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | /** @preserve 17 | (c) 2012 by Cédric Mesnil. All rights reserved. 18 | 19 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 20 | 21 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 22 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | (function (Math) { 28 | // Shortcuts 29 | var C = CryptoJS; 30 | var C_lib = C.lib; 31 | var WordArray = C_lib.WordArray; 32 | var Hasher = C_lib.Hasher; 33 | var C_algo = C.algo; 34 | 35 | // Constants table 36 | var _zl = WordArray.create([ 37 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 38 | 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 39 | 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 40 | 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 41 | 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); 42 | var _zr = WordArray.create([ 43 | 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 44 | 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 45 | 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 46 | 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 47 | 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); 48 | var _sl = WordArray.create([ 49 | 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 50 | 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 51 | 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 52 | 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 53 | 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]); 54 | var _sr = WordArray.create([ 55 | 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 56 | 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 57 | 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 58 | 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 59 | 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]); 60 | 61 | var _hl = WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); 62 | var _hr = WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); 63 | 64 | /** 65 | * RIPEMD160 hash algorithm. 66 | */ 67 | var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({ 68 | _doReset: function () { 69 | this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); 70 | }, 71 | 72 | _doProcessBlock: function (M, offset) { 73 | 74 | // Swap endian 75 | for (var i = 0; i < 16; i++) { 76 | // Shortcuts 77 | var offset_i = offset + i; 78 | var M_offset_i = M[offset_i]; 79 | 80 | // Swap 81 | M[offset_i] = ( 82 | (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | 83 | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) 84 | ); 85 | } 86 | // Shortcut 87 | var H = this._hash.words; 88 | var hl = _hl.words; 89 | var hr = _hr.words; 90 | var zl = _zl.words; 91 | var zr = _zr.words; 92 | var sl = _sl.words; 93 | var sr = _sr.words; 94 | 95 | // Working variables 96 | var al, bl, cl, dl, el; 97 | var ar, br, cr, dr, er; 98 | 99 | ar = al = H[0]; 100 | br = bl = H[1]; 101 | cr = cl = H[2]; 102 | dr = dl = H[3]; 103 | er = el = H[4]; 104 | // Computation 105 | var t; 106 | for (var i = 0; i < 80; i += 1) { 107 | t = (al + M[offset+zl[i]])|0; 108 | if (i<16){ 109 | t += f1(bl,cl,dl) + hl[0]; 110 | } else if (i<32) { 111 | t += f2(bl,cl,dl) + hl[1]; 112 | } else if (i<48) { 113 | t += f3(bl,cl,dl) + hl[2]; 114 | } else if (i<64) { 115 | t += f4(bl,cl,dl) + hl[3]; 116 | } else {// if (i<80) { 117 | t += f5(bl,cl,dl) + hl[4]; 118 | } 119 | t = t|0; 120 | t = rotl(t,sl[i]); 121 | t = (t+el)|0; 122 | al = el; 123 | el = dl; 124 | dl = rotl(cl, 10); 125 | cl = bl; 126 | bl = t; 127 | 128 | t = (ar + M[offset+zr[i]])|0; 129 | if (i<16){ 130 | t += f5(br,cr,dr) + hr[0]; 131 | } else if (i<32) { 132 | t += f4(br,cr,dr) + hr[1]; 133 | } else if (i<48) { 134 | t += f3(br,cr,dr) + hr[2]; 135 | } else if (i<64) { 136 | t += f2(br,cr,dr) + hr[3]; 137 | } else {// if (i<80) { 138 | t += f1(br,cr,dr) + hr[4]; 139 | } 140 | t = t|0; 141 | t = rotl(t,sr[i]) ; 142 | t = (t+er)|0; 143 | ar = er; 144 | er = dr; 145 | dr = rotl(cr, 10); 146 | cr = br; 147 | br = t; 148 | } 149 | // Intermediate hash value 150 | t = (H[1] + cl + dr)|0; 151 | H[1] = (H[2] + dl + er)|0; 152 | H[2] = (H[3] + el + ar)|0; 153 | H[3] = (H[4] + al + br)|0; 154 | H[4] = (H[0] + bl + cr)|0; 155 | H[0] = t; 156 | }, 157 | 158 | _doFinalize: function () { 159 | // Shortcuts 160 | var data = this._data; 161 | var dataWords = data.words; 162 | 163 | var nBitsTotal = this._nDataBytes * 8; 164 | var nBitsLeft = data.sigBytes * 8; 165 | 166 | // Add padding 167 | dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); 168 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( 169 | (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) | 170 | (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) 171 | ); 172 | data.sigBytes = (dataWords.length + 1) * 4; 173 | 174 | // Hash final blocks 175 | this._process(); 176 | 177 | // Shortcuts 178 | var hash = this._hash; 179 | var H = hash.words; 180 | 181 | // Swap endian 182 | for (var i = 0; i < 5; i++) { 183 | // Shortcut 184 | var H_i = H[i]; 185 | 186 | // Swap 187 | H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | 188 | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); 189 | } 190 | 191 | // Return final computed hash 192 | return hash; 193 | }, 194 | 195 | clone: function () { 196 | var clone = Hasher.clone.call(this); 197 | clone._hash = this._hash.clone(); 198 | 199 | return clone; 200 | } 201 | }); 202 | 203 | 204 | function f1(x, y, z) { 205 | return ((x) ^ (y) ^ (z)); 206 | 207 | } 208 | 209 | function f2(x, y, z) { 210 | return (((x)&(y)) | ((~x)&(z))); 211 | } 212 | 213 | function f3(x, y, z) { 214 | return (((x) | (~(y))) ^ (z)); 215 | } 216 | 217 | function f4(x, y, z) { 218 | return (((x) & (z)) | ((y)&(~(z)))); 219 | } 220 | 221 | function f5(x, y, z) { 222 | return ((x) ^ ((y) |(~(z)))); 223 | 224 | } 225 | 226 | function rotl(x,n) { 227 | return (x<>>(32-n)); 228 | } 229 | 230 | 231 | /** 232 | * Shortcut function to the hasher's object interface. 233 | * 234 | * @param {WordArray|string} message The message to hash. 235 | * 236 | * @return {WordArray} The hash. 237 | * 238 | * @static 239 | * 240 | * @example 241 | * 242 | * var hash = CryptoJS.RIPEMD160('message'); 243 | * var hash = CryptoJS.RIPEMD160(wordArray); 244 | */ 245 | C.RIPEMD160 = Hasher._createHelper(RIPEMD160); 246 | 247 | /** 248 | * Shortcut function to the HMAC's object interface. 249 | * 250 | * @param {WordArray|string} message The message to hash. 251 | * @param {WordArray|string} key The secret key. 252 | * 253 | * @return {WordArray} The HMAC. 254 | * 255 | * @static 256 | * 257 | * @example 258 | * 259 | * var hmac = CryptoJS.HmacRIPEMD160(message, key); 260 | */ 261 | C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160); 262 | }(Math)); 263 | 264 | 265 | return CryptoJS.RIPEMD160; 266 | 267 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/md5.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function (Math) { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var WordArray = C_lib.WordArray; 21 | var Hasher = C_lib.Hasher; 22 | var C_algo = C.algo; 23 | 24 | // Constants table 25 | var T = []; 26 | 27 | // Compute constants 28 | (function () { 29 | for (var i = 0; i < 64; i++) { 30 | T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; 31 | } 32 | }()); 33 | 34 | /** 35 | * MD5 hash algorithm. 36 | */ 37 | var MD5 = C_algo.MD5 = Hasher.extend({ 38 | _doReset: function () { 39 | this._hash = new WordArray.init([ 40 | 0x67452301, 0xefcdab89, 41 | 0x98badcfe, 0x10325476 42 | ]); 43 | }, 44 | 45 | _doProcessBlock: function (M, offset) { 46 | // Swap endian 47 | for (var i = 0; i < 16; i++) { 48 | // Shortcuts 49 | var offset_i = offset + i; 50 | var M_offset_i = M[offset_i]; 51 | 52 | M[offset_i] = ( 53 | (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | 54 | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) 55 | ); 56 | } 57 | 58 | // Shortcuts 59 | var H = this._hash.words; 60 | 61 | var M_offset_0 = M[offset + 0]; 62 | var M_offset_1 = M[offset + 1]; 63 | var M_offset_2 = M[offset + 2]; 64 | var M_offset_3 = M[offset + 3]; 65 | var M_offset_4 = M[offset + 4]; 66 | var M_offset_5 = M[offset + 5]; 67 | var M_offset_6 = M[offset + 6]; 68 | var M_offset_7 = M[offset + 7]; 69 | var M_offset_8 = M[offset + 8]; 70 | var M_offset_9 = M[offset + 9]; 71 | var M_offset_10 = M[offset + 10]; 72 | var M_offset_11 = M[offset + 11]; 73 | var M_offset_12 = M[offset + 12]; 74 | var M_offset_13 = M[offset + 13]; 75 | var M_offset_14 = M[offset + 14]; 76 | var M_offset_15 = M[offset + 15]; 77 | 78 | // Working varialbes 79 | var a = H[0]; 80 | var b = H[1]; 81 | var c = H[2]; 82 | var d = H[3]; 83 | 84 | // Computation 85 | a = FF(a, b, c, d, M_offset_0, 7, T[0]); 86 | d = FF(d, a, b, c, M_offset_1, 12, T[1]); 87 | c = FF(c, d, a, b, M_offset_2, 17, T[2]); 88 | b = FF(b, c, d, a, M_offset_3, 22, T[3]); 89 | a = FF(a, b, c, d, M_offset_4, 7, T[4]); 90 | d = FF(d, a, b, c, M_offset_5, 12, T[5]); 91 | c = FF(c, d, a, b, M_offset_6, 17, T[6]); 92 | b = FF(b, c, d, a, M_offset_7, 22, T[7]); 93 | a = FF(a, b, c, d, M_offset_8, 7, T[8]); 94 | d = FF(d, a, b, c, M_offset_9, 12, T[9]); 95 | c = FF(c, d, a, b, M_offset_10, 17, T[10]); 96 | b = FF(b, c, d, a, M_offset_11, 22, T[11]); 97 | a = FF(a, b, c, d, M_offset_12, 7, T[12]); 98 | d = FF(d, a, b, c, M_offset_13, 12, T[13]); 99 | c = FF(c, d, a, b, M_offset_14, 17, T[14]); 100 | b = FF(b, c, d, a, M_offset_15, 22, T[15]); 101 | 102 | a = GG(a, b, c, d, M_offset_1, 5, T[16]); 103 | d = GG(d, a, b, c, M_offset_6, 9, T[17]); 104 | c = GG(c, d, a, b, M_offset_11, 14, T[18]); 105 | b = GG(b, c, d, a, M_offset_0, 20, T[19]); 106 | a = GG(a, b, c, d, M_offset_5, 5, T[20]); 107 | d = GG(d, a, b, c, M_offset_10, 9, T[21]); 108 | c = GG(c, d, a, b, M_offset_15, 14, T[22]); 109 | b = GG(b, c, d, a, M_offset_4, 20, T[23]); 110 | a = GG(a, b, c, d, M_offset_9, 5, T[24]); 111 | d = GG(d, a, b, c, M_offset_14, 9, T[25]); 112 | c = GG(c, d, a, b, M_offset_3, 14, T[26]); 113 | b = GG(b, c, d, a, M_offset_8, 20, T[27]); 114 | a = GG(a, b, c, d, M_offset_13, 5, T[28]); 115 | d = GG(d, a, b, c, M_offset_2, 9, T[29]); 116 | c = GG(c, d, a, b, M_offset_7, 14, T[30]); 117 | b = GG(b, c, d, a, M_offset_12, 20, T[31]); 118 | 119 | a = HH(a, b, c, d, M_offset_5, 4, T[32]); 120 | d = HH(d, a, b, c, M_offset_8, 11, T[33]); 121 | c = HH(c, d, a, b, M_offset_11, 16, T[34]); 122 | b = HH(b, c, d, a, M_offset_14, 23, T[35]); 123 | a = HH(a, b, c, d, M_offset_1, 4, T[36]); 124 | d = HH(d, a, b, c, M_offset_4, 11, T[37]); 125 | c = HH(c, d, a, b, M_offset_7, 16, T[38]); 126 | b = HH(b, c, d, a, M_offset_10, 23, T[39]); 127 | a = HH(a, b, c, d, M_offset_13, 4, T[40]); 128 | d = HH(d, a, b, c, M_offset_0, 11, T[41]); 129 | c = HH(c, d, a, b, M_offset_3, 16, T[42]); 130 | b = HH(b, c, d, a, M_offset_6, 23, T[43]); 131 | a = HH(a, b, c, d, M_offset_9, 4, T[44]); 132 | d = HH(d, a, b, c, M_offset_12, 11, T[45]); 133 | c = HH(c, d, a, b, M_offset_15, 16, T[46]); 134 | b = HH(b, c, d, a, M_offset_2, 23, T[47]); 135 | 136 | a = II(a, b, c, d, M_offset_0, 6, T[48]); 137 | d = II(d, a, b, c, M_offset_7, 10, T[49]); 138 | c = II(c, d, a, b, M_offset_14, 15, T[50]); 139 | b = II(b, c, d, a, M_offset_5, 21, T[51]); 140 | a = II(a, b, c, d, M_offset_12, 6, T[52]); 141 | d = II(d, a, b, c, M_offset_3, 10, T[53]); 142 | c = II(c, d, a, b, M_offset_10, 15, T[54]); 143 | b = II(b, c, d, a, M_offset_1, 21, T[55]); 144 | a = II(a, b, c, d, M_offset_8, 6, T[56]); 145 | d = II(d, a, b, c, M_offset_15, 10, T[57]); 146 | c = II(c, d, a, b, M_offset_6, 15, T[58]); 147 | b = II(b, c, d, a, M_offset_13, 21, T[59]); 148 | a = II(a, b, c, d, M_offset_4, 6, T[60]); 149 | d = II(d, a, b, c, M_offset_11, 10, T[61]); 150 | c = II(c, d, a, b, M_offset_2, 15, T[62]); 151 | b = II(b, c, d, a, M_offset_9, 21, T[63]); 152 | 153 | // Intermediate hash value 154 | H[0] = (H[0] + a) | 0; 155 | H[1] = (H[1] + b) | 0; 156 | H[2] = (H[2] + c) | 0; 157 | H[3] = (H[3] + d) | 0; 158 | }, 159 | 160 | _doFinalize: function () { 161 | // Shortcuts 162 | var data = this._data; 163 | var dataWords = data.words; 164 | 165 | var nBitsTotal = this._nDataBytes * 8; 166 | var nBitsLeft = data.sigBytes * 8; 167 | 168 | // Add padding 169 | dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); 170 | 171 | var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); 172 | var nBitsTotalL = nBitsTotal; 173 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( 174 | (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | 175 | (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) 176 | ); 177 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( 178 | (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | 179 | (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) 180 | ); 181 | 182 | data.sigBytes = (dataWords.length + 1) * 4; 183 | 184 | // Hash final blocks 185 | this._process(); 186 | 187 | // Shortcuts 188 | var hash = this._hash; 189 | var H = hash.words; 190 | 191 | // Swap endian 192 | for (var i = 0; i < 4; i++) { 193 | // Shortcut 194 | var H_i = H[i]; 195 | 196 | H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | 197 | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); 198 | } 199 | 200 | // Return final computed hash 201 | return hash; 202 | }, 203 | 204 | clone: function () { 205 | var clone = Hasher.clone.call(this); 206 | clone._hash = this._hash.clone(); 207 | 208 | return clone; 209 | } 210 | }); 211 | 212 | function FF(a, b, c, d, x, s, t) { 213 | var n = a + ((b & c) | (~b & d)) + x + t; 214 | return ((n << s) | (n >>> (32 - s))) + b; 215 | } 216 | 217 | function GG(a, b, c, d, x, s, t) { 218 | var n = a + ((b & d) | (c & ~d)) + x + t; 219 | return ((n << s) | (n >>> (32 - s))) + b; 220 | } 221 | 222 | function HH(a, b, c, d, x, s, t) { 223 | var n = a + (b ^ c ^ d) + x + t; 224 | return ((n << s) | (n >>> (32 - s))) + b; 225 | } 226 | 227 | function II(a, b, c, d, x, s, t) { 228 | var n = a + (c ^ (b | ~d)) + x + t; 229 | return ((n << s) | (n >>> (32 - s))) + b; 230 | } 231 | 232 | /** 233 | * Shortcut function to the hasher's object interface. 234 | * 235 | * @param {WordArray|string} message The message to hash. 236 | * 237 | * @return {WordArray} The hash. 238 | * 239 | * @static 240 | * 241 | * @example 242 | * 243 | * var hash = CryptoJS.MD5('message'); 244 | * var hash = CryptoJS.MD5(wordArray); 245 | */ 246 | C.MD5 = Hasher._createHelper(MD5); 247 | 248 | /** 249 | * Shortcut function to the HMAC's object interface. 250 | * 251 | * @param {WordArray|string} message The message to hash. 252 | * @param {WordArray|string} key The secret key. 253 | * 254 | * @return {WordArray} The HMAC. 255 | * 256 | * @static 257 | * 258 | * @example 259 | * 260 | * var hmac = CryptoJS.HmacMD5(message, key); 261 | */ 262 | C.HmacMD5 = Hasher._createHmacHelper(MD5); 263 | }(Math)); 264 | 265 | 266 | return CryptoJS.MD5; 267 | 268 | })); -------------------------------------------------------------------------------- /src/client/js/crypto-js/sha3.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./x64-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./x64-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function (Math) { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var WordArray = C_lib.WordArray; 21 | var Hasher = C_lib.Hasher; 22 | var C_x64 = C.x64; 23 | var X64Word = C_x64.Word; 24 | var C_algo = C.algo; 25 | 26 | // Constants tables 27 | var RHO_OFFSETS = []; 28 | var PI_INDEXES = []; 29 | var ROUND_CONSTANTS = []; 30 | 31 | // Compute Constants 32 | (function () { 33 | // Compute rho offset constants 34 | var x = 1, y = 0; 35 | for (var t = 0; t < 24; t++) { 36 | RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64; 37 | 38 | var newX = y % 5; 39 | var newY = (2 * x + 3 * y) % 5; 40 | x = newX; 41 | y = newY; 42 | } 43 | 44 | // Compute pi index constants 45 | for (var x = 0; x < 5; x++) { 46 | for (var y = 0; y < 5; y++) { 47 | PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; 48 | } 49 | } 50 | 51 | // Compute round constants 52 | var LFSR = 0x01; 53 | for (var i = 0; i < 24; i++) { 54 | var roundConstantMsw = 0; 55 | var roundConstantLsw = 0; 56 | 57 | for (var j = 0; j < 7; j++) { 58 | if (LFSR & 0x01) { 59 | var bitPosition = (1 << j) - 1; 60 | if (bitPosition < 32) { 61 | roundConstantLsw ^= 1 << bitPosition; 62 | } else /* if (bitPosition >= 32) */ { 63 | roundConstantMsw ^= 1 << (bitPosition - 32); 64 | } 65 | } 66 | 67 | // Compute next LFSR 68 | if (LFSR & 0x80) { 69 | // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 70 | LFSR = (LFSR << 1) ^ 0x71; 71 | } else { 72 | LFSR <<= 1; 73 | } 74 | } 75 | 76 | ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); 77 | } 78 | }()); 79 | 80 | // Reusable objects for temporary values 81 | var T = []; 82 | (function () { 83 | for (var i = 0; i < 25; i++) { 84 | T[i] = X64Word.create(); 85 | } 86 | }()); 87 | 88 | /** 89 | * SHA-3 hash algorithm. 90 | */ 91 | var SHA3 = C_algo.SHA3 = Hasher.extend({ 92 | /** 93 | * Configuration options. 94 | * 95 | * @property {number} outputLength 96 | * The desired number of bits in the output hash. 97 | * Only values permitted are: 224, 256, 384, 512. 98 | * Default: 512 99 | */ 100 | cfg: Hasher.cfg.extend({ 101 | outputLength: 512 102 | }), 103 | 104 | _doReset: function () { 105 | var state = this._state = [] 106 | for (var i = 0; i < 25; i++) { 107 | state[i] = new X64Word.init(); 108 | } 109 | 110 | this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; 111 | }, 112 | 113 | _doProcessBlock: function (M, offset) { 114 | // Shortcuts 115 | var state = this._state; 116 | var nBlockSizeLanes = this.blockSize / 2; 117 | 118 | // Absorb 119 | for (var i = 0; i < nBlockSizeLanes; i++) { 120 | // Shortcuts 121 | var M2i = M[offset + 2 * i]; 122 | var M2i1 = M[offset + 2 * i + 1]; 123 | 124 | // Swap endian 125 | M2i = ( 126 | (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) | 127 | (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00) 128 | ); 129 | M2i1 = ( 130 | (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) | 131 | (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00) 132 | ); 133 | 134 | // Absorb message into state 135 | var lane = state[i]; 136 | lane.high ^= M2i1; 137 | lane.low ^= M2i; 138 | } 139 | 140 | // Rounds 141 | for (var round = 0; round < 24; round++) { 142 | // Theta 143 | for (var x = 0; x < 5; x++) { 144 | // Mix column lanes 145 | var tMsw = 0, tLsw = 0; 146 | for (var y = 0; y < 5; y++) { 147 | var lane = state[x + 5 * y]; 148 | tMsw ^= lane.high; 149 | tLsw ^= lane.low; 150 | } 151 | 152 | // Temporary values 153 | var Tx = T[x]; 154 | Tx.high = tMsw; 155 | Tx.low = tLsw; 156 | } 157 | for (var x = 0; x < 5; x++) { 158 | // Shortcuts 159 | var Tx4 = T[(x + 4) % 5]; 160 | var Tx1 = T[(x + 1) % 5]; 161 | var Tx1Msw = Tx1.high; 162 | var Tx1Lsw = Tx1.low; 163 | 164 | // Mix surrounding columns 165 | var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); 166 | var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); 167 | for (var y = 0; y < 5; y++) { 168 | var lane = state[x + 5 * y]; 169 | lane.high ^= tMsw; 170 | lane.low ^= tLsw; 171 | } 172 | } 173 | 174 | // Rho Pi 175 | for (var laneIndex = 1; laneIndex < 25; laneIndex++) { 176 | // Shortcuts 177 | var lane = state[laneIndex]; 178 | var laneMsw = lane.high; 179 | var laneLsw = lane.low; 180 | var rhoOffset = RHO_OFFSETS[laneIndex]; 181 | 182 | // Rotate lanes 183 | if (rhoOffset < 32) { 184 | var tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); 185 | var tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); 186 | } else /* if (rhoOffset >= 32) */ { 187 | var tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); 188 | var tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); 189 | } 190 | 191 | // Transpose lanes 192 | var TPiLane = T[PI_INDEXES[laneIndex]]; 193 | TPiLane.high = tMsw; 194 | TPiLane.low = tLsw; 195 | } 196 | 197 | // Rho pi at x = y = 0 198 | var T0 = T[0]; 199 | var state0 = state[0]; 200 | T0.high = state0.high; 201 | T0.low = state0.low; 202 | 203 | // Chi 204 | for (var x = 0; x < 5; x++) { 205 | for (var y = 0; y < 5; y++) { 206 | // Shortcuts 207 | var laneIndex = x + 5 * y; 208 | var lane = state[laneIndex]; 209 | var TLane = T[laneIndex]; 210 | var Tx1Lane = T[((x + 1) % 5) + 5 * y]; 211 | var Tx2Lane = T[((x + 2) % 5) + 5 * y]; 212 | 213 | // Mix rows 214 | lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); 215 | lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); 216 | } 217 | } 218 | 219 | // Iota 220 | var lane = state[0]; 221 | var roundConstant = ROUND_CONSTANTS[round]; 222 | lane.high ^= roundConstant.high; 223 | lane.low ^= roundConstant.low;; 224 | } 225 | }, 226 | 227 | _doFinalize: function () { 228 | // Shortcuts 229 | var data = this._data; 230 | var dataWords = data.words; 231 | var nBitsTotal = this._nDataBytes * 8; 232 | var nBitsLeft = data.sigBytes * 8; 233 | var blockSizeBits = this.blockSize * 32; 234 | 235 | // Add padding 236 | dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32); 237 | dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; 238 | data.sigBytes = dataWords.length * 4; 239 | 240 | // Hash final blocks 241 | this._process(); 242 | 243 | // Shortcuts 244 | var state = this._state; 245 | var outputLengthBytes = this.cfg.outputLength / 8; 246 | var outputLengthLanes = outputLengthBytes / 8; 247 | 248 | // Squeeze 249 | var hashWords = []; 250 | for (var i = 0; i < outputLengthLanes; i++) { 251 | // Shortcuts 252 | var lane = state[i]; 253 | var laneMsw = lane.high; 254 | var laneLsw = lane.low; 255 | 256 | // Swap endian 257 | laneMsw = ( 258 | (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) | 259 | (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00) 260 | ); 261 | laneLsw = ( 262 | (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) | 263 | (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00) 264 | ); 265 | 266 | // Squeeze state to retrieve hash 267 | hashWords.push(laneLsw); 268 | hashWords.push(laneMsw); 269 | } 270 | 271 | // Return final computed hash 272 | return new WordArray.init(hashWords, outputLengthBytes); 273 | }, 274 | 275 | clone: function () { 276 | var clone = Hasher.clone.call(this); 277 | 278 | var state = clone._state = this._state.slice(0); 279 | for (var i = 0; i < 25; i++) { 280 | state[i] = state[i].clone(); 281 | } 282 | 283 | return clone; 284 | } 285 | }); 286 | 287 | /** 288 | * Shortcut function to the hasher's object interface. 289 | * 290 | * @param {WordArray|string} message The message to hash. 291 | * 292 | * @return {WordArray} The hash. 293 | * 294 | * @static 295 | * 296 | * @example 297 | * 298 | * var hash = CryptoJS.SHA3('message'); 299 | * var hash = CryptoJS.SHA3(wordArray); 300 | */ 301 | C.SHA3 = Hasher._createHelper(SHA3); 302 | 303 | /** 304 | * Shortcut function to the HMAC's object interface. 305 | * 306 | * @param {WordArray|string} message The message to hash. 307 | * @param {WordArray|string} key The secret key. 308 | * 309 | * @return {WordArray} The HMAC. 310 | * 311 | * @static 312 | * 313 | * @example 314 | * 315 | * var hmac = CryptoJS.HmacSHA3(message, key); 316 | */ 317 | C.HmacSHA3 = Hasher._createHmacHelper(SHA3); 318 | }(Math)); 319 | 320 | 321 | return CryptoJS.SHA3; 322 | 323 | })); -------------------------------------------------------------------------------- /src/server/server.js: -------------------------------------------------------------------------------- 1 | // This file is required by app.js. It sets up event listeners 2 | // and listens for socket.io messages. 3 | "use strict"; 4 | 5 | // Socket.io channels: 6 | // connection on new socket creatation 7 | // disconnect on lost user socket 8 | // error on system error 9 | // login on user request to login by user and password 10 | // signed on user successfull signed in to application 11 | // update on update users and channels list to all users 12 | // msg on send or receive message in channel 13 | // exception on get an error to users 14 | // typing on a user typing some thing in message text box 15 | // resign on user sign-in expiration 16 | 17 | // Use the gravatar module, to turn email addresses into avatar images: 18 | var gravatar = require('gravatar'); 19 | var manager = require('./manager.js'); 20 | var crypto = require("crypto-js"); 21 | var serverVersion = manager.generateGuid(); // a unique version for every startup of server 22 | var globalChannel = "environment"; // add any authenticated user to this channel 23 | var chat = {}; // socket.io 24 | var loginExpireTime = 3600 * 1000; // 3600sec 25 | 26 | // Export a function, so that we can pass 27 | // the app and io instances from the app.js file: 28 | module.exports = function (app, io) { 29 | // Initialize a new socket.io application, named 'chat' 30 | chat = io; 31 | io.on('connection', function (socket) { 32 | console.info(`socket: ${socket.id} connected`); 33 | 34 | // When the client emits 'login', save his name and avatar, 35 | // and add them to the channel 36 | socket.on('login', data => { 37 | // check login password from decrypt cipher by nonce password (socket.id) 38 | var userHashedPass = crypto.TripleDES.decrypt(data.password, socket.id).toString(crypto.enc.Utf8); 39 | 40 | var user = manager.clients[data.email.hashCode()]; 41 | if (user) { // exist user 42 | if (user.password == userHashedPass) { 43 | // check user sign expiration 44 | if (user.lastLoginDate + loginExpireTime > Date.now()) { // expire after 60min 45 | userSigned(user, socket); 46 | } 47 | else { 48 | socket.emit("resign"); 49 | } 50 | user.lastLoginDate = Date.now(); // update user login time 51 | } 52 | else { // exist user, entry password is incorrect 53 | socket.emit("exception", "The username or password is incorrect!"); 54 | console.info(`User <${user.username}> can't login, because that password is incorrect!`); 55 | } 56 | } 57 | else { // new user 58 | // Use the socket object to store data. Each client gets 59 | // their own unique socket object 60 | var user = { 61 | "socketid": socket.id, // just solid for this connection and changed for another connecting times 62 | "id": data.email.hashCode(), // unique for this email 63 | "username": data.username, // display name, maybe not unique 64 | "email": data.email, // unique email address for any users 65 | "password": userHashedPass, // Store Password Hashing for client login to authenticate one user per email 66 | "avatar": gravatar.url(data.email, { s: '140', r: 'x', d: 'mm' }), // user avatar picture's 67 | "status": "online", // { "online", "offline" } 68 | "lastLoginDate": Date.now() // last login time accourding by server time 69 | }; 70 | manager.clients[user.id] = user; 71 | userSigned(user, socket); 72 | } 73 | }); // login 74 | 75 | }); // connected user - socket scope 76 | 77 | } // module.export func 78 | 79 | 80 | function userSigned(user, socket) { 81 | user.status = "online"; 82 | user.socketid = socket.id; 83 | socket.user = user; 84 | // 85 | // send success ack to user by self data object 86 | socket.emit("signed", { 87 | "id": user.id, 88 | "username": user.username, 89 | "email": user.email, 90 | "avatar": user.avatar, 91 | "status": user.status, 92 | "serverVersion": serverVersion, // chance of this version caused to refresh clients cached data 93 | }); 94 | 95 | socket.join(globalChannel); // join all users in global authenticated group 96 | 97 | // add user to all joined channels 98 | var userChannels = manager.getUserChannels(user.id, true); // by p2p channel 99 | for (var channel in userChannels) { 100 | socket.join(channel); 101 | } 102 | 103 | updateAllUsers(); 104 | defineSocketEvents(socket); 105 | 106 | console.info(`User <${user.username}> by socket <${user.socketid}> connected`) 107 | } // signed-in 108 | 109 | function updateAllUsers() { 110 | // tell new user added and list updated to everyone except the socket that starts it 111 | chat.sockets.in(globalChannel).emit("update", { users: manager.getUsers(), channels: manager.getChannels() }); 112 | } 113 | 114 | function createChannel(name, user, p2p) { 115 | var channel = { name: name, p2p: p2p, adminUserId: user.id, status: "online", users: [user.id] }; 116 | manager.channels[name] = channel; 117 | chat.sockets.connected[user.socketid].join(name); // add admin to self chat 118 | return channel; 119 | } 120 | 121 | function defineSocketEvents(socket) { 122 | 123 | // Somebody left the chat 124 | socket.on('disconnect', () => { 125 | // Upon disconnection, sockets leave all the channels they were part of automatically, 126 | // and no special teardown is needed on this part. 127 | 128 | // find user who abandon sockets 129 | var user = socket.user || manager.findUser(socket.id); 130 | if (user) { 131 | console.warn(`User <${user.username}> by socket <${user.socketid}> disconnected!`); 132 | user.status = "offline"; 133 | 134 | // Notify the other person in the chat channel 135 | // that his partner has left 136 | socket.broadcast.to(globalChannel).emit('leave', 137 | { username: user.username, id: user.id, avatar: user.avatar, status: user.status }); 138 | } 139 | }); 140 | 141 | // Handle the sending of messages 142 | socket.on("msg", data => { 143 | var from = socket.user || manager.findUser(socket.id); 144 | var channel = manager.channels[data.to]; 145 | 146 | if (from != null && channel != null && channel.users.indexOf(from.id) != -1) { 147 | var msg = manager.messages[channel.name]; 148 | if (msg == null) 149 | msg = manager.messages[channel.name] = []; 150 | 151 | data.date = Date.now(); 152 | data.type = "msg"; 153 | // When the server receives a message, it sends it to the all clients, so also to sender 154 | chat.sockets.in(channel.name).emit('receive', data); 155 | msg.push(data); 156 | } 157 | }); 158 | 159 | // Handle the request of users for chat 160 | socket.on("request", data => { 161 | 162 | // find user who requested to this chat by socket id 163 | var from = socket.user || manager.findUser(socket.id); 164 | 165 | // if user authenticated 166 | if (from) { 167 | data.from = from.id; // inject user id in data 168 | 169 | // find admin user who should be send request to 170 | var adminUser = manager.getAdminFromChannelName(data.channel, from.id) 171 | 172 | if (adminUser) { 173 | if (adminUser.status == "offline") { 174 | var p2p = (manager.channels[data.channel] == null ? true : manager.channels[data.channel].p2p); 175 | socket.emit("reject", { from: adminUser.id, channel: data.channel, p2p: p2p, msg: "admin user is offline" }); 176 | } 177 | else 178 | chat.to(adminUser.socketid).emit("request", data) 179 | return; 180 | } 181 | } 182 | // 183 | // from or adminUser is null 184 | socket.emit("exception", "The requested chat not found!"); 185 | }); 186 | 187 | // Handle the request of users for chat 188 | socket.on("accept", data => { 189 | 190 | // find user who accepted to this chat by socket id 191 | var from = socket.user || manager.findUser(socket.id); 192 | 193 | // find user who is target user by user id 194 | var to = manager.clients[data.to]; 195 | 196 | // if users authenticated 197 | if (from != null && to != null) { 198 | var channel = manager.channels[data.channel]; 199 | 200 | if (channel == null) { 201 | // new p2p channel 202 | channel = createChannel(data.channel, from, true) 203 | } 204 | // 205 | // add new user to this channel 206 | channel.users.push(to.id); 207 | chat.sockets.connected[to.socketid].join(channel.name); // add new user to chat channel 208 | 209 | // send accept msg to user which requested to chat 210 | socket.to(to.socketid).emit("accept", { from: from.id, channel: channel.name, p2p: channel.p2p, channelKey: data.channelKey }) 211 | } 212 | }); 213 | 214 | // Handle the request to create channel 215 | socket.on("createChannel", name => { 216 | var from = socket.user; 217 | var channel = manager.channels[name]; 218 | 219 | if (channel) { 220 | // the given channel name is already exist! 221 | socket.emit("reject", { from: from.id, p2p: false, channel: channel, msg: "The given channel name is already exist" }) 222 | return; 223 | } 224 | 225 | // create new channel 226 | channel = createChannel(name, from, false); 227 | updateAllUsers(); 228 | 229 | console.info(`Channel <${channel.name}> created by user <${from.username}: ${channel.adminUserId}>`) 230 | }); 231 | 232 | 233 | // Handle the request of users for chat 234 | socket.on("reject", data => { 235 | 236 | // find user who accepted to this chat by socket id 237 | var from = socket.user || manager.findUser(socket.id); 238 | 239 | // find user who is target user by user id 240 | var to = manager.clients[data.to]; 241 | 242 | // if users authenticated 243 | if (from != null && to != null) { 244 | var channel = manager.channels[data.channel]; 245 | socket.to(to.socketid).emit("reject", { from: from.id, p2p: (channel == null), channel: data.channel }) 246 | } 247 | }); 248 | 249 | // Handle the request of users for chat 250 | socket.on("fetch-messages", channelName => { 251 | // find fetcher user 252 | var fetcher = socket.user || manager.findUser(socket.id); 253 | 254 | var channel = manager.channels[channelName]; 255 | 256 | // check fetcher was a user of channel 257 | if (fetcher != null && channel != null && channel.users.indexOf(fetcher.id) !== -1) 258 | socket.emit("fetch-messages", { channel: channel.name, messages: manager.messages[channel.name] }); 259 | else 260 | socket.emit("exception", `you are not joined in <${channelName}> channel or maybe the server was lost your data!!!`); 261 | }); 262 | 263 | socket.on("typing", channelName => { 264 | var user = socket.user || manager.findUser(socket.id); 265 | var channel = manager.channels[channelName]; 266 | 267 | if (user && channel && channel.users.indexOf(user.id) !== -1) { 268 | chat.sockets.in(channel.name).emit("typing", { channel: channel.name, user: user.id }); 269 | } 270 | }); 271 | 272 | } // defineSocketEvents -------------------------------------------------------------------------------- /src/client/js/crypto-js/sha512.js: -------------------------------------------------------------------------------- 1 | ;(function (root, factory, undef) { 2 | if (typeof exports === "object") { 3 | // CommonJS 4 | module.exports = exports = factory(require("./core"), require("./x64-core")); 5 | } 6 | else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(["./core", "./x64-core"], factory); 9 | } 10 | else { 11 | // Global (browser) 12 | factory(root.CryptoJS); 13 | } 14 | }(this, function (CryptoJS) { 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = CryptoJS; 19 | var C_lib = C.lib; 20 | var Hasher = C_lib.Hasher; 21 | var C_x64 = C.x64; 22 | var X64Word = C_x64.Word; 23 | var X64WordArray = C_x64.WordArray; 24 | var C_algo = C.algo; 25 | 26 | function X64Word_create() { 27 | return X64Word.create.apply(X64Word, arguments); 28 | } 29 | 30 | // Constants 31 | var K = [ 32 | X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd), 33 | X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc), 34 | X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019), 35 | X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118), 36 | X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe), 37 | X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2), 38 | X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1), 39 | X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694), 40 | X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3), 41 | X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65), 42 | X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483), 43 | X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5), 44 | X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210), 45 | X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4), 46 | X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725), 47 | X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70), 48 | X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926), 49 | X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df), 50 | X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8), 51 | X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b), 52 | X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001), 53 | X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30), 54 | X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910), 55 | X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8), 56 | X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53), 57 | X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8), 58 | X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb), 59 | X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3), 60 | X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60), 61 | X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec), 62 | X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9), 63 | X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b), 64 | X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207), 65 | X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178), 66 | X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6), 67 | X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b), 68 | X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493), 69 | X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c), 70 | X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a), 71 | X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817) 72 | ]; 73 | 74 | // Reusable objects 75 | var W = []; 76 | (function () { 77 | for (var i = 0; i < 80; i++) { 78 | W[i] = X64Word_create(); 79 | } 80 | }()); 81 | 82 | /** 83 | * SHA-512 hash algorithm. 84 | */ 85 | var SHA512 = C_algo.SHA512 = Hasher.extend({ 86 | _doReset: function () { 87 | this._hash = new X64WordArray.init([ 88 | new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b), 89 | new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1), 90 | new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f), 91 | new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179) 92 | ]); 93 | }, 94 | 95 | _doProcessBlock: function (M, offset) { 96 | // Shortcuts 97 | var H = this._hash.words; 98 | 99 | var H0 = H[0]; 100 | var H1 = H[1]; 101 | var H2 = H[2]; 102 | var H3 = H[3]; 103 | var H4 = H[4]; 104 | var H5 = H[5]; 105 | var H6 = H[6]; 106 | var H7 = H[7]; 107 | 108 | var H0h = H0.high; 109 | var H0l = H0.low; 110 | var H1h = H1.high; 111 | var H1l = H1.low; 112 | var H2h = H2.high; 113 | var H2l = H2.low; 114 | var H3h = H3.high; 115 | var H3l = H3.low; 116 | var H4h = H4.high; 117 | var H4l = H4.low; 118 | var H5h = H5.high; 119 | var H5l = H5.low; 120 | var H6h = H6.high; 121 | var H6l = H6.low; 122 | var H7h = H7.high; 123 | var H7l = H7.low; 124 | 125 | // Working variables 126 | var ah = H0h; 127 | var al = H0l; 128 | var bh = H1h; 129 | var bl = H1l; 130 | var ch = H2h; 131 | var cl = H2l; 132 | var dh = H3h; 133 | var dl = H3l; 134 | var eh = H4h; 135 | var el = H4l; 136 | var fh = H5h; 137 | var fl = H5l; 138 | var gh = H6h; 139 | var gl = H6l; 140 | var hh = H7h; 141 | var hl = H7l; 142 | 143 | // Rounds 144 | for (var i = 0; i < 80; i++) { 145 | // Shortcut 146 | var Wi = W[i]; 147 | 148 | // Extend message 149 | if (i < 16) { 150 | var Wih = Wi.high = M[offset + i * 2] | 0; 151 | var Wil = Wi.low = M[offset + i * 2 + 1] | 0; 152 | } else { 153 | // Gamma0 154 | var gamma0x = W[i - 15]; 155 | var gamma0xh = gamma0x.high; 156 | var gamma0xl = gamma0x.low; 157 | var gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7); 158 | var gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); 159 | 160 | // Gamma1 161 | var gamma1x = W[i - 2]; 162 | var gamma1xh = gamma1x.high; 163 | var gamma1xl = gamma1x.low; 164 | var gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6); 165 | var gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); 166 | 167 | // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] 168 | var Wi7 = W[i - 7]; 169 | var Wi7h = Wi7.high; 170 | var Wi7l = Wi7.low; 171 | 172 | var Wi16 = W[i - 16]; 173 | var Wi16h = Wi16.high; 174 | var Wi16l = Wi16.low; 175 | 176 | var Wil = gamma0l + Wi7l; 177 | var Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); 178 | var Wil = Wil + gamma1l; 179 | var Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); 180 | var Wil = Wil + Wi16l; 181 | var Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); 182 | 183 | Wi.high = Wih; 184 | Wi.low = Wil; 185 | } 186 | 187 | var chh = (eh & fh) ^ (~eh & gh); 188 | var chl = (el & fl) ^ (~el & gl); 189 | var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); 190 | var majl = (al & bl) ^ (al & cl) ^ (bl & cl); 191 | 192 | var sigma0h = ((ah >>> 28) | (al << 4)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7)); 193 | var sigma0l = ((al >>> 28) | (ah << 4)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7)); 194 | var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9)); 195 | var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9)); 196 | 197 | // t1 = h + sigma1 + ch + K[i] + W[i] 198 | var Ki = K[i]; 199 | var Kih = Ki.high; 200 | var Kil = Ki.low; 201 | 202 | var t1l = hl + sigma1l; 203 | var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); 204 | var t1l = t1l + chl; 205 | var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); 206 | var t1l = t1l + Kil; 207 | var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); 208 | var t1l = t1l + Wil; 209 | var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); 210 | 211 | // t2 = sigma0 + maj 212 | var t2l = sigma0l + majl; 213 | var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); 214 | 215 | // Update working variables 216 | hh = gh; 217 | hl = gl; 218 | gh = fh; 219 | gl = fl; 220 | fh = eh; 221 | fl = el; 222 | el = (dl + t1l) | 0; 223 | eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; 224 | dh = ch; 225 | dl = cl; 226 | ch = bh; 227 | cl = bl; 228 | bh = ah; 229 | bl = al; 230 | al = (t1l + t2l) | 0; 231 | ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; 232 | } 233 | 234 | // Intermediate hash value 235 | H0l = H0.low = (H0l + al); 236 | H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); 237 | H1l = H1.low = (H1l + bl); 238 | H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); 239 | H2l = H2.low = (H2l + cl); 240 | H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); 241 | H3l = H3.low = (H3l + dl); 242 | H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); 243 | H4l = H4.low = (H4l + el); 244 | H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); 245 | H5l = H5.low = (H5l + fl); 246 | H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); 247 | H6l = H6.low = (H6l + gl); 248 | H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); 249 | H7l = H7.low = (H7l + hl); 250 | H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); 251 | }, 252 | 253 | _doFinalize: function () { 254 | // Shortcuts 255 | var data = this._data; 256 | var dataWords = data.words; 257 | 258 | var nBitsTotal = this._nDataBytes * 8; 259 | var nBitsLeft = data.sigBytes * 8; 260 | 261 | // Add padding 262 | dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); 263 | dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); 264 | dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; 265 | data.sigBytes = dataWords.length * 4; 266 | 267 | // Hash final blocks 268 | this._process(); 269 | 270 | // Convert hash to 32-bit word array before returning 271 | var hash = this._hash.toX32(); 272 | 273 | // Return final computed hash 274 | return hash; 275 | }, 276 | 277 | clone: function () { 278 | var clone = Hasher.clone.call(this); 279 | clone._hash = this._hash.clone(); 280 | 281 | return clone; 282 | }, 283 | 284 | blockSize: 1024/32 285 | }); 286 | 287 | /** 288 | * Shortcut function to the hasher's object interface. 289 | * 290 | * @param {WordArray|string} message The message to hash. 291 | * 292 | * @return {WordArray} The hash. 293 | * 294 | * @static 295 | * 296 | * @example 297 | * 298 | * var hash = CryptoJS.SHA512('message'); 299 | * var hash = CryptoJS.SHA512(wordArray); 300 | */ 301 | C.SHA512 = Hasher._createHelper(SHA512); 302 | 303 | /** 304 | * Shortcut function to the HMAC's object interface. 305 | * 306 | * @param {WordArray|string} message The message to hash. 307 | * @param {WordArray|string} key The secret key. 308 | * 309 | * @return {WordArray} The HMAC. 310 | * 311 | * @static 312 | * 313 | * @example 314 | * 315 | * var hmac = CryptoJS.HmacSHA512(message, key); 316 | */ 317 | C.HmacSHA512 = Hasher._createHmacHelper(SHA512); 318 | }()); 319 | 320 | 321 | return CryptoJS.SHA512; 322 | 323 | })); -------------------------------------------------------------------------------- /src/client/js/client.js: -------------------------------------------------------------------------------- 1 | /* This file is executed in the browser, when people visit / */ 2 | "use strict"; 3 | 4 | // variables which hold the data for each person 5 | var socket = io(), // connect to the socket 6 | lstUsers = null, 7 | lstChannels = null, 8 | currentChannelName = "", 9 | channelMessages = {}, 10 | channels = null, 11 | state = ["offline", "online"], // 0: offline, 1: online 12 | lstTypingUser = {}, 13 | keys = getCipherKeys(); 14 | 15 | // on connection to server get the id of person's channel 16 | socket.on("connect", () => { 17 | console.log(`connected by socket.id: ${socket.id}`) 18 | setConnectionStatus("connected"); 19 | var me = getMe(); 20 | if (me && localStorage.hashedPass) { 21 | // nonce password 22 | me.password = getNoncePassword(localStorage.hashedPass); 23 | socket.emit('login', me); 24 | } 25 | }); 26 | 27 | // when me sign-in was expired from server time 28 | socket.on("resign", () => { 29 | var me = getMe(); 30 | $(".login100-form-title").html("Login"); 31 | $("#yourName").val(me.username); 32 | $("#yourEmail").val(me.email); 33 | $("#yourAvatar").attr("src", me.avatar); 34 | }); 35 | 36 | // when me disconnected from server then changed my profile status to offline mode 37 | socket.on("disconnect", () => { 38 | console.warn(`socket <${getMe().socketid}> disconnected!`); 39 | setConnectionStatus("disconnected"); 40 | }); 41 | 42 | // on exception occurred from server call 43 | socket.on("exception", err => { 44 | alert(err); 45 | }); 46 | 47 | // save the my user data when I signed-in to server successfully 48 | socket.on('signed', signedin); 49 | 50 | // update users and channels data when thats status changed 51 | socket.on('update', data => { 52 | lstUsers = data.users; 53 | lstChannels = data.channels; 54 | $("#userContacts").empty(); 55 | $("#channelContacts").empty(); 56 | 57 | delete lstUsers[getMe().id]; // remove me from users list 58 | for (var prop in lstUsers) { 59 | var user = lstUsers[prop]; 60 | var channel = getChannelName(user.id); 61 | $("#userContacts").append("
  • " + getUserLink(user, channel) + "
  • "); 62 | } 63 | 64 | for (var prop in lstChannels) { 65 | var channel = lstChannels[prop]; 66 | $("#channelContacts").append("
  • " + getChannelLink(channel) + "
  • ") 67 | }; 68 | 69 | if (currentChannelName != null && currentChannelName.length > 0) { 70 | chatStarted(currentChannelName); 71 | } 72 | }); 73 | 74 | // when a client socket disconnected or a channel admin be offline 75 | socket.on('leave', leftedUser => { 76 | var u = lstUsers[leftedUser.id]; 77 | if (u != null) { 78 | u.status = leftedUser.status; 79 | var chat = getChannelName(u.id); 80 | $(`#${getChannelName(u.id)}`).html(getUserLink(u, chat)) 81 | } 82 | }); 83 | 84 | // on a user requested to chat by me or join to the channel which is me admin of 85 | socket.on('request', data => { 86 | var reqUser = lstUsers[data.from]; 87 | if (reqUser == null) { 88 | socket.emit("reject", { to: data.from, channel: data.channel, msg: "I don't know who requested!" }); 89 | return; // incorrect request from 90 | } 91 | 92 | var reqChannel = getChannels()[data.channel]; 93 | 94 | if (reqChannel == null) { // dose not exist in channel list, so it's a new p2p channel! 95 | // ask me to accept or reject user request 96 | if (confirm(`Do you allow <${reqUser.username}> to chat with you?`) == false) { 97 | socket.emit("reject", { to: data.from, channel: data.channel }); 98 | return; 99 | } 100 | // wow, accepted... 101 | createChannel(data.channel, true); 102 | reqChannel = getChannels()[data.channel]; 103 | } 104 | else if (reqChannel.p2p === false) { 105 | // ask me to accept or reject user request 106 | if (confirm(`Do you allow <${reqUser.username}> to join in <${reqChannel.name}> channel?`) == false) { 107 | socket.emit("reject", { to: data.from, channel: data.channel }); 108 | return; 109 | } 110 | } 111 | // encrypt the chat symmetricKey by requested user public key 112 | var encryptedChannelKey = reqChannel.channelKey.asymEncrypt(data.pubKey) 113 | // 114 | // send data to requester user to join in current channel 115 | socket.emit("accept", { to: data.from, channelKey: encryptedChannelKey, channel: reqChannel.name }) 116 | chatStarted(reqChannel.name); 117 | }); 118 | 119 | // when my chat request accepted by channel admin 120 | socket.on('accept', data => { 121 | // decrypt RSA cipher by my pricate key 122 | var symmetricKey = data.channelKey.asymDecrypt(keys.privateKey); 123 | // 124 | // store this channel to my channels list 125 | setChannel(data.channel, { name: data.channel, p2p: data.p2p, channelKey: symmetricKey }); 126 | chatStarted(data.channel); 127 | }); 128 | 129 | // when my chat request rejected by channel admin 130 | socket.on('reject', data => { 131 | var admin = lstUsers[data.from]; 132 | var reason = data.msg == null ? "" : "because " + data.msg; 133 | if (data.p2p) 134 | alert(`Your request to chat by <${admin.username}> rejected. ${reason}`); 135 | else 136 | alert(`Your join request to <${data.channel}> channel rejected. ${reason}`); 137 | 138 | $(`#${data.channel}`).find(".wait").css("display", "none"); 139 | }); 140 | 141 | // when a messsage sent to me or channel which is I member in 142 | socket.on('receive', data => { 143 | if (currentChannelName == data.to) // from current chat 144 | appendMessage(data); 145 | else { 146 | // keep in buffer for other time view 147 | data.state = "replies"; 148 | // 149 | // increase badge 150 | var badge = $(`#${data.to}`).find(".badge"); 151 | var badgeVal = badge.attr("data-badge"); 152 | if (badgeVal == "") badgeVal = 0; 153 | badge.attr("data-badge", parseInt(badgeVal) + 1); 154 | } 155 | 156 | getMessages(data.to).push(data); 157 | }); 158 | 159 | // when get response of my requests to fetch history of the chat messages 160 | socket.on('fetch-messages', data => { 161 | if (data.messages == null) 162 | data.messages == []; // set to un-null to except next time requests 163 | channelMessages[data.channel] = data.messages; 164 | updateMessages(); 165 | }); 166 | 167 | socket.on('error', () => { 168 | console.log("Client: error"); 169 | socket.socket.reconnect(); 170 | }); 171 | 172 | 173 | // on a user typing in a associated chat with me 174 | socket.on("typing", data => { 175 | var user = lstUsers[data.user]; 176 | var channel = getChannels()[data.channel]; 177 | if (channel && user && channel.name === currentChannelName) { 178 | lstTypingUser[user.username] = Date.now(); 179 | updateTypingUsers(channel); 180 | var timeout = 10000; // 10sec 181 | setTimeout(() => { 182 | for (var u in lstTypingUser) 183 | if (lstTypingUser[u] + timeout - 2000 < Date.now()) { 184 | // clear old typing state users 185 | delete lstTypingUser[u]; 186 | } 187 | 188 | updateTypingUsers(channel); 189 | }, timeout); 190 | } 191 | }); 192 | 193 | // 194 | // 195 | // 196 | // ------------------------------------ utilitie functions ------------------------------------- 197 | // 198 | // 199 | function updateTypingUsers(channel) { 200 | var typingSpan = $("#channel-user-typing"); 201 | 202 | if (Object.keys(lstTypingUser).length > 0) { 203 | if (channel.p2p) 204 | typingSpan.html(`is typing...`); 205 | else { 206 | var names = Object.getOwnPropertyNames(lstTypingUser); 207 | var usernames = names.slice(0, 3).join(", "); 208 | if (names.length > 3) 209 | usernames += " and others are"; 210 | else if (names.length <= 1) 211 | usernames += " is"; 212 | else 213 | usernames += " are"; 214 | 215 | typingSpan.html(`${usernames} typing...`); 216 | } 217 | 218 | typingSpan.css("display", "flex"); 219 | } 220 | else { 221 | typingSpan.css("display", "none"); 222 | } 223 | } 224 | 225 | function reqChatBy(name) { 226 | $(`#${name}`).find(".wait").css("display", "block"); 227 | var channel = getChannels()[name]; 228 | 229 | if (channel && channel.channelKey) { // me already joined in chat 230 | chatStarted(name); 231 | } 232 | else { 233 | socket.emit("request", { channel: name, pubKey: keys.publicKey }); 234 | } 235 | } 236 | 237 | function getUserLink(user, channel) { 238 | return `
    239 | 240 | 241 |
    242 |
    243 |

    ${user.username}

    244 |
    245 |
    `; 246 | } 247 | 248 | function getChannelLink(channel) { 249 | return `
    250 | 251 |
    252 |
    253 |

    ${channel.name}

    254 |
    255 |
    `; 256 | } 257 | 258 | function getChannelName(userid) { 259 | var ids = [getMe().id, userid].sort(); 260 | return `${ids[0]}_${ids[1]}`; // unique name for this users private 261 | } 262 | 263 | // set channels thread safe 264 | function setChannel(name, channel) { 265 | getChannels()[name] = channel; 266 | localStorage.channels = JSON.stringify(getChannels()); 267 | } 268 | 269 | function getChannels() { 270 | if (channels) 271 | return channels; 272 | 273 | if (localStorage.channels) 274 | channels = JSON.parse(localStorage.channels) 275 | else { 276 | channels = {}; 277 | localStorage.channels = "{}"; // store string of object 278 | } 279 | 280 | return channels; 281 | } 282 | 283 | function setMe(data) { 284 | var lastMe = getMe(); 285 | 286 | if (lastMe && lastMe.serverVersion !== data.serverVersion) { 287 | // server restarted, so refresh cached data 288 | localStorage.channels = "{}"; 289 | } 290 | localStorage.me = JSON.stringify(data); 291 | } 292 | 293 | function getMe() { 294 | var me = localStorage.me; 295 | if (me == null) 296 | return null; 297 | 298 | return JSON.parse(me); 299 | } 300 | 301 | function setConnectionStatus(state) { 302 | $("#profile-img").removeClass(); 303 | 304 | if (state === "connected") { 305 | $("#profile-img").addClass('online'); 306 | } 307 | else if (state === "disconnected") { 308 | $("#profile-img").addClass('offline'); 309 | } 310 | } 311 | 312 | function chatStarted(channel) { 313 | currentChannelName = channel; 314 | $("li").removeClass("active"); 315 | var contact = $(`#${channel}`); 316 | contact.addClass("active"); 317 | contact.find(".badge").attr("data-badge", ""); // remove badge 318 | $("#channel-profile-img").attr("src", contact.find("img").attr("src")) 319 | $("#channel-profile-name").html(contact.find(".name").html()) 320 | contact.find(".wait").css("display", "none"); 321 | 322 | updateMessages(); 323 | } 324 | 325 | function signedin(me) { 326 | console.info(`I signed-in by socket <${me.socketid}>`); 327 | setMe(me); 328 | $("title").html(`Secure Chat - ${me.username}`) 329 | $("#profile-img").attr("src", me.avatar); 330 | $("#myUsername").html(me.username); 331 | $("#myEmail").val(me.email); 332 | $(".limiter").remove(); 333 | $("#frame").css("display", "block"); 334 | } 335 | 336 | function updateMessages() { 337 | // show old messages 338 | var messages = getMessages(currentChannelName); 339 | 340 | // add all messages to screen 341 | var lstMessagesDom = $('.messages ul'); 342 | lstMessagesDom.empty(); // clear screen 343 | for (var i in messages) { 344 | appendMessage(messages[i]); 345 | } 346 | } 347 | 348 | function newMessage() { 349 | var message = $(".message-input input").val(); 350 | if ($.trim(message) == '') { 351 | return false; 352 | } 353 | 354 | if (currentChannelName == null || currentChannelName == '') { 355 | alert("Please first select a chat to sending message!"); 356 | return false; 357 | } 358 | 359 | // get channel symmetric key and encrypt message 360 | var chatSymmetricKey = getChannels()[currentChannelName].channelKey; 361 | var msg = message.symEncrypt(chatSymmetricKey) 362 | 363 | // Send the message to the chat channel 364 | socket.emit('msg', { msg: msg, from: getMe().id, to: currentChannelName, avatar: getMe().avatar }); 365 | 366 | // Empty the message input 367 | $('.message-input input').val(null); 368 | $('.message-input input').focus(); 369 | }; 370 | 371 | function appendMessage(data) { 372 | if (data.from == getMe().id) { 373 | data.state = "sent"; 374 | data.name = getMe().username; 375 | } else { 376 | data.state = "replies" 377 | data.name = lstUsers[data.from].username; 378 | } 379 | 380 | data.msgHeader = ""; 381 | if (lstChannels[data.to]) { // if is a real channel 382 | data.msgHeader = `${data.name}
    ` 383 | } 384 | 385 | // get this channel symmetric key to decrypt message 386 | var symmetricKey = getChannels()[currentChannelName].channelKey; 387 | var msg = data.msg.symDecrypt(symmetricKey) 388 | 389 | // add to self screen 390 | var messagesScreen = $(".messages"); 391 | messagesScreen.find("ul").append(`
  • ${data.msgHeader}${msg}

  • `); // append message to end of page 392 | messagesScreen.scrollTop(messagesScreen[0].scrollHeight); // scroll to end of messages page 393 | } 394 | 395 | function getMessages(channel) { 396 | var msgArray = channelMessages[channel]; 397 | if (msgArray == null) { 398 | // fetch from server 399 | socket.emit("fetch-messages", channel); 400 | return []; 401 | } 402 | else 403 | return msgArray; 404 | } 405 | 406 | function createChannel(channel, p2p) { 407 | if (lstChannels[channel]) 408 | return false; 409 | 410 | // my socket is admin for this channel 411 | // generate symmetric key 412 | var symmetricKey = generateKey(50); 413 | // 414 | // store this channel to my channels list 415 | setChannel(channel, { name: channel, p2p: p2p, channelKey: symmetricKey }); 416 | 417 | return true; 418 | } 419 | 420 | // create nonce password by socket.id 421 | function getNoncePassword(pass) { 422 | return pass.symEncrypt(socket.id); 423 | } 424 | 425 | // 426 | // 427 | // 428 | // ------------------------------------ Jquery DOM Events ------------------------------------- 429 | // 430 | // 431 | (function ($) { 432 | "use strict"; 433 | 434 | /*================================================================== 435 | [ Expand profile ]*/ 436 | $(".expand-button").click(function () { 437 | $("#profile").toggleClass("expanded"); 438 | $("#contacts").toggleClass("expanded"); 439 | }); 440 | 441 | /*================================================================== 442 | [ Press Enter to send message ]*/ 443 | $('.submit').click(function () { 444 | newMessage(); 445 | }); 446 | 447 | $(window).on('keydown', function (e) { 448 | // notify user is typing... 449 | if (currentChannelName != null && currentChannelName.length > 0) 450 | socket.emit("typing", currentChannelName) 451 | 452 | if (e.which == 13) { 453 | newMessage(); 454 | } 455 | }); 456 | 457 | /*================================================================== 458 | [ Press Enter to login ]*/ 459 | $(".validate-input").on('keydown', function (e) { 460 | if (e.which == 13) { 461 | $("#loginButton").click(); 462 | } 463 | }); 464 | 465 | /*================================================================== 466 | [ Focus input ]*/ 467 | $('.input100').each(function () { 468 | $(this).on('blur', function () { 469 | if ($(this).val().trim() != "") { 470 | $(this).addClass('has-val'); 471 | } 472 | else { 473 | $(this).removeClass('has-val'); 474 | } 475 | }) 476 | }) 477 | 478 | /*================================================================== 479 | [ Add channel button ]*/ 480 | $("#addchannel").on("click", () => { 481 | var name = prompt("Please enter channel name:", "Channel"); 482 | if (name) { 483 | name = name.replace(/ /g, "_"); // replace all space to _ 484 | if (createChannel(name, false)) { 485 | // send data to requester user to join in current channel 486 | socket.emit("createChannel", name); 487 | } 488 | else { 489 | alert(`The <${name}> channel name already exist`); 490 | } 491 | } 492 | }) 493 | 494 | /*================================================================== 495 | [ Validate ]*/ 496 | var input = $('.validate-input .input100'); 497 | 498 | // Submit login div 499 | $("#loginButton").on('click', () => { 500 | // validation data 501 | var check = true; 502 | for (var i = 0; i < input.length; i++) { 503 | if (validate(input[i]) == false) { 504 | showValidate(input[i]); 505 | check = false; 506 | } 507 | } 508 | 509 | if (check) { // if login data is valid then: 510 | var name = $.trim($("#yourName").val()); 511 | var email = $("#yourEmail").val(); 512 | var pass = $("#yourPass").val(); 513 | localStorage.hashedPass = pass.getHash(); // store my login password by hashing 514 | var noncePass = getNoncePassword(localStorage.hashedPass); 515 | socket.emit('login', { username: name, email: email, password: noncePass }); 516 | } 517 | }); 518 | 519 | $('.validate-form .input100').each(function () { 520 | $(this).focus(function () { 521 | hideValidate(this); 522 | }); 523 | }); 524 | 525 | function validate(input) { 526 | if ($(input).attr('type') == 'email' || $(input).attr('name') == 'email') { 527 | if ($(input).val().trim().match(/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{1,5}|[0-9]{1,3})(\]?)$/) == null) { 528 | return false; 529 | } 530 | } 531 | else { 532 | if ($(input).val().trim() == '') { 533 | return false; 534 | } 535 | } 536 | } 537 | 538 | function showValidate(input) { 539 | var thisAlert = $(input).parent(); 540 | 541 | $(thisAlert).addClass('alert-validate'); 542 | } 543 | 544 | function hideValidate(input) { 545 | var thisAlert = $(input).parent(); 546 | 547 | $(thisAlert).removeClass('alert-validate'); 548 | } 549 | 550 | })(jQuery); --------------------------------------------------------------------------------