React E2EE
An end-to-end encryption package that is basically a wrapper package of SubtleCrypto
library for browsers. See MDN.
Installation
Use the package manager npm to install react-e2ee.
npm install @chatereum/react-e2ee
Run test cases
npm run test
What's New? 🔥
Changelogs v3.0.0
-
encrypt
,decrypt
,encryptFile
anddecryptFile
functions are now deprecated. However, you can still use these functions. - added
encryptPlaintext
,decryptForPlaintext
,encryptFileBuffer
anddecryptFileBuffer
functions to replace corresponding deprecated functions. These functions will be improved in terms of performance and better error handling in future releases. - added test cases using
jest
- added better typescript documentation and intellisense
Usage
General usage
import E2EE from '@chatereum/react-e2ee';
//generates a RSA-OAEP private key and public key in PEM format
const keys = await E2EE.getKeys();
/*
would return something like:
{
private_key : "-----BEGIN PRIVATE KEY-----...", //PEM
public_key : "-------BEGIN PUBLIC KEY-----...." //PEM
}
*/
//encrypts any string format message
//if you want to encrypt a format other than string, convert it into string first
const message = "Made with 💙 by Arjis Chakraborty";
const encrypted = await E2EE.encryptPlaintext({
public_key: keys.public_key,
plain_text: message,
});
/*
would return something like:
{
cipher_text: /hfan3ulskxzkjr20mckmicurj38rmdkalclalor\dj3*, //base64
aes_key: 9r2hnankal92/*gawaoaowrj38jma/daun, //base64
iv: 1hnfkalmnfinfkeif874fsf&bbdajwk9dkacam //base64
}
you can now wire this entire object to the recipient through eg: WebSockets
*/
//on the receiver's end
//decrypting an encrypted message
const decrypted = await E2EE.decryptForPlaintext({
encrypted_text: encrypted,
private_key: keys.private_key,
});
/*
would return the original message:
decrypted = "Made with 💙 by Arjis Chakraborty"
you can now show this message on the recipient's frontend
*/
End-to-end encrypting files
import E2EE from '@chatereum/react-e2ee';
//encrypts any buffer format file
const file_buffer = new ArrayBuffer(16); //this should be the file in buffer format
const encrypted = await E2EE.encryptFileBuffer({
public_key: keys.public_key,
file_buffer,
});
/*
would return something like:
{
cipher_buffer: ArrayBuffer { byteLength: 16 }, //ArrayBuffer
aes_key: 9r2hnankal92/*gawaoaowrj38jma/daun, //base64
iv: 1hnfkalmnfinfkeif874fsf&bbdajwk9dkacam //base64
}
you can now wire this entire object to the recipient through eg: WebSockets
*/
//on the receiver's end
//decrypting an encrypted file
const decrypted = await E2EE.decryptFileBuffer({
encrypted_buffer: encrypted,
private_key: keys.private_key,
});
/*
would return the original message:
decrypted = ArrayBuffer { byteLength: 16 }
you can now use this ArrayBuffer to show maybe an image by converting it to a base64 data URL
*/
v2.0
Note: If you are using deprecated functions in your code, check out the documentation for How it works
-
We generate a private and public
RSA-OAEP
keys usinggetKeys()
function -
We get the raw string message that needs to be encrypted (usually referred to as
plainText
) -
We then call the
encrypt()
function to encrypt ourplainText
with the RSApublic key
of the recipient. -
Internally, a lot of things are going on in the
encrypt()
function.-
We first
encode
theplainText
using anencoder()
function. Let's call thisencoded
. -
Then we generate a
Diffie-Hellman
shared secret key using theAES-CBC
cipher of length256
. This also requires aiv
padding which is of typeUint8Array
of size16
. Ultimately, we get anAES
key back. Let's call this keyAES
and theiv
padding asIV
. -
Now we take
encoded
and encrypt it usingAES
. This gives us back the encryptedplainText
. Let's call thisencrypted_text
. -
Now we use the
public key
of the recipient to encrypt theAES
key. Let's call thisencrypted_AES
. -
To finish the
encryption
process, we return an object containingencrypted_text
,encrypted_AES
andIV
. We send backIV
because we need this indecrypt()
.
-
-
Now that we have our encrypted message, we can pass this entire object onto our server to further be passed on to the recipient client.
-
On the recipient client, we call the
decrypt()
function. -
Again, internally, we have a lot of stuff going on:
-
The recipients takes its
private key
and tries to decrypt theencrypted_AES
. Let's call thisAES
. -
It then tries to use the
AES
key alongwith theIV
to decryptencrypted_text
. Let's call thisencoded_text
. -
Once we have our
encoded_text
, we need to decode this into human-readable format (UTF-8). -
We run a
text decoder
function to decode theencoded_text
. -
Finally, we have our decoded, human-readable
plainText
.
-
-
This
plainText
is what is displayed to the recipient's frontend. -
You can read more about
End-to-end encryption
here.
Prerequisites
These are some important requirements that you need to make sure before you can use this library:
❗ The website on which you intend to use this library must have a TLS or SSL certificate installed, i.e. it must have support for HTTPS
. Alternatively, for testing purposes, you should access your site over localhost
or else the library won't work.
❗ This library is strictly for browser based Node.js
frameworks and specifically for React
as the name already suggests.
❗ DO NOT ever share your private key
over the "wire". You can only share your public key
to the server side or even directly to your recipient client.
Good to know
💙 This library uses the SubtleCrypto
library which is embedded in the browser. A down side to SubtleCrypto
is that it can't run on an http
connection that doesn't have any TLS
or SSL
certificates. However, localhost
seems to be an exception. You can learn more about the library here.
💙 This library is primarily made for React
and some other browser based Node.js
frameworks but you can fork this repository and use the code on any browser based application you like that supports SubtleCrypto
.
💙 I am working on a few examples to demonstrate the full working of this library. Until then, SubtleCrypto has a lot of documentation to offer.
Contributing
This repository is open to any contributions to make the library a hassle free solution to End-to-End Encryption in browsers.
Made with 💙 by Arjis Chakraborty