sodium-crypter

1.1.4 • Public • Published

sodium-crypter

sodium-crypter is a robust and secure package designed for encryption and decryption of data. It leverages the power of the Sodium cryptographic library to provide high-level encryption standards. This package is ideal for handling sensitive data, ensuring it remains secure during storage and transmission. It offers easy-to-use functions for encrypting and decrypting data, making it a go-to choice for developers needing reliable cryptographic operations in their applications.

Table of Contents

Prerequisites

Before you begin, ensure you have met the following requirements:

  • You have installed the latest version of Node.js and npm.
  • You are familiar with JavaScript and Node.js package management.

Back To The Top

Installation

To install sodium-crypter, follow these steps:

  1. Open your terminal.
  2. Use npm to install the package:
npm install sodium-crypter

Back To The Top

How to Use

Symmetric Encryption and Decryption

Here's a proper example for symmetric encryption and decryption or check ./examples/symmetric.test.js:

const fs = require("fs").promises;
const {
  CHUNK_SIZE,
  crypto_secretstream_xchacha20poly1305_ABYTES,
} = require("sodium-crypter/config/constants.js");
const serviceWorker = require("sodium-crypter/worker/serviceWorker.js");
const generatePassword = require("sodium-crypter/utils/generatePassword.js");
const passwordStrengthCheck = require("sodium-crypter/utils/passwordStrengthCheck.js");
const formatBytes = require("sodium-crypter/helpers/formatBytes.js");
let password, encryptedData, decryptedData;

async function encryption() {
  const filePath = "./path/to/your/data"; // path to file
  const fileContents = await fs.readFile(filePath);
  const fileName = await serviceWorker.assignFileNameEnc({ name: filePath });

  password = await generatePassword(); // Generate password
  if (!password.status) throw new Error(password.message);

  await passwordStrengthCheck({ password: password.data }); // Check password strength

  const fileSize = formatBytes(fileContents.length); // Get file size
  const encKey = await serviceWorker.encKeyGenerator({
    password: password.data,
  }); // Generate encryption key
  if (!encKey.status) throw new Error(encKey.message);

  // Encrypt file in chunks
  for (let index = 0; index < fileContents.length; index += CHUNK_SIZE) {
    const chunk = fileContents.slice(index, index + CHUNK_SIZE);
    const last = index + CHUNK_SIZE >= fileContents.length;

    encryptedData =
      index === 0
        ? await serviceWorker.encryptFirstChunk({ chunk: chunk, last: last })
        : await serviceWorker.encryptRestOfChunks({ chunk: chunk, last: last });
  }

  if (!encryptedData.status) throw new Error(encryptedData.message);
  await fs.writeFile(
    `./path/to/your/file/${fileName.data}`,
    encryptedData.data
  ); // Write encrypted data to file
}

async function decryption() {
  const startIndex = 51;
  const filePath = "./path/to/your/data"; // path to encrypted file
  const fileContents = await fs.readFile(filePath);
  const fileName = await serviceWorker.assignFileNameDec({ name: filePath });
  const fileSize = formatBytes(fileContents.length);

  const chunk = fileContents.slice(0, startIndex);
  const [signature, salt, header] = [
    chunk.slice(0, 11), // signature
    chunk.slice(11, 27), // salt
    chunk.slice(27, 51), // header
  ];

  const encType = await serviceWorker.checkEncryptionType({
    signature: signature,
  });
  if (!encType.status) throw new Error(encType.message);

  const decKeys = await serviceWorker.decKeyGenerator({
    password: password.data,
    signature: signature,
    salt: salt,
    header: header,
  });
  if (!decKeys.status) throw new Error(decKeys.message);

  if (
    startIndex + CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES >=
    fileContents.length
  ) {
    const fullChunk = fileContents.slice(
      startIndex,
      startIndex + CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES
    );
    const kickOfDecryption = await serviceWorker.testDecryption({
      password: password.data,
      signature: signature,
      salt: salt,
      header: header,
      decFileBuff: fullChunk,
    });
  }

  for (
    let i = startIndex;
    i < fileContents.length;
    i += CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES
  ) {
    const chunk = fileContents.slice(
      i,
      i + CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES
    );
    const last =
      i + CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES >=
      fileContents.length;

    decryptedData = await serviceWorker.decryptChunks({
      chunk: chunk,
      last: last,
    });
  }

  if (!decryptedData.status) throw new Error(decryptedData.message);
  await fs.writeFile(
    `./path/to/your/file/${fileName.data}`,
    decryptedData.data
  );
}

async function wait(seconds) {
  return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}

(async () => {
  try {
    await encryption();
    await wait(2); // wait for 2 seconds
    await decryption();
  } catch (error) {
    console.error(error);
  }
})();

This example demonstrates symmetric encryption and decryption. The data is first encrypted using the symmetricEncrypt function and then decrypted using the symmetricDecrypt function.

Back To The Top

Asymmetric Encryption and Decryption

Here's a proper example for asymmetric encryption and decryption or check ./examples/symmetric.test.js:

const fs = require("fs").promises;
const formatBytes = require("sodium-crypter/helpers/formatBytes.js");
const serviceWorker = require("sodium-crypter/worker/serviceWorker.js");
const {
  CHUNK_SIZE,
  crypto_secretstream_xchacha20poly1305_ABYTES,
} = require("sodium-crypter/config/constants.js");
const generateAsymmetricKeys = require("sodium-crypter/utils/generateAsymmetricKeys.js");
let senderKeys, receiverKeys;

async function encryption() {
  const filePath = "./path/to/your/data"; // path to file
  const fileContents = await fs.readFile(filePath);
  const fileName = await serviceWorker.assignFileNameEnc({ name: filePath });

  senderKeys = await generateAsymmetricKeys(); // Generate sender keys
  if (!senderKeys.status) throw new Error(senderKeys.message);

  receiverKeys = await generateAsymmetricKeys(); // Generate receiver keys
  if (!receiverKeys.status) throw new Error(receiverKeys.message);

  const fileSize = formatBytes(fileContents.length);
  const encKeyPair = await serviceWorker.encKeyPair({
    ssk: senderKeys.data.privateKey,
    rpk: receiverKeys.data.publicKey,
    mode: "derive",
  });
  if (!encKeyPair.status) throw new Error(encKeyPair.message);

  let encryptedData;
  for (let index = 0; index < fileContents.length; index += CHUNK_SIZE) {
    const chunk = fileContents.slice(index, index + CHUNK_SIZE);
    const last = index + CHUNK_SIZE >= fileContents.length;

    encryptedData =
      index === 0
        ? await serviceWorker.asymmetricEncryptFirstChunk({
            chunk: chunk,
            last: last,
          })
        : await serviceWorker.encryptRestOfChunks({ chunk: chunk, last: last });
  }

  if (!encryptedData.status) throw new Error(encryptedData.message);
  console.log("encrypted data: ", encryptedData.data, "file size: ", fileSize);
  await fs.writeFile(
    `./path/to/your/file/${fileName.data}`,
    encryptedData.data
  );
}

async function decryption() {
  const startIndex = 35;
  const filePath = "/path/to/your/data"; // path to encrypted file
  const fileContents = await fs.readFile(filePath);
  const fileName = await serviceWorker.assignFileNameDec({ name: filePath });
  const fileSize = formatBytes(fileContents.length);

  const chunk = fileContents.slice(0, startIndex);
  const [signature, header] = [
    chunk.slice(0, 11), // signature
    chunk.slice(11, startIndex), // header
  ];

  const encType = await serviceWorker.checkEncryptionType({
    signature: signature,
  });
  if (!encType.status) throw new Error(encType.message);

  let decryptedData;
  for (
    let i = startIndex;
    i < fileContents.length;
    i += CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES
  ) {
    const chunk = fileContents.slice(
      i,
      i + CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES
    );
    const last =
      i + CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES >=
      fileContents.length;

    if (i === startIndex) {
      const decKeyPair = await serviceWorker.requestDecKeyPair({
        rsk: receiverKeys.data.privateKey,
        spk: senderKeys.data.publicKey,
        header: header,
        decFileBuff: chunk,
        mode: "derive",
      });
      if (!decKeyPair.status) throw new Error(decKeyPair.message);
    }

    decryptedData = await serviceWorker.decryptChunks({
      chunk: chunk,
      last: last,
    });
  }

  if (!decryptedData.status) throw new Error(decryptedData.message);
  console.log("file size: ", fileSize);
  await fs.writeFile(`/path/to/your/file/${fileName.data}`, decryptedData.data);
}

async function wait(seconds) {
  return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}

(async () => {
  try {
    await encryption();
    console.log("Start");
    await wait(2); // wait for 2 seconds
    console.log("End");
    await decryption();
  } catch (error) {
    console.error(error);
  }
})();

This example demonstrates asymmetric encryption and decryption. Key pairs are generated for the sender and receiver. The data is then encrypted using the sender's private key and the receiver's public key, and decrypted using the receiver's private key and the sender's public key.

Back To The Top

Author

This project is created and maintained by XpeedStudio.

Back To The Top

License

Copyright © 2024 XpeedStudio

sodium-crypter is licensed under the GNU General Public License v3.0.

Back To The Top

References

This project makes use of the hat.sh web application for encryption and decryption. You can find the source code for hat.sh on its GitHub repository.

Back To The Top

Contributors

Thanks goes to these wonderful people:

mdmuhtasimfuadfahim
emranio
mahmudsagar

Back To The Top


Package Sidebar

Install

npm i sodium-crypter

Weekly Downloads

4

Version

1.1.4

License

GPL

Unpacked Size

261 kB

Total Files

31

Last publish

Collaborators

  • xpeedstudio