Cipher.js for Bun, Node, and Browsers
Because you don't have to be an expert to use cryptography!
- Keys can be 128-, 192-, or 256-bit (16, 24, or 32 bytes)
- Plain input can be raw
Uint8Array
s or (UTF-8)String
s - Encrypted output can be
Base64UrlSafe
Strings, or rawUint8Array
s
- Example
- Generate a Key
- Initialize the Cipher (Codec)
- Encrypt (Cipher) Data
- Decrypt (Decipher) Data
- Convert between Bytes, Hex, Base64, and URL-Safe Base64
- API
- Implementation Details
Encrypt and Decrypt with AES-GCM.
let Cipher = require("@root/cipher");
let cipher = Cipher.create(sharedSecret);
let plainBytes = [0xde, 0xad, 0xbe, 0xef];
let encBase64UrlSafe = cipher.encrypt(plainBytes);
let originalBytes = Cipher.decrypt(encBase64UrlSafe);
Copy-and-Paste Snippets for the Masses
// Generate a 128-bit, 192-bit, or 256-bit AES secret:
let secretBytes = new Uint8Array(16); // or 24, or 32
crypto.getRandomValues(secretBytes);
let secretHex = Cipher.utils.bytesTohex(secretBytes);
let secretHex = process.env.APP_SECRET_KEY;
let secretBytes = Cipher.utils.hexToBytes(secretHex);
let cipher = Cipher.create(sharedSecret);
let plainBytes = [0xde, 0xad, 0xbe, 0xef];
let encBase64UrlSafe = cipher.encrypt(plainBytes);
console.info("Encrypted (URL-Safe Base64)", encBase64UrlSafe);
let plainText = "123-45-6789";
let encBase64UrlSafe = cipher.encryptString(plainText);
console.info("Encrypted (URL-Safe Base64)", encBase64UrlSafe);
let plainBytes = [0xde, 0xad, 0xbe, 0xef];
let encBytes = cipher.encryptAsBytes(plainBytes);
console.info("Encrypted (Bytes)", encBytes);
let plainText = "123-45-6789";
let encBytes = cipher.encryptStringAsBytes(plainText);
console.info("Encrypted (Bytes)", encBytes);
let bytes = cipher.decrypt(encBase64UrlSafe);
console.info("Plain (Bytes)", bytes);
let bytes = cipher.decryptBytes(encBytes);
console.info("Plain (Bytes)", bytes);
let text = cipher.decryptToString(encBase64UrlSafe);
console.info("Plain (Text)", text);
let text = cipher.decryptBytesToString(encBytes);
console.info("Plain (Text)", text);
Doing what Uint8Array
should do, but doesn't.
let hex = Cipher.utils.bytesToHex(bytes);
let bytes = Cipher.utils.hexToBytes(hex);
let base64 = Cipher.utils.bytesToBase64(bytes);
let bytes = Cipher.utils.base64ToBytes(base64);
let base64urlsafe = Cipher.utils.bytesToUrlSafe(bytes);
let bytes = Cipher.utils.urlSafeToBytes(base64urlsafe);
Cipher.create(keyBytes) => cipher instance
cipher.encrypt(bytes) => Promise<Base64UrlSafe>
cipher.encryptString(string) => Promise<Base64UrlSafe>
cipher.encryptAsBytes(bytes) => Promise<Uint8Array>
cipher.encryptStringAsBytes(string) => Promise<Uint8Array>
cipher.decrypt(encrypted) => Promise<Uint8Array>
cipher.decryptToString(encrypted) => Promise<Base64UrlSafe>
cipher.decryptBytes(encBytes) => Promise<Uint8Array>
cipher.decryptBytesToString(encBytes) => Promise<Base64UrlSafe>
Cipher.utils.bytesToHex(bytes) => hex string
Cipher.utils.hexToBytes(hex) => bytes
Cipher.utils.bytesToBase64(bytes) => base64
Cipher.utils.base64ToBytes(base64) => bytes
Cipher.utils.bytesToUrlSafe(bytes) => url-safe base64 string
Cipher.utils.urlSafeToBytes(url64) => bytes
The Initialization Vector (IV) is a salt that prevents known-plaintext attacks - meaning that if you encrypt the same message with the same key twice, you get a different encrypted output.
The first 12-bytes (96-bits) are for the IV. The following bytes are the data and the Tag.
If the data is somehow corrupted or truncated, but the first bytes are intact, it may be possible to use the IV to restore some of the partial data (though Tag verification will likely fail).
Copyright 2021-Present Root, Inc
This Source Code Form is subject to the terms of the Mozilla
Public License, v. 2.0. If a copy of the MPL was not distributed
with this file, You can obtain one at
https://mozilla.org/MPL/2.0/.