├── .gitignore ├── README.md ├── example ├── client.js ├── package.json └── server.js ├── index.js ├── package.json ├── reserved-events.js └── symbol.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # socket.io-encrypt 2 | 3 | Patches `socket.emit` and and `socket.on` functions to send encrypted and decrypt messages using **[cryptr]**. 4 | 5 | [cryptr]: https://github.com/MauriceButler/cryptr 6 | 7 | ## Install 8 | 9 | ``` 10 | npm i socket.io-encrypt 11 | ``` 12 | 13 | ## Usage 14 | 15 | ### **`client`** 16 | 17 | ```js 18 | const SocketIO = require('socket.io-client') 19 | const encrypt = require('socket.io-encrypt') 20 | 21 | const socket = SocketIO(SERVER_URL) 22 | encrypt('secret')(socket) 23 | 24 | socket.emit('message', {/* will be encrypted */}) 25 | ``` 26 | 27 | ### **`server`** 28 | 29 | ```js 30 | const SocketIO = require('socket.io') 31 | const encrypt = require('socket.io-encrypt') 32 | 33 | const io = SocketIO({}) 34 | io.use(encrypt(secret)) 35 | 36 | io.on('connect', socket => { 37 | 38 | socket.on('message', data /* decrypted */ => { ... }) 39 | socket.on('error', console.error /* handle decryption errors */) 40 | 41 | }) 42 | ``` 43 | -------------------------------------------------------------------------------- /example/client.js: -------------------------------------------------------------------------------- 1 | const SocketIO = require('socket.io-client'); 2 | const encrypt = require('socket.io-encrypt'); 3 | 4 | const socket = SocketIO('http://localhost:3000'); 5 | encrypt('secret')(socket); 6 | 7 | socket.on('connect', () => { 8 | console.log('Connected'); 9 | socket.emit('message', { message: 'my secret message' }); 10 | }); 11 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "socket.io-encrypt": "file:..", 4 | "socket.io": "^2.2.0", 5 | "socket.io-client": "^2.2.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example/server.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const SocketIO = require('socket.io'); 3 | const encrypt = require('socket.io-encrypt'); 4 | 5 | const server = http.createServer(); 6 | const io = SocketIO(server); 7 | 8 | io.use(encrypt('secret')); 9 | 10 | server.listen(3000, error => { 11 | if (error) console.error(error); 12 | else console.log('Listening at 3000'); 13 | }); 14 | 15 | io.on('connect', socket => { 16 | console.log('Connected:', socket.id); 17 | socket.on('message', data => { 18 | console.log('Message from', socket.id, data); 19 | }); 20 | socket.on('error', console.error); 21 | }); 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const Cryptr = require('cryptr'); 2 | const { emit, on, off, removeEventListener, removeListener } = require('./symbol'); 3 | const reservedEvents = require('./reserved-events'); 4 | 5 | module.exports = (secret) => (socket, next) => { 6 | const handlers = new WeakMap(); 7 | const cryptr = new Cryptr(secret); 8 | 9 | const encrypt = args => { 10 | const encrypted = []; 11 | let ack; 12 | for (let i = 0; i < args.length; i++) { 13 | const arg = args[i]; 14 | if (i === args.length - 1 && typeof arg === 'function') { 15 | ack = arg; 16 | } else { 17 | encrypted.push(cryptr.encrypt(JSON.stringify(arg))); 18 | } 19 | 20 | } 21 | if (!encrypted.length) return args; 22 | args = [{ encrypted }]; 23 | if (ack) args.push(ack); 24 | return args; 25 | }; 26 | 27 | const decrypt = encrypted => { 28 | try { 29 | return encrypted.map(a => JSON.parse(cryptr.decrypt(a))); 30 | } catch (e) { 31 | const error = new Error(`Couldn't decrypt. Wrong secret used on client or invalid data sent. (${e.message})`); 32 | error.code = 'ERR_DECRYPTION_ERROR'; 33 | throw error; 34 | } 35 | }; 36 | 37 | socket[emit] = socket.emit; 38 | socket[on] = socket.on; 39 | socket[off] = socket.off; 40 | socket[removeEventListener] = socket.removeEventListener; 41 | socket[removeListener] = socket.removeListener; 42 | 43 | socket.emit = (event, ...args) => { 44 | if (reservedEvents.includes(event)) return socket[emit](event, ...args); 45 | 46 | return socket[emit](event, ...encrypt(args)); 47 | }; 48 | 49 | socket.on = (event, handler) => { 50 | if (reservedEvents.includes(event)) return socket[on](event, handler); 51 | 52 | const newHandler = function(...args) { 53 | if (args[0] && args[0].encrypted) { 54 | try { 55 | args = decrypt(args[0].encrypted); 56 | } catch (error) { 57 | socket[emit]('error', error); 58 | return; 59 | } 60 | } 61 | return handler.call(this, ...args); 62 | }; 63 | 64 | handlers.set(handler, newHandler); 65 | return socket[on](event, newHandler); 66 | }; 67 | 68 | socket.off = (event, handler) => { 69 | if (reservedEvents.includes(event)) return socket[off](event, handler); 70 | 71 | const properHandler = handlers.get(handler); 72 | if (properHandler) { 73 | handlers.delete(handler); 74 | return socket[off](event, properHandler); 75 | } 76 | 77 | return socket[off](event, handler); 78 | } 79 | 80 | socket.removeEventListener = (event, handler) => { 81 | return socket.off(event, handler); 82 | } 83 | 84 | socket.removeListener = (event, handler) => { 85 | return socket.off(event, handler); 86 | } 87 | 88 | if (next) next(); 89 | return socket; 90 | }; 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "socket.io-encrypt", 3 | "version": "0.2.1", 4 | "description": "Send encrypted and decrypt messages", 5 | "main": "index.js", 6 | "repository": "laggingreflex/socket.io-encrypt", 7 | "peerDependencies": { 8 | "socket.io": "^2.0.0", 9 | "socket.io-client": "^2.0.0" 10 | }, 11 | "dependencies": { 12 | "cryptr": "^4.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /reserved-events.js: -------------------------------------------------------------------------------- 1 | /*https://socket.io/docs/emit-cheatsheet/*/ 2 | module.exports = [ 3 | 'error', 4 | 'connect', 5 | 'disconnect', 6 | 'disconnecting', 7 | 'newListener', 8 | 'removeListener', 9 | 'ping', 10 | 'pong' 11 | ]; 12 | -------------------------------------------------------------------------------- /symbol.js: -------------------------------------------------------------------------------- 1 | exports.emit = Symbol('emit'); 2 | exports.on = Symbol('on'); 3 | exports.off = Symbol('off'); 4 | exports.removeEventListener = Symbol('removeEventListener'); 5 | exports.removeListener = Symbol('removeListener'); 6 | --------------------------------------------------------------------------------