systemquery/src/lib/crypto/secretbox.mjs

58 lines
1.8 KiB
JavaScript

"use strict";
import tweetnacl from 'tweetnacl';
const { randomBytes, secretbox } = tweetnacl;
/**
* Creates a new key ready for encryption.
* @return {string} A new base64-encoded key.
*/
function make_key() {
return Buffer.from(randomBytes(secretbox.keyLength)).toString("base64");
}
/**
* Encrypts the given data with the given key.
* @param {string} key The base64-encoded key to use to encrypt the data.
* @param {string} data The data to encrypt.
* @return {string} The encrypted data, base64 encoded.
*/
function encrypt(key, data) {
const key_bytes = Buffer.from(key, "base64");
const nonce = randomBytes(secretbox.nonceLength);
const data_bytes = Buffer.from(data, "utf-8");
const cipher_bytes = secretbox(data_bytes, nonce, key_bytes);
const concat_bytes = Buffer.concat([nonce, cipher_bytes]);
key_bytes.fill(0);
nonce.fill(0);
return Buffer.from(concat_bytes).toString("base64");
}
/**
* Decrypts the given data with the given key.
* @param {string} key The base64-encoded keyto use to decrypt the data.
* @param {string} cipher_text The base64-encoded ciphertext to decrypt.
* @return {string} The decoded data, utf-8 encoded.
*/
function decrypt(key, cipher_text) {
const concat_bytes = Buffer.from(cipher_text, "base64");
const key_bytes = Buffer.from(key, "base64");
const nonce = concat_bytes.slice(0, secretbox.nonceLength);
const cipher_bytes = concat_bytes.slice(secretbox.nonceLength);
const data_bytes = secretbox.open(cipher_bytes, nonce, key_bytes);
// Failed to decrypt message. Could be because the nonce, key, or ciphertext is invalid
// Ref https://github.com/dchest/tweetnacl-js/blob/master/test/04-secretbox.quick.js
// Ref https://github.com/dchest/tweetnacl-js/wiki/Examples#secretbox
if(!data_bytes) return null;
return Buffer.from(data_bytes).toString("utf-8");
}
export { make_key, encrypt, decrypt };