Convert data into a single encrypted archive data that contains all metadata needed for decryption.
-
Only password and target data are required
Other data required for encryption (nonce, key derivation function, etc.) will be generated automatically.
-
Support for secure algorithms
This package supports only the following algorithms that are currently (2021) recommended.
- Encryption algorithm
- AES-GCM (256-bit)
- ChaCha20-Poly1305
- Key derivation function
- Argon2
- Encryption algorithm
-
A counter is used to generate the IV (Initialization Vector)
When encrypting with the same key, the IV MUST NEVER be reused. However, there is a risk of generating the same IV when using random numbers. In this package, IVs are counter-generated to avoid unintentional reuse of IVs.
-
Backward compatibility
The data format uses unsigned varint and Protocol Buffers. High backward compatibility is maintained even when new features are added in the future.
- Generating a backup file
- Private data files accessible through public URLs
-
Encryption of transmission data
If you encrypt a large amount of small data, there is a risk that the counter used to generate the IV will overflow.
-
Multi-processing and multi-threading
Currently, the counter used to generate IVs does not support different processes or threads. If used in multiple processes or threads, there is a danger of duplicate IVs.
I am not a security expert. I have researched a lot of information in order to create this package. I believe that this package will be secure. However, there is a possibility that I am wrong.
npm install @sounisi5011/encrypted-archive
yarn add @sounisi5011/encrypted-archive
pnpm add @sounisi5011/encrypted-archive
If you have a short string or a small file of data to encrypt, you can use a simple function.
const { encrypt, decrypt } = require('@sounisi5011/encrypted-archive');
const plaintext = 'Hello World!';
const password = '1234';
encrypt(plaintext, password, {
// These options are optional, but it is recommended that you specify the appropriate options for your application.
algorithm: 'chacha20-poly1305',
keyDerivation: {
algorithm: 'argon2d',
iterations: 3,
memory: 12,
parallelism: 1,
},
// If the data to be encrypted is text, you can also compress the data.
// Binary data (e.g. images, videos, etc.) can also be compressed,
// but the effect of compression is often small and is not recommended.
compress: 'gzip',
})
.then(encryptedData => {
// ...
})
.catch(error => {
// ...
});
// ----- //
const encryptedData = Buffer.from( ... );
decrypt(encryptedData, password)
.then(decryptedData => {
// ...
})
.catch(error => {
// ...
});
For huge files or data (e.g., hundreds of megabytes or tens of gigabytes), you can use Node.js Stream or Async Iteration.
const fs = require('fs');
const stream = require('stream');
const { encryptStream, decryptStream } = require('@sounisi5011/encrypted-archive');
const password = '1234';
const inputStream = fs.createReadStream('very-large.mp4');
const outputStream = fs.createWriteStream('very-large.mp4.enc');
stream.pipeline(
inputStream,
encryptStream(password, {
// These options are optional, but it is recommended that you specify the appropriate options for your application.
algorithm: 'aes-256-gcm',
keyDerivation: {
algorithm: 'argon2d',
iterations: 3,
memory: 12,
parallelism: 1,
},
// If the data to be encrypted is text, you can also compress the data.
// Binary data (e.g. images, videos, etc.) can also be compressed,
// but the effect of compression is often small and is not recommended.
//compress: 'gzip',
}),
outputStream,
error => {
if (error) {
// ...
} else {
// ...
}
},
);
// ----- //
stream.pipeline(
fs.createReadStream('very-large.mp4.enc'),
decryptStream(password),
fs.createWriteStream('very-large.mp4'),
error => {
if (error) {
// ...
} else {
// ...
}
},
);
const fs = require('fs');
const { encryptIterator, decryptIterator } = require('@sounisi5011/encrypted-archive');
const password = '1234';
const inputIterator = (async function*() {
for await (const chunk of fs.createReadStream('very-large.mp4')) {
yield chunk;
}
})();
const encryptor = encryptIterator(password, {
// These options are optional, but it is recommended that you specify the appropriate options for your application.
algorithm: 'aes-256-gcm',
keyDerivation: {
algorithm: 'argon2d',
iterations: 3,
memory: 12,
parallelism: 1,
},
// If the data to be encrypted is text, you can also compress the data.
// Binary data (e.g. images, videos, etc.) can also be compressed,
// but the effect of compression is often small and is not recommended.
//compress: 'gzip',
});
(async () => {
try {
for await (const encryptedDataChunk of encryptor(inputIterator)) {
// ...
}
} catch (error) {
// ...
}
})();
// ----- //
const inputEncryptedIterator = (async function*() {
for await (const chunk of fs.createReadStream('very-large.mp4.enc')) {
yield chunk;
}
})();
const decryptor = decryptIterator(password);
(async () => {
try {
for await (const decryptedDataChunk of decryptor(inputEncryptedIterator)) {
// ...
}
} catch (error) {
// ...
}
})();
Returns a Promise giving a Buffer
object.
-
plaintext
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
-
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
-
options
see
EncryptOptions
Returns a Promise giving a Buffer
object.
-
encryptedData
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
-
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
Returns a Transform
stream.
-
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
-
options
see
EncryptOptions
Returns a Transform
stream.
-
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
Returns an IteratorConverter
function.
-
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
-
options
see
EncryptOptions
Returns an IteratorConverter
function.
-
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
Returns an AsyncIterableIterator giving a Buffer
object.
-
source
Type:
Iterable<string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer> | AsyncIterable<string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer>
An object with the following properties:
All properties are optional.
Type: CryptoAlgorithmName
An encryption algorithm name string. Specify one of the following:
"aes-256-gcm"
"chacha20-poly1305"
(default on Node.js)
Type: KeyDerivationOptions
An object with the key derivation function name and options.
The key derivation function name is specified as a string in the algorithm
property.
The other properties are options for the key derivation function.
Currently, the following key derivation functions are supported:
-
-
algorithm
"argon2d"
(default)"argon2id"
-
iterations
Type:
number
the number of iterations. default:
3
-
memory
Type:
number
used memory, in KiB. default:
12
-
parallelism
Type:
number
desired parallelism. default:
1
For more information on the values that should be specified for these parameters, please refer to the following article: Choose Argon2 Parameters for Secure Password Hashing and Login - ory.sh
-
Type: CompressOptions | CompressOptions['algorithm']
A compression algorithm name string, or an options object for the compression algorithm.
When specifying an object, the compression algorithm name is specified as a string in the algorithm
property.
The other properties are options for the compression algorithm.
Currently, the following compression algorithm are supported:
-
Gzip
algorithm
"gzip"
Other properties are passed to zlib options. However, the following properties are not allowed:
flush
finishFlush
dictionary
info
maxOutputLength
-
Brotli
algorithm
"brotli"
Other properties are passed to brotli options. However, the following properties are not allowed:
flush
finishFlush
maxOutputLength