sodium-crypter
v1.1.4
Published
A encryption and decryption tool with secret and public key cryptography
Downloads
18
Maintainers
Readme
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.
Installation
To install sodium-crypter
, follow these steps:
- Open your terminal.
- Use npm to install the package:
npm install sodium-crypter
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.
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.
Author
This project is created and maintained by XpeedStudio.
License
Copyright © 2024 XpeedStudio
sodium-crypter
is licensed under the GNU General Public License v3.0.
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.
Contributors
Thanks goes to these wonderful people:
| | | | | :------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------: |