chat-server/main.js

326 lines
6.8 KiB
JavaScript
Raw Normal View History

2019-03-24 17:57:54 +11:00
#!/usr/bin/node
// Get some libraries
const random_bytes = require("random-bytes");
const bsplit = require("buffer-split");
const node_rsa = require("node-rsa");
2019-04-09 19:19:02 +10:00
const btoa = require("btoa");
const atob = require("atob");
2019-03-24 17:57:54 +11:00
const net = require("net");
const fs = require("fs");
// Load the settings
var settings = require("./settings.json");
console.log("Ready.");
2019-04-09 19:19:02 +10:00
function toBuffer(bytes)
{
// String
if(typeof(bytes) == 'string')
{
// Create a buffer
var buffer = new Buffer.alloc(bytes.length);
// Loop over the bytes
for(var i=0;i<bytes.length;i++)
{
// Save to the buffer
buffer[i] = bytes[i].charCodeAt(0);
}
// Return the buffer
return buffer;
}
// Return if this is anything else
return bytes;
}
function toBytes(buffer)
{
// Make sure the buffer is a buffer
buffer = toBuffer(buffer);
// Create some bytes
var bytes = "";
// Loop over the buffer
for(var i=0;i<buffer.length;i++)
{
// Add to the bytes string
bytes += String.fromCharCode(buffer[i]);
}
// Return the bytes
return bytes;
}
// Recieve helper global varibles
var recieve_buffer = new Buffer.alloc(0);
var recieve_get = false;
var recieve_size = 0;
function recieve_ordered(data, callback)
{
// Convert the data into a buffer
data = toBuffer(data);
// Loop over the data
for(var i=0;i<data.length;i++)
{
// Add the data to the buffer
recieve_buffer = new Buffer.concat([recieve_buffer, Buffer([data[i]])]);
// Is the buffer getting data
if(!recieve_get)
{
// Does the buffer contain a number
if(recieve_buffer.length >= 4)
{
// Get the number
recieve_size = recieve_buffer.readUInt32BE(0);
// Reset the buffer
recieve_buffer = new Buffer.alloc(0);
// Set the get data mode to true
recieve_get = true;
}
}
else
{
// Is the recieve buffer as big as the size
if(recieve_buffer.length == recieve_size)
{
// Call the callback
callback(recieve_buffer);
// Reset the buffer and the size
recieve_buffer = new Buffer.alloc(0);
recieve_size = 0;
// Set the get data mode to false
recieve_get = false;
}
}
}
}
function send_ordered(data)
{
// Convert the data into a buffer
data = toBuffer(data);
// Get the size of the data
var size = data.length;
// Turn it into a 32 bit buffer
var bytes = new Buffer.alloc(4);
bytes.writeUInt32BE(size, 0);
// Return the buffer and the data
return new Buffer.concat([bytes, data]);
}
function string_decrypt(key, string)
{
// Convert the string to a buffer
2019-04-09 19:19:02 +10:00
var buff = toBuffer(string);
// Create some new data
var decrypted = new Buffer.alloc(buff.length);
// Iterate over the string
for(var i=0;i<string.length;i++)
{
// Convert the string item to a number
var d = buff[i]-key.str[key.at.rx];
while(d < 0) d += 256;
decrypted[i] = d;
// Add 1 to the key counter
key.at.rx += 1;
// Is the key counter out of range
if(key.at.rx >= key.str.length)
{
// Set to zero
key.at.rx = 0;
}
}
// Return the encrypted data
return decrypted;
}
function string_encrypt(key, string)
{
// Convert the string to a buffer
2019-04-09 19:19:02 +10:00
var buff = toBuffer(string);
// Create some new data
var encrypted = new Buffer.alloc(buff.length);
// Iterate over the string
for(var i=0;i<string.length;i++)
{
// Convert the string item to a number
var e = buff[i]+key.str[key.at.tx];
while(e > 255) e -= 256;
encrypted[i] = e;
// Add 1 to the key counter
key.at.tx += 1;
// Is the key counter out of range
if(key.at.tx >= key.str.length)
{
// Set to zero
key.at.tx = 0;
}
}
// Return the encrypted data
return encrypted;
}
function make_encryption_key(string)
{
// Make a new key
var key = new Object();
// Set the varibles
key.str = toBuffer(string);
key.at = new Object();
key.at.rx = 0;
key.at.tx = 0;
console.log("make_encryption_key:", key.str);
// Return the key
return key;
}
function socket_write(socket, data)
{
// Send the data encrypted with JSON
2019-04-09 19:19:02 +10:00
socket.sock.write(send_ordered(string_encrypt(socket.key, JSON.stringify(data)+"\n")));
}
function socket_init(socket, callback, ondata)
{
// Set the socket
var sock = new Object();
sock.sock = socket;
sock.new = true;
console.log("Connection from "+socket.localAdress);
// Wait for data
sock.sock.on('data', function(data)
{
2019-04-09 19:19:02 +10:00
// Recieve data in order
recieve_ordered(data, function(data)
{
2019-04-09 19:19:02 +10:00
console.log(data);
2019-04-09 19:19:02 +10:00
// Is the socket new
if(sock.new)
{
2019-04-09 19:19:02 +10:00
// Set sock new
sock.new = false;
// Convert from JSON
data = JSON.parse(data);
// Is this the public key
if(data.mode == 'pubkey')
{
// Load the key
var key = new node_rsa();
key.importKey(data.key, 'public');
console.log("Loaded the RSA key", data);
// Get some random bytes
random_bytes(settings.encryption_key_size, function(error,string)
{
console.log("btoa(string):",btoa(string));
// Throw an error if there is one
if(error) throw error;
// Make the key
sock.key = make_encryption_key(string);
console.log("Created an encryption key")
// Encrypt the key with RSA
var key_encrypted = key.encrypt(string, 'base64');
console.log("Encrypted the key: ", toBytes(key_encrypted));
2019-04-09 19:19:02 +10:00
// Send the key to the client
sock.sock.write(send_ordered(JSON.stringify({
key: toBytes(key_encrypted),
mode: "encryption_key"
})));
console.log("Sent the key to the client");
});
}
}
2019-04-09 19:19:02 +10:00
else
{
2019-04-09 19:19:02 +10:00
// Decrypt the data
data = string_decrypt(sock.key, data);
console.log(data);
// Parse the json data
var data = JSON.parse(data);
// Is the data status 1
if(data == 1)
{
console.log("Recieved 1");
// Send the callback
callback(sock);
}
else
{
console.log(data);
// Send the parsed data to the callback
ondata(data);
}
}
2019-04-09 19:19:02 +10:00
});
});
// Return the socket
return sock;
}
2019-03-24 17:57:54 +11:00
// Create a server
var server = net.createServer(function(socket)
{
var sock;
2019-03-24 17:57:54 +11:00
// Initialise the socket and wait for data
socket_init(socket, function(socket)
{
socket_write(socket, {message: "From the server! :D", array: [1,2,3,4,6,5,"xD",12]});
sock = socket;
},
function(data)
2019-03-24 17:57:54 +11:00
{
console.log(data);
socket_write(sock, {echo: data});
2019-03-24 17:57:54 +11:00
});
});
// Listen for data
server.listen(22068, '');