diff --git a/client/components/MessageInput.tsx b/client/components/MessageInput.tsx index 431ac5d..7b8fa6e 100644 --- a/client/components/MessageInput.tsx +++ b/client/components/MessageInput.tsx @@ -5,10 +5,11 @@ import { useSocket } from "@/context/socket.context" import UploadButton from "./UploadButton"; import SendOutlinedIcon from '@mui/icons-material/SendOutlined'; import EVENTS from '@/config/events'; +import crypto from 'crypto' const MessageInput = () => { - const { socket, username, messages, setMessages, roomID } = useSocket(); + const { socket, username, messages, setMessages, roomID, aesKey } = useSocket(); const [ textInput, setTextInput ] = useState(""); const handleChange = (e: any) => { @@ -28,12 +29,24 @@ const MessageInput = () => { const date = new Date(); const timestamp = date.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true });; + + const iv = crypto.randomBytes(16); + const ivString = iv.toString('hex'); + const encryptedMessage = encrypt(textInput, iv); setMessages([...messages, {type: "text", username: username, body: textInput, timestamp: timestamp}]); - socket.emit(EVENTS.CLIENT.SEND_MESSAGE, {type: "text", roomID: roomID, username: username, body: textInput, timestamp: timestamp}); + socket.emit(EVENTS.CLIENT.SEND_MESSAGE, {type: "text", roomID: roomID, username: username, body: encryptedMessage, timestamp: timestamp, iv: ivString}); setTextInput(""); }; + const encrypt = (text: string, iv: any) => { + const cipher = crypto.createCipheriv('aes-256-cbc', aesKey, iv); + let encryptedMessage = cipher.update(text, 'utf-8', 'hex'); + encryptedMessage += cipher.final('hex'); + + return encryptedMessage; + }; + return (
diff --git a/client/context/socket.context.tsx b/client/context/socket.context.tsx index 18351d4..467d5da 100644 --- a/client/context/socket.context.tsx +++ b/client/context/socket.context.tsx @@ -1,8 +1,9 @@ 'use client'; -import { createContext, useContext, useState, useEffect } from 'react'; +import { createContext, useContext, useState, useEffect, useRef } from 'react'; import io, { Socket } from 'socket.io-client'; import EVENTS from '@/config/events'; +import crypto from 'crypto' interface Context { socket: Socket; @@ -11,13 +12,13 @@ interface Context { messages: { type: string; username: string; - body: string; + body: any; timestamp: string; }[]; setMessages: Function; roomID?: string; usersConnected: []; - setUsersConnected: Function; + aesKey: Buffer; } const SOCKET_URL = @@ -29,13 +30,16 @@ const socket = io(SOCKET_URL, { transports: ['websocket', 'polling'], }); +const aesKeyString = "fcba69ac69c7182417c68a5f6f78f6a24072156dd444013e69a2820f631164e7"; +const aesKey = Buffer.from(aesKeyString, 'hex'); + const SocketContext = createContext({ socket, messages: [], usersConnected: [], + aesKey, setUsername: () => false, - setMessages: () => false, - setUsersConnected: () => false + setMessages: () => false }); const SocketsProvider = (props: any) => { @@ -44,14 +48,20 @@ const SocketsProvider = (props: any) => { { type: string; username: string; body: string; timestamp: string }[] >([]); const [roomID, setRoomID] = useState(''); - const [ usersConnected, setUsersConnected ] = useState([]); + const [usersConnected, setUsersConnected] = useState([]); useEffect(() => { socket.on( EVENTS.SERVER.SEND_MESSAGE, - ({ type, username, body, timestamp }) => { - setMessages([...messages, { type, username, body, timestamp }]); - } + ({ type, username, body, timestamp, iv }) => { + + const decipher = crypto.createDecipheriv('aes-256-cbc', aesKey, Buffer.from(iv, 'hex')); + let decryptedMessage: any= decipher.update(body, 'hex', 'utf-8'); + decryptedMessage += decipher.final('utf-8'); + body = decryptedMessage; + + setMessages([...messages, { type, username, body, timestamp }]); + } ); }, [socket]); @@ -59,17 +69,22 @@ const SocketsProvider = (props: any) => { setMessages([]); }, [roomID]); - socket.on(EVENTS.UPDATE_USERS, ({ usersConnected }) => { - setUsersConnected(usersConnected); - }); - socket.on( EVENTS.SERVER.SEND_MESSAGE, - ({ type, username, body, timestamp }) => { + ({ type, username, body, timestamp, iv }) => { + const decipher = crypto.createDecipheriv('aes-256-cbc', aesKey, Buffer.from(iv, 'hex')); + let decryptedMessage: any= decipher.update(body, 'hex', 'utf-8'); + decryptedMessage += decipher.final('utf-8'); + body = decryptedMessage; + setMessages([...messages, { type, username, body, timestamp }]); } ); + socket.on(EVENTS.UPDATE_USERS, ({ usersConnected }) => { + setUsersConnected(usersConnected); + }); + socket.on(EVENTS.SERVER.JOIN_ROOM, ({ roomID }) => { setRoomID(roomID); setMessages([]); @@ -81,7 +96,7 @@ const SocketsProvider = (props: any) => { return ( ); diff --git a/server/src/app.ts b/server/src/app.ts index 8967059..5de9c9f 100644 --- a/server/src/app.ts +++ b/server/src/app.ts @@ -2,6 +2,7 @@ import express from 'express'; import { createServer } from 'http'; import { Server, Socket } from 'socket.io'; import { nanoid } from 'nanoid'; +import crypto from 'crypto' const port = process.env.PORT || 4000; const corsOrigin = '*'; @@ -61,12 +62,14 @@ httpServer.listen(port, () => { socket.on(EVENTS.CLIENT.SEND_MESSAGE, (data) => { console.log(`${data.username} sent a ${data.type} to room: ${data.roomID}`); + socket.to(data.roomID).emit(EVENTS.SERVER.SEND_MESSAGE, { type: data.type, username: data.username, body: data.body, - timestamp: data.timestamp + timestamp: data.timestamp, + iv: data.iv, }); });