@sounisi5011/encrypted-archive
v0.1.0
Published
Convert data into a single encrypted archive data that contains all metadata needed for decryption
Downloads
137
Maintainers
Readme
@sounisi5011/encrypted-archive
Convert data into a single encrypted archive data that contains all metadata needed for decryption.
Features
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.
Example of use
- Generating a backup file
- Private data files accessible through public URLs
Not recommended for use
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.
Attention
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.
Installation
npm install @sounisi5011/encrypted-archive
yarn add @sounisi5011/encrypted-archive
pnpm add @sounisi5011/encrypted-archive
Usage
Small data
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 cleartext = 'Hello World!';
const password = '1234';
encrypt(cleartext, 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 => {
// ...
});
Huge data
For huge files or data (e.g., hundreds of megabytes or tens of gigabytes), you can use Node.js Stream or Async Iteration.
Stream
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 {
// ...
}
},
);
Async Iteration
const fs = require('fs');
const stream = require('stream');
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) {
// ...
}
})();
API
encrypt(cleartext, password, options?)
Returns a Promise giving a Buffer
object.
cleartext
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
options
see
EncryptOptions
decrypt(encryptedData, password)
Returns a Promise giving a Buffer
object.
encryptedData
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
encryptStream(password, options?)
Returns a Transform
stream.
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
options
see
EncryptOptions
decryptStream(password)
Returns a Transform
stream.
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
encryptIterator(password, options?)
Returns an IteratorConverter
function.
password
Type:
string | Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer
options
see
EncryptOptions
decryptIterator(password)
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)
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