Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Javascript / Node.js end-to-end encryption
<html>
<head>
<!-- The following package is required https://www.npmjs.com/package/simple-free-encryption-tool -->
<script src="js/windowSfet.js"></script>
<script language="javascript">
// SECURITY_LEVEL is the encryption key size in bits
let SECURITY_LEVEL = 2048;
// internet explorer can't handle 2048 bit key generation in a reasonable amount of time, so we use 1024 bit.
// this will have minimal impact as the credentials are secured using an externally transmitted verification
// code and cracking the client->server comms won't (usually) compromise server->client comms
// if client->server comms being compromised is a serious problem, then simply force the user to wait
if ((window.navigator.userAgent.indexOf('MSIE') > 0) ||
(window.navigator.userAgent.indexOf('Trident/7') > 0) ||
(window.navigator.userAgent.indexOf('Edge/') > 0)) {
SECURITY_LEVEL = 1024;
}
// RSA keys used to secure the session
let keys = {
client: {},
server: {}
};
// generate the client's keys for the session
function generateSessionKeys {
console.log('generating ' + SECURITY_LEVEL + '-bit key pair...');
keys.client = sfet.rsa.generateKeysSync(SECURITY_LEVEL);
console.log('Keys Generated in ' + keys.client.time);
}
// load existing session keys from storage or generate new keys
function loadSessionKeys() {
// ensure html5 storage available
if (typeof (Storage) !== "undefined") {
if (sessionStorage.RSAKeys) {
keys = JSON.parse(sessionStorage.RSAKeys);
console.log('client keys loaded from session storage');
} else {
generateSessionKeys();
sessionStorage.RSAKeys = JSON.stringify(keys);
console.log('session keys saved to storage');
}
} else {
console.log('Sorry! No Web Storage support..');
// it's possible to continue with new keys generated per page,
// but then you'll have to repeat the key exchange with a new code
}
}
function packMessageData(data) {
data = JSON.stringify(data);
let packedData = {};
// generate aes secret
let aesSecret = sfet.utils.randomstring.generate();
try {
// add RSA-encrypted aes secret to output
packedData.key = sfet.rsa.encrypt(keys.server.public, aesSecret);
// add encrypted data to output
packedData.encrypted = sfet.aes.encrypt(aesSecret, data);
return packedData;
} catch (dataEncryptionException) {
console.log('failed to pack message: ' + dataEncryptionException.message);
return {};
}
}
function unpackMessageData(data) {
var secret = sfet.rsa.decrypt(keys.client.private, data.key);
var message = JSON.parse(sfet.aes.decrypt(secret, data.encrypted));
}
</script>
</head>
<body>
</body>
</html>
var sfet = require('simple-free-encryption-tool');
var SECURITY_LEVEL = 2048;
// generate shared secret for session authentication
var generateSessionSecret = function () {
// number between 4 and 8
var secretLength = Math.floor((Math.random() * 5) + 4);
// session secret must not include ambiguous characters like O/0, 1/l
var secret = sfet.utils.randomstring.generate({
length: secretLength,
readable: true
});
return secret;
};
function pack(data) {
data = JSON.stringify(data);
var packedData = {};
// generate aes key
let aesSecret = sfet.utils.randomstring.generate();
// add encrypted aes key to output
packedData.key = sfet.rsa.encrypt(clientPublicKey, aesSecret);
// add encrypted data to output
packedData.encrypted = sfet.aes.encrypt(aesSecret, data);
return packedData;
}
function unpack(data) {
var aesSecret = sfet.rsa.decrypt(serverPrivateKey, data.key);
return sfet.aes.decrypt(aesSecret, data.encrypted);
}
@rasheshved

This comment has been minimized.

Copy link

@rasheshved rasheshved commented Aug 16, 2017

Can you please explain y does it require to both encrypt,decrypt data on both server,client side?
Also Where this pem files for client is being stored(location)

@therightstuff

This comment has been minimized.

Copy link
Owner Author

@therightstuff therightstuff commented May 11, 2018

This is required to create an encrypted bi-directional channel between client and server. For initialization, the client sends it's RSA key AES-encrypted to the server using a secret delivered by a second-factor authentication device (email, sms), and the server responds in the regular format with a randomly generated message key encrypted with the RSA key and the payload encrypted with the message key.

The keys are generated when initializing the session and are stored in memory - in the browser I use HTML5's local storage, on the server I store it in a database or cached.

@TheLox95

This comment has been minimized.

Copy link

@TheLox95 TheLox95 commented May 25, 2020

This code still works with the new versions of the libraries used? You should specify the version used. It would be nice to have an example on how to use it. Currently I'm trying to encrypt/decrypt a json only on fron-end using the packMessageData/unpackMessageData to test this example and it only gives me non-redable string like this 熡yB6 A文+ķǓ1z-؂t-\m_ѰO@3}y(ꂛ/*堺i鷍%婅b꺦㷬뮡D䥭趣k 㱸Ń͞A6_s녻囀

@therightstuff

This comment has been minimized.

Copy link
Owner Author

@therightstuff therightstuff commented May 30, 2020

This code still works with the new versions of the libraries used? You should specify the version used. It would be nice to have an example on how to use it. Currently I'm trying to encrypt/decrypt a json only on fron-end using the packMessageData/unpackMessageData to test this example and it only gives me non-redable string like this 熡yB6 A文+ķǓ1z-؂t-\m_ѰO@3}y(ꂛ/*堺i鷍%婅b꺦㷬뮡D䥭趣k 㱸Ń͞A6_s녻囀

I haven't looked at this in years, but I have built the simple-free-encryption-tool that can be used to replace a lot of this functionality.

@therightstuff

This comment has been minimized.

Copy link
Owner Author

@therightstuff therightstuff commented May 30, 2020

This code still works with the new versions of the libraries used? You should specify the version used. It would be nice to have an example on how to use it. Currently I'm trying to encrypt/decrypt a json only on fron-end using the packMessageData/unpackMessageData to test this example and it only gives me non-redable string like this 熡yB6 A文+ķǓ1z-؂t-\m_ѰO@3}y(ꂛ/*堺i鷍%婅b꺦㷬뮡D䥭趣k 㱸Ń͞A6_s녻囀

Hey @TheLox95, I've just updated this gist to use the tool that those original functions were turned into, the code will work and it will run client-side, in node.js, and it's also compatible with C# (the gists for those are in the sfet README and source)

@amitojsingh366

This comment has been minimized.

Copy link

@amitojsingh366 amitojsingh366 commented Jan 4, 2021

What are clientPublicKey and serverPrivateKey in server.js. And how do i obtain them... Sorry if its a dumb question, I'm very new to encryption

@therightstuff

This comment has been minimized.

Copy link
Owner Author

@therightstuff therightstuff commented Jan 5, 2021

What are clientPublicKey and serverPrivateKey in server.js. And how do i obtain them... Sorry if its a dumb question, I'm very new to encryption

You can review the documentation at https://github.com/therightstuff/simple-free-encryption-tool#readme for details on how to generate keys using the simple-free-encryption-tool, but if you're not familiar with the fundamentals of public / private key encryption you should probably look that up first

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment