This is a special encryption algorithm created for K9Crypt.
bun add k9cryptconst k9crypt = require('k9crypt');
async function test() {
const secretKey = 'VeryLongSecretKey!@#1234567890';
const encryptor = new k9crypt(secretKey);
// Or you can use it without providing a secretKey value. A key will be generated by the system.
// const encryptor = new k9crypt();
const plaintext = 'Hello, World!';
try {
const encrypted = await encryptor.encrypt(plaintext);
console.log('Encrypted data:', encrypted);
const decrypted = await encryptor.decrypt(encrypted);
console.log('Decrypted data:', decrypted);
} catch (error) {
// Errors are generic (e.g. "Encryption failed", "Decryption failed") for security
console.error('Error:', error.message);
}
}
test();New encryptions use a versioned payload format with authenticated time metadata. The final encryption key is derived from the user secret, a random per-payload salt, and the authenticated time bucket.
const secretKey = 'VeryLongSecretKey!@#1234567890';
const encryptor = new k9crypt(secretKey);
const plaintext = 'Time-scoped secure payload';
const encrypted = await encryptor.encrypt(plaintext, {
timeStepSeconds: 300
});
const decrypted = await encryptor.decrypt(encrypted);
console.log(decrypted);timeStepSeconds controls the time bucket size. The timestamp is stored inside the authenticated payload, so decryption stays deterministic even if the system clock changes later.
Use issuedAt or issuedAtUnix when a system needs to assign a controlled payload timestamp.
const issuedAt = Math.floor(Date.now() / 1000);
const encrypted = await encryptor.encrypt(plaintext, {
issuedAt,
timeStepSeconds: 60
});
const decrypted = await encryptor.decrypt(encrypted);
console.log(decrypted);Freshness checks are optional and run after integrity validation. They reject payloads that exceed the accepted age window or appear too far in the future.
const encrypted = await encryptor.encrypt(plaintext, {
timeStepSeconds: 60
});
const decrypted = await encryptor.decrypt(encrypted, {
maxAgeSeconds: 300,
allowedClockSkewSeconds: 30
});
console.log(decrypted);maxAgeSeconds limits how long a valid ciphertext is accepted. It is not a complete replay-prevention mechanism by itself.
Previous payloads decrypt by default for migration safety. New deployments that do not need old ciphertext support can disable that compatibility path.
const decrypted = await encryptor.decrypt(encrypted, {
allowLegacyPayloads: false
});The default compression level is 0 for low-latency encryption. Set compressionLevel above 0 when payload size is more important than latency.
const encryptor = new k9crypt(secretKey, { compressionLevel: 5 });
const encrypted = await encryptor.encrypt(plaintext, { compressionLevel: 7 });Buffer inputs are restored as Buffers after decryption. Text inputs are restored as strings.
const binaryData = Buffer.from([0, 255, 1, 2, 3]);
const encrypted = await encryptor.encrypt(binaryData, {
timeStepSeconds: 300
});
const decrypted = await encryptor.decrypt(encrypted);
console.log(Buffer.isBuffer(decrypted));encryptFile and decryptFile operate on buffered data. They are intended for bounded in-memory payloads and enforce a conservative size limit for production stability.
async function encryptBigFile() {
const largeData = 'Very large data...';
const encrypted = await encryptor.encryptFile(largeData, {
timeStepSeconds: 300,
compressionLevel: 6,
onProgress: (progress) => {
console.log(`Processed: ${progress.processedBytes} bytes`);
}
});
const decrypted = await encryptor.decryptFile(encrypted, {
maxAgeSeconds: 600,
onProgress: (progress) => {
console.log(`Decrypted: ${progress.processedBytes} bytes`);
}
});
return decrypted;
}async function encryptMultipleData() {
const dataArray = ['data1', 'data2', 'data3', 'data4'];
const encrypted = await encryptor.encryptMany(dataArray, {
timeStepSeconds: 300,
compressionLevel: 5,
onProgress: (progress) => {
console.log(`Progress: ${progress.percentage}% (${progress.current}/${progress.total})`);
}
});
const decrypted = await encryptor.decryptMany(encrypted, {
skipInvalid: true,
maxAgeSeconds: 600,
onProgress: (progress) => {
console.log(`Progress: ${progress.percentage}%`);
}
});
return decrypted;
}async function encryptManyDataFast() {
const dataArray = Array(100).fill('sample data');
const encrypted = await encryptor.encryptMany(dataArray, {
parallel: true,
batchSize: 2,
timeStepSeconds: 300,
compressionLevel: 4
});
const decrypted = await encryptor.decryptMany(encrypted, {
parallel: true,
batchSize: 2,
maxAgeSeconds: 600,
skipInvalid: false
});
return decrypted;
}This project is licensed under the MIT license.
