mirror of
https://github.com/darkwire/darkwire.io.git
synced 2025-07-18 18:54:52 +00:00
Creating interface for darkwire, started work on filetransfer
This commit is contained in:
parent
4338f1aa8a
commit
e59bb2a1cf
10
readme.md
10
readme.md
@ -42,7 +42,15 @@ Group chats work the same way because in step 5 we encrypt keys with everyone's
|
|||||||
|
|
||||||
Darkwire does not provide any guarantee that the person you're communicating with is who you think they are. Authentication functionality may be incorporated in future versions.
|
Darkwire does not provide any guarantee that the person you're communicating with is who you think they are. Authentication functionality may be incorporated in future versions.
|
||||||
|
|
||||||
### Sockets & Server
|
## File Transfer
|
||||||
|
|
||||||
|
Files are not transferred over the wire-only the file name and extension. Darkwire encodes documents into base64 using [btoa](https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/btoa) and is encrypted the same way chat messages are.
|
||||||
|
|
||||||
|
1. When a file is "uploaded", the document is encoded on the client and the server recieves the encrypted base64 string.
|
||||||
|
2. The server sends the encrypted base64 string to clients in the same chat room.
|
||||||
|
3. Clients recieving the encrypted base64 string then decrypts the string, then decodes the base64 string using [atob](https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/atob).
|
||||||
|
|
||||||
|
## Sockets & Server
|
||||||
|
|
||||||
Darkwire uses [socket.io](http://socket.io) to transmit encrypted information using secure [WebSockets](https://en.wikipedia.org/wiki/WebSocket) (WSS).
|
Darkwire uses [socket.io](http://socket.io) to transmit encrypted information using secure [WebSockets](https://en.wikipedia.org/wiki/WebSocket) (WSS).
|
||||||
|
|
||||||
|
@ -10,7 +10,9 @@ import fs from 'fs';
|
|||||||
|
|
||||||
import Room from './room';
|
import Room from './room';
|
||||||
|
|
||||||
const $PORT = 3000;
|
const $CONFIG = {
|
||||||
|
port: 3000
|
||||||
|
}
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
@ -54,6 +56,6 @@ app.get('/:roomId', (req, res) => {
|
|||||||
return res.redirect('/');
|
return res.redirect('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen($PORT, () => {
|
server.listen($CONFIG.port, () => {
|
||||||
console.log(`darkwire is online on port ${$PORT}.`);
|
console.log(`darkwire is online on port ${$CONFIG.port}.`);
|
||||||
});
|
});
|
||||||
|
200
src/js/darkwire.js
Normal file
200
src/js/darkwire.js
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import _ from 'underscore';
|
||||||
|
import AudioHandler from './audio';
|
||||||
|
import CryptoUtil from './crypto';
|
||||||
|
|
||||||
|
export default class Darkwire {
|
||||||
|
constructor() {
|
||||||
|
this._audio = new AudioHandler();
|
||||||
|
this._cryptoUtil = new CryptoUtil();
|
||||||
|
this._myUserId = false;
|
||||||
|
this._connected = false;
|
||||||
|
this._users = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get users() {
|
||||||
|
return this._users;
|
||||||
|
}
|
||||||
|
|
||||||
|
get audio() {
|
||||||
|
return this._audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
addUser(data) {
|
||||||
|
let importKeysPromises = [];
|
||||||
|
// Import all user keys if not already there
|
||||||
|
_.each(data.users, (user) => {
|
||||||
|
if (!_.findWhere(this._users, {id: user.id})) {
|
||||||
|
let promise = new Promise((resolve, reject) => {
|
||||||
|
let currentUser = user;
|
||||||
|
Promise.all([
|
||||||
|
this._cryptoUtil.importPrimaryKey(currentUser.publicKey, "spki")
|
||||||
|
])
|
||||||
|
.then((keys) => {
|
||||||
|
this._users.push({
|
||||||
|
id: currentUser.id,
|
||||||
|
username: currentUser.username,
|
||||||
|
publicKey: keys[0]
|
||||||
|
});
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
importKeysPromises.push(promise);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this._myUserId) {
|
||||||
|
// Set my id if not already set
|
||||||
|
let me = _.findWhere(data.users, {username: username});
|
||||||
|
this._myUserId = me.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return importKeysPromises;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage(message, messageType) {
|
||||||
|
// Don't send unless other users exist
|
||||||
|
console.log(this._users);
|
||||||
|
if (this._users.length <= 1) return;
|
||||||
|
|
||||||
|
// if there is a non-empty message and a socket connection
|
||||||
|
if (message && this._connected) {
|
||||||
|
$inputMessage.val('');
|
||||||
|
$('#send-message-btn').removeClass('active');
|
||||||
|
addChatMessage({
|
||||||
|
username: username,
|
||||||
|
message: message
|
||||||
|
});
|
||||||
|
let vector = this._cryptoUtil.crypto.getRandomValues(new Uint8Array(16));
|
||||||
|
|
||||||
|
let secretKey;
|
||||||
|
let secretKeys;
|
||||||
|
let messageData;
|
||||||
|
let signature;
|
||||||
|
let signingKey;
|
||||||
|
let encryptedMessageData;
|
||||||
|
|
||||||
|
// Generate new secret key and vector for each message
|
||||||
|
this._cryptoUtil.createSecretKey()
|
||||||
|
.then(function(key) {
|
||||||
|
secretKey = key;
|
||||||
|
return this._cryptoUtil.createSigningKey();
|
||||||
|
})
|
||||||
|
.then(function(key) {
|
||||||
|
signingKey = key;
|
||||||
|
// Generate secretKey and encrypt with each user's public key
|
||||||
|
let promises = [];
|
||||||
|
_.each(this._users, function(user) {
|
||||||
|
// If not me
|
||||||
|
if (user.username !== window.username) {
|
||||||
|
let promise = new Promise(function(resolve, reject) {
|
||||||
|
let thisUser = user;
|
||||||
|
|
||||||
|
let secretKeyStr;
|
||||||
|
|
||||||
|
// Export secret key
|
||||||
|
this._cryptoUtil.exportKey(secretKey, "raw")
|
||||||
|
.then(function(data) {
|
||||||
|
return this._cryptoUtil.encryptSecretKey(data, thisUser.publicKey);
|
||||||
|
})
|
||||||
|
.then(function(encryptedSecretKey) {
|
||||||
|
let encData = new Uint8Array(encryptedSecretKey);
|
||||||
|
secretKeyStr = this._cryptoUtil.convertArrayBufferViewToString(encData);
|
||||||
|
// Export HMAC signing key
|
||||||
|
return this._cryptoUtil.exportKey(signingKey, "raw");
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
// Encrypt signing key with user's public key
|
||||||
|
return this._cryptoUtil.encryptSigningKey(data, thisUser.publicKey);
|
||||||
|
})
|
||||||
|
.then(function(encryptedSigningKey) {
|
||||||
|
let encData = new Uint8Array(encryptedSigningKey);
|
||||||
|
var str = this._cryptoUtil.convertArrayBufferViewToString(encData);
|
||||||
|
resolve({
|
||||||
|
id: thisUser.id,
|
||||||
|
secretKey: secretKeyStr,
|
||||||
|
encryptedSigningKey: str
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
promises.push(promise);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Promise.all(promises);
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
secretKeys = data;
|
||||||
|
messageData = this._cryptoUtil.convertStringToArrayBufferView(message);
|
||||||
|
return this._cryptoUtil.signKey(messageData, signingKey);
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
signature = data;
|
||||||
|
return this._cryptoUtil.encryptMessage(messageData, secretKey, vector);
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
encryptedMessageData = data;
|
||||||
|
let msg = this._cryptoUtil.convertArrayBufferViewToString(new Uint8Array(encryptedMessageData));
|
||||||
|
let vct = this._cryptoUtil.convertArrayBufferViewToString(new Uint8Array(vector));
|
||||||
|
let sig = this._cryptoUtil.convertArrayBufferViewToString(new Uint8Array(signature));
|
||||||
|
socket.emit('new message', {
|
||||||
|
message: msg,
|
||||||
|
vector: vct,
|
||||||
|
messageType: type,
|
||||||
|
secretKeys: secretKeys,
|
||||||
|
signature: sig
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeMessage(data) {
|
||||||
|
return new Promise( (resolve, reject) => {
|
||||||
|
let message = data.message;
|
||||||
|
let messageData = this._cryptoUtil.convertStringToArrayBufferView(message);
|
||||||
|
let username = data.username;
|
||||||
|
let senderId = data.id
|
||||||
|
let vector = data.vector;
|
||||||
|
let vectorData = this._cryptoUtil.convertStringToArrayBufferView(vector);
|
||||||
|
let secretKeys = data.secretKeys;
|
||||||
|
let decryptedMessageData;
|
||||||
|
let decryptedMessage;
|
||||||
|
|
||||||
|
let mySecretKey = _.find(secretKeys, (key) => {
|
||||||
|
return key.id === this._myUserId;
|
||||||
|
});
|
||||||
|
let signature = data.signature;
|
||||||
|
let signatureData = this._cryptoUtil.convertStringToArrayBufferView(signature);
|
||||||
|
let secretKeyArrayBuffer = this._cryptoUtil.convertStringToArrayBufferView(mySecretKey.secretKey);
|
||||||
|
let signingKeyArrayBuffer = this._cryptoUtil.convertStringToArrayBufferView(mySecretKey.encryptedSigningKey);
|
||||||
|
|
||||||
|
this._cryptoUtil.decryptSecretKey(secretKeyArrayBuffer, keys.private)
|
||||||
|
.then((data) => {
|
||||||
|
return this._cryptoUtil.importSecretKey(new Uint8Array(data), "raw");
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
let secretKey = data;
|
||||||
|
return this._cryptoUtil.decryptMessage(messageData, secretKey, vectorData);
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
decryptedMessageData = data;
|
||||||
|
decryptedMessage = this._cryptoUtil.convertArrayBufferViewToString(new Uint8Array(data))
|
||||||
|
return this._cryptoUtil.decryptSigningKey(signingKeyArrayBuffer, keys.private)
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
return this._cryptoUtil.importSigningKey(new Uint8Array(data), "raw");
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
let signingKey = data;
|
||||||
|
return this._cryptoUtil.verifyKey(signatureData, decryptedMessageData, signingKey);
|
||||||
|
})
|
||||||
|
.then((bool) => {
|
||||||
|
if (bool) {
|
||||||
|
resolve({
|
||||||
|
username: username,
|
||||||
|
message: decryptedMessage
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
56
src/js/fileHandler.js
Normal file
56
src/js/fileHandler.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
export default class FileHandler {
|
||||||
|
constructor() {
|
||||||
|
if (window.File && window.FileReader && window.FileList && window.Blob && window.btoa) {
|
||||||
|
this._isSupported = true;
|
||||||
|
this.listen();
|
||||||
|
} else {
|
||||||
|
this._isSupported = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get isSupported() {
|
||||||
|
return this._isSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
encodeFile(event) {
|
||||||
|
const file = event.target.files && event.target.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
|
||||||
|
let encodedFile = {
|
||||||
|
fileName: file.name,
|
||||||
|
fileSize: file.fileSize,
|
||||||
|
base64: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// Support for only 1MB
|
||||||
|
if (file.size > 1000000) {
|
||||||
|
console.log(file);
|
||||||
|
alert("Max filesize is 1MB.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = (readerEvent) => {
|
||||||
|
const base64 = window.btoa(readerEvent.target.result);
|
||||||
|
encodedFile.base64 = base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsBinaryString(file);
|
||||||
|
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
listen() {
|
||||||
|
// browser API
|
||||||
|
document.getElementById('fileInput').addEventListener('change', this.encodeFile, false);
|
||||||
|
|
||||||
|
// darkwire
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
209
src/js/main.js
209
src/js/main.js
@ -1,15 +1,14 @@
|
|||||||
import AudioHandler from './audio';
|
import Darkwire from './darkwire';
|
||||||
import CryptoUtil from './crypto';
|
|
||||||
import WindowHandler from './window';
|
import WindowHandler from './window';
|
||||||
|
import CryptoUtil from './crypto';
|
||||||
|
|
||||||
let fs = window.RequestFileSystem || window.webkitRequestFileSystem;
|
let fs = window.RequestFileSystem || window.webkitRequestFileSystem;
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
const audio = new AudioHandler();
|
const darkwire = new Darkwire();
|
||||||
const cryptoUtil = new CryptoUtil();
|
const cryptoUtil = new CryptoUtil();
|
||||||
const windowHandler = new WindowHandler();
|
const windowHandler = new WindowHandler();
|
||||||
|
|
||||||
let newMessages = 0;
|
|
||||||
let FADE_TIME = 150; // ms
|
let FADE_TIME = 150; // ms
|
||||||
let TYPING_TIMER_LENGTH = 400; // ms
|
let TYPING_TIMER_LENGTH = 400; // ms
|
||||||
|
|
||||||
@ -28,12 +27,7 @@ $(function() {
|
|||||||
|
|
||||||
let $chatPage = $('.chat.page'); // The chatroom page
|
let $chatPage = $('.chat.page'); // The chatroom page
|
||||||
|
|
||||||
let users = [];
|
|
||||||
|
|
||||||
// Prompt for setting a username
|
|
||||||
let username;
|
let username;
|
||||||
let myUserId;
|
|
||||||
let connected = false;
|
|
||||||
let typing = false;
|
let typing = false;
|
||||||
let lastTypingTime;
|
let lastTypingTime;
|
||||||
|
|
||||||
@ -195,7 +189,7 @@ $(function() {
|
|||||||
|
|
||||||
// Updates the typing event
|
// Updates the typing event
|
||||||
function updateTyping () {
|
function updateTyping () {
|
||||||
if (connected) {
|
if (darkwire.connected) {
|
||||||
if (!typing) {
|
if (!typing) {
|
||||||
typing = true;
|
typing = true;
|
||||||
socket.emit('typing');
|
socket.emit('typing');
|
||||||
@ -237,7 +231,8 @@ $(function() {
|
|||||||
$window.keydown(function (event) {
|
$window.keydown(function (event) {
|
||||||
// When the client hits ENTER on their keyboard and chat message input is focused
|
// When the client hits ENTER on their keyboard and chat message input is focused
|
||||||
if (event.which === 13 && $('.inputMessage').is(':focus')) {
|
if (event.which === 13 && $('.inputMessage').is(':focus')) {
|
||||||
sendMessage();
|
let message = cleanInput($inputMessage.val());
|
||||||
|
darkwire.sendMessage(message, 'chat');
|
||||||
socket.emit('stop typing');
|
socket.emit('stop typing');
|
||||||
typing = false;
|
typing = false;
|
||||||
}
|
}
|
||||||
@ -278,203 +273,34 @@ $(function() {
|
|||||||
|
|
||||||
// Whenever the server emits 'login', log the login message
|
// Whenever the server emits 'login', log the login message
|
||||||
socket.on('user joined', function (data) {
|
socket.on('user joined', function (data) {
|
||||||
connected = true;
|
darkwire.connected = true;
|
||||||
addParticipantsMessage(data);
|
addParticipantsMessage(data);
|
||||||
|
let importKeysPromises = darkwire.addUser(data);
|
||||||
let importKeysPromises = [];
|
Promise.all(importKeysPromises).then(() => {
|
||||||
|
|
||||||
// Import all user keys if not already there
|
|
||||||
_.each(data.users, function(user) {
|
|
||||||
if (!_.findWhere(users, {id: user.id})) {
|
|
||||||
let promise = new Promise(function(resolve, reject) {
|
|
||||||
let currentUser = user;
|
|
||||||
Promise.all([
|
|
||||||
cryptoUtil.importPrimaryKey(currentUser.publicKey, "spki")
|
|
||||||
])
|
|
||||||
.then(function(keys) {
|
|
||||||
users.push({
|
|
||||||
id: currentUser.id,
|
|
||||||
username: currentUser.username,
|
|
||||||
publicKey: keys[0]
|
|
||||||
});
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
importKeysPromises.push(promise);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!myUserId) {
|
|
||||||
// Set my id if not already set
|
|
||||||
let me = _.findWhere(data.users, {username: username});
|
|
||||||
myUserId = me.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all(importKeysPromises)
|
|
||||||
.then(function() {
|
|
||||||
// All users' keys have been imported
|
// All users' keys have been imported
|
||||||
if (data.numUsers === 1) {
|
if (data.numUsers === 1) {
|
||||||
$('#first-modal').modal('show');
|
$('#first-modal').modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
log(data.username + ' joined');
|
log(data.username + ' joined');
|
||||||
|
|
||||||
renderParticipantsList();
|
renderParticipantsList();
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sends a chat message
|
|
||||||
function sendMessage () {
|
|
||||||
// Don't send unless other users exist
|
|
||||||
if (users.length <= 1) return;
|
|
||||||
|
|
||||||
let message = $inputMessage.val();
|
|
||||||
// Prevent markup from being injected into the message
|
|
||||||
message = cleanInput(message);
|
|
||||||
// if there is a non-empty message and a socket connection
|
|
||||||
if (message && connected) {
|
|
||||||
$inputMessage.val('');
|
|
||||||
$('#send-message-btn').removeClass('active');
|
|
||||||
addChatMessage({
|
|
||||||
username: username,
|
|
||||||
message: message
|
|
||||||
});
|
});
|
||||||
let vector = cryptoUtil.crypto.getRandomValues(new Uint8Array(16));
|
|
||||||
|
|
||||||
let secretKey;
|
|
||||||
let secretKeys;
|
|
||||||
let messageData;
|
|
||||||
let signature;
|
|
||||||
let signingKey;
|
|
||||||
let encryptedMessageData;
|
|
||||||
|
|
||||||
// Generate new secret key and vector for each message
|
|
||||||
cryptoUtil.createSecretKey()
|
|
||||||
.then(function(key) {
|
|
||||||
secretKey = key;
|
|
||||||
return cryptoUtil.createSigningKey();
|
|
||||||
})
|
|
||||||
.then(function(key) {
|
|
||||||
signingKey = key;
|
|
||||||
// Generate secretKey and encrypt with each user's public key
|
|
||||||
let promises = [];
|
|
||||||
_.each(users, function(user) {
|
|
||||||
// If not me
|
|
||||||
if (user.username !== window.username) {
|
|
||||||
let promise = new Promise(function(resolve, reject) {
|
|
||||||
let thisUser = user;
|
|
||||||
|
|
||||||
let secretKeyStr;
|
|
||||||
|
|
||||||
// Export secret key
|
|
||||||
cryptoUtil.exportKey(secretKey, "raw")
|
|
||||||
.then(function(data) {
|
|
||||||
return cryptoUtil.encryptSecretKey(data, thisUser.publicKey);
|
|
||||||
})
|
|
||||||
.then(function(encryptedSecretKey) {
|
|
||||||
let encData = new Uint8Array(encryptedSecretKey);
|
|
||||||
secretKeyStr = cryptoUtil.convertArrayBufferViewToString(encData);
|
|
||||||
// Export HMAC signing key
|
|
||||||
return cryptoUtil.exportKey(signingKey, "raw");
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
// Encrypt signing key with user's public key
|
|
||||||
return cryptoUtil.encryptSigningKey(data, thisUser.publicKey);
|
|
||||||
})
|
|
||||||
.then(function(encryptedSigningKey) {
|
|
||||||
let encData = new Uint8Array(encryptedSigningKey);
|
|
||||||
var str = cryptoUtil.convertArrayBufferViewToString(encData);
|
|
||||||
resolve({
|
|
||||||
id: thisUser.id,
|
|
||||||
secretKey: secretKeyStr,
|
|
||||||
encryptedSigningKey: str
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
promises.push(promise);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return Promise.all(promises);
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
secretKeys = data;
|
|
||||||
messageData = cryptoUtil.convertStringToArrayBufferView(message);
|
|
||||||
return cryptoUtil.signKey(messageData, signingKey);
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
signature = data;
|
|
||||||
return cryptoUtil.encryptMessage(messageData, secretKey, vector);
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
encryptedMessageData = data;
|
|
||||||
let msg = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(encryptedMessageData));
|
|
||||||
let vct = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(vector));
|
|
||||||
let sig = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(signature));
|
|
||||||
socket.emit('new message', {
|
|
||||||
message: msg,
|
|
||||||
vector: vct,
|
|
||||||
secretKeys: secretKeys,
|
|
||||||
signature: sig
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whenever the server emits 'new message', update the chat body
|
// Whenever the server emits 'new message', update the chat body
|
||||||
socket.on('new message', function (data) {
|
socket.on('new message', function (data) {
|
||||||
// Don't show messages if no key
|
// Don't show messages if no key
|
||||||
if (!windowHandler.isActive) {
|
if (!windowHandler.isActive) {
|
||||||
windowHandler.notifyFavicon();
|
windowHandler.notifyFavicon();
|
||||||
audio.play();
|
darkwire.audio.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = data.message;
|
let decoded = darkwire.decode(data);
|
||||||
let messageData = cryptoUtil.convertStringToArrayBufferView(message);
|
decoded.then( (data) => {
|
||||||
let username = data.username;
|
console.log(data);
|
||||||
let senderId = data.id
|
|
||||||
let vector = data.vector;
|
|
||||||
let vectorData = cryptoUtil.convertStringToArrayBufferView(vector);
|
|
||||||
let secretKeys = data.secretKeys;
|
|
||||||
let decryptedMessageData;
|
|
||||||
let decryptedMessage;
|
|
||||||
|
|
||||||
let mySecretKey = _.find(secretKeys, function(key) {
|
|
||||||
return key.id === myUserId;
|
|
||||||
});
|
|
||||||
let signature = data.signature;
|
|
||||||
let signatureData = cryptoUtil.convertStringToArrayBufferView(signature);
|
|
||||||
let secretKeyArrayBuffer = cryptoUtil.convertStringToArrayBufferView(mySecretKey.secretKey);
|
|
||||||
let signingKeyArrayBuffer = cryptoUtil.convertStringToArrayBufferView(mySecretKey.encryptedSigningKey);
|
|
||||||
|
|
||||||
cryptoUtil.decryptSecretKey(secretKeyArrayBuffer, keys.private)
|
|
||||||
.then(function(data) {
|
|
||||||
return cryptoUtil.importSecretKey(new Uint8Array(data), "raw");
|
|
||||||
})
|
})
|
||||||
.then(function(data) {
|
|
||||||
let secretKey = data;
|
|
||||||
return cryptoUtil.decryptMessage(messageData, secretKey, vectorData);
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
decryptedMessageData = data;
|
|
||||||
decryptedMessage = cryptoUtil.convertArrayBufferViewToString(new Uint8Array(data))
|
|
||||||
return cryptoUtil.decryptSigningKey(signingKeyArrayBuffer, keys.private)
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
return cryptoUtil.importSigningKey(new Uint8Array(data), "raw");
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
let signingKey = data;
|
|
||||||
return cryptoUtil.verifyKey(signatureData, decryptedMessageData, signingKey);
|
|
||||||
})
|
|
||||||
.then(function(bool) {
|
|
||||||
if (bool) {
|
|
||||||
addChatMessage({
|
|
||||||
username: username,
|
|
||||||
message: decryptedMessage
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Whenever the server emits 'user left', log it in the chat body
|
// Whenever the server emits 'user left', log it in the chat body
|
||||||
@ -518,7 +344,7 @@ $(function() {
|
|||||||
|
|
||||||
function renderParticipantsList() {
|
function renderParticipantsList() {
|
||||||
$('#participants-modal ul.users').empty();
|
$('#participants-modal ul.users').empty();
|
||||||
_.each(users, function(user) {
|
_.each(darkwire.users, function(user) {
|
||||||
let li;
|
let li;
|
||||||
if (user.username === window.username) {
|
if (user.username === window.username) {
|
||||||
// User is me
|
// User is me
|
||||||
@ -532,7 +358,10 @@ $(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('#send-message-btn').click(function() {
|
$('#send-message-btn').click(function() {
|
||||||
sendMessage();
|
let message = $inputMessage.val();
|
||||||
|
// Prevent markup from being injected into the message
|
||||||
|
message = cleanInput(message);
|
||||||
|
darkwire.sendMessage(message, 'chat');
|
||||||
socket.emit('stop typing');
|
socket.emit('stop typing');
|
||||||
typing = false;
|
typing = false;
|
||||||
});
|
});
|
||||||
@ -544,7 +373,7 @@ $(function() {
|
|||||||
let audioSwitch = $('input.bs-switch').bootstrapSwitch();
|
let audioSwitch = $('input.bs-switch').bootstrapSwitch();
|
||||||
|
|
||||||
audioSwitch.on('switchChange.bootstrapSwitch', function(event, state) {
|
audioSwitch.on('switchChange.bootstrapSwitch', function(event, state) {
|
||||||
audio.soundEnabled = state;
|
darkwire.audio.soundEnabled = state;
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
import FileHandler from './fileHandler';
|
||||||
|
|
||||||
export default class WindowHandler {
|
export default class WindowHandler {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._isActive = false;
|
this._isActive = false;
|
||||||
|
this.fileHandler = new FileHandler();
|
||||||
|
|
||||||
this.newMessages = 0;
|
this.newMessages = 0;
|
||||||
this.favicon = new Favico({
|
this.favicon = new Favico({
|
||||||
@ -8,6 +11,7 @@ export default class WindowHandler {
|
|||||||
type : 'rectangle'
|
type : 'rectangle'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.enableFileTransfer();
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +29,15 @@ export default class WindowHandler {
|
|||||||
this.favicon.badge(this.newMessages);
|
this.favicon.badge(this.newMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableFileTransfer() {
|
||||||
|
if (this.fileHandler.isSupported) {
|
||||||
|
$('#send-file').click((e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
$('#fileInput').trigger('click');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bindEvents() {
|
bindEvents() {
|
||||||
window.onfocus = () => {
|
window.onfocus = () => {
|
||||||
this._isActive = true;
|
this._isActive = true;
|
||||||
|
@ -222,11 +222,12 @@ input {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
html.no-touchevents .chat #input-icons {
|
html.no-touchevents .chat #input-icons {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
.chat #input-icons #send-message-btn {
|
.chat #input-icons #send-message-btn, .chat #input-icons #send-file {
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
color: white;
|
color: white;
|
||||||
@ -291,3 +292,7 @@ html.no-touchevents .chat #input-icons {
|
|||||||
background: #2a9fd6 !important;
|
background: #2a9fd6 !important;
|
||||||
border-color: #2a9fd6 !important;
|
border-color: #2a9fd6 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fileSendForm {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ class Room {
|
|||||||
username: socket.username,
|
username: socket.username,
|
||||||
id: socket.user.id,
|
id: socket.user.id,
|
||||||
message: data.message,
|
message: data.message,
|
||||||
|
messageType: data.messageType,
|
||||||
vector: data.vector,
|
vector: data.vector,
|
||||||
secretKeys: data.secretKeys,
|
secretKeys: data.secretKeys,
|
||||||
signature: data.signature
|
signature: data.signature
|
||||||
|
@ -55,6 +55,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<input class="inputMessage" placeholder="Type here..."/>
|
<input class="inputMessage" placeholder="Type here..."/>
|
||||||
<div id="input-icons">
|
<div id="input-icons">
|
||||||
|
<span class="glyphicon glyphicon-file" id="send-file"></span>
|
||||||
|
<input type="file" id="fileInput">
|
||||||
<span class="glyphicon glyphicon-send" id="send-message-btn" aria-hidden="true"></span>
|
<span class="glyphicon glyphicon-send" id="send-message-btn" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user