Javascript String Encryption and Decryption?

I'm interested in building a small app for personal use that will encrypt and decrypt information on the client side using JavaScript. The encrypted information will be stored in a database on a server, but never the decrypted version.

It doesn't have to be super duper secure, but I would like to use a currently unbroken algorithm.

Ideally I'd be able to do something like

var gibberish = encrypt(string, salt, key);

to generate the encoded string, and something like

var sensical = decrypt(gibberish, key);

to decode it later.

So far I've seen this:

Any other libraries I should look at?

4

12 Answers

 var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
//U2FsdGVkX18ZUVvShFSES21qHsQEqZXMxQ9zgHy+bu0=

var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
//4d657373616765


document.getElementById("demo1").innerHTML = encrypted;
document.getElementById("demo2").innerHTML = decrypted;
document.getElementById("demo3").innerHTML = decrypted.toString(CryptoJS.enc.Utf8);
Full working sample actually is:

    <script src="" integrity="sha256-/H4YS+7aYb9kJ5OKhFYPUjSJdrtV6AeyJOtTkw6X72o=" crossorigin="anonymous"></script>

<br><br>
<label>encrypted</label>
<div id="demo1"></div>
<br>

<label>decrypted</label>
<div id="demo2"></div>

<br>
<label>Actual Message</label>
<div id="demo3"></div>
10

How about CryptoJS?

It's a solid crypto library, with a lot of functionality. It implements hashers, HMAC, PBKDF2 and ciphers. In this case ciphers is what you need. Check out the quick-start quide on the project's homepage.

You could do something like with the AES:

<script src=""></script>

<script>
    var encryptedAES = CryptoJS.AES.encrypt("Message", "My Secret Passphrase");
    var decryptedBytes = CryptoJS.AES.decrypt(encryptedAES, "My Secret Passphrase");
    var plaintext = decryptedBytes.toString(CryptoJS.enc.Utf8);
</script>

As for security, at the moment of my writing AES algorithm is thought to be unbroken

Edit :

Seems online URL is down & you can use the downloaded files for encryption from below given link & place the respective files in your root folder of the application.

or used other CDN like

4

I created an insecure but simple text cipher/decipher utility. No dependencies with any external library.

These are the functions:

const cipher = salt => {
    const textToChars = text => text.split('').map(c => c.charCodeAt(0));
    const byteHex = n => ("0" + Number(n).toString(16)).substr(-2);
    const applySaltToChar = code => textToChars(salt).reduce((a,b) => a ^ b, code);

    return text => text.split('')
      .map(textToChars)
      .map(applySaltToChar)
      .map(byteHex)
      .join('');
}
    
const decipher = salt => {
    const textToChars = text => text.split('').map(c => c.charCodeAt(0));
    const applySaltToChar = code => textToChars(salt).reduce((a,b) => a ^ b, code);
    return encoded => encoded.match(/.{1,2}/g)
      .map(hex => parseInt(hex, 16))
      .map(applySaltToChar)
      .map(charCode => String.fromCharCode(charCode))
      .join('');
}

// To create a cipher
const myCipher = cipher('mySecretSalt')

//Then cipher any text:
console.log(myCipher('the secret string'))

//To decipher, you need to create a decipher and use it:
const myDecipher = decipher('mySecretSalt')
console.log(myDecipher("7c606d287b6d6b7a6d7c287b7c7a61666f"))
11

This code is based on @Jorgeblom's answer above.


@Jorgeblom my man, that's fantastic small crypto lib :D I touch it a bit because I didn't like that I have to assign the salt and to call it again but in general, for my needs is absolutely perfect.

const crypt = (salt, text) => {
  const textToChars = (text) => text.split("").map((c) => c.charCodeAt(0));
  const byteHex = (n) => ("0" + Number(n).toString(16)).substr(-2);
  const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code);

  return text
    .split("")
    .map(textToChars)
    .map(applySaltToChar)
    .map(byteHex)
    .join("");
};

const decrypt = (salt, encoded) => {
  const textToChars = (text) => text.split("").map((c) => c.charCodeAt(0));
  const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code);
  return encoded
    .match(/.{1,2}/g)
    .map((hex) => parseInt(hex, 16))
    .map(applySaltToChar)
    .map((charCode) => String.fromCharCode(charCode))
    .join("");
};

And you use it

// encrypting
const encrypted_text = crypt("salt", "Hello"); // -> 426f666665

// decrypting
const decrypted_string = decrypt("salt", "426f666665"); // -> Hello
4

The existing answers which leverage SJCL, CryptoJS, and/or WebCrypto aren't necessarily wrong but they're not as safe as you might initially suspect. Generally you want to use libsodium. First I'll explain why, then how.

Why Not SJCL, CryptoJS, WebCrypto, etc.?

Short answer: In order for your encryption to actually be secure, these libraries expect you to make too many choices e.g. the block cipher mode (CBC, CTR, GCM; if you can't tell which of the three I just listed is secure to use and under what constraints, you shouldn't be burdened with this sort of choice at all).

Unless your job title is cryptography engineer, the odds are stacked against you implementing it securely.

Maya Lin-Takahashi

Maya Lin-Takahashi

Consumer Tech & Gadget Reviewer

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.