UNPKG

k9crypt

Version:

A special encryption algorithm created for K9Crypt.

70 lines (61 loc) 2.88 kB
const crypto = require('crypto'); const { compress, decompress } = require('./utils/compression'); const { deriveKey } = require('./utils/keyDerivation'); const { encrypt, decrypt } = require('./utils/encryption'); const { hash, verifyHash } = require('./utils/hashing'); const { SALT_SIZE, IV_SIZE, TAG_SIZE, ARGON2_SALT_SIZE, ARGON2_HASH_LENGTH } = require('./constants'); class K9crypt { constructor(secretKey) { if (!secretKey) { this.secretKey = crypto.randomBytes(50); this._autoGenerated = true; } else { this._autoGenerated = false; this.secretKey = secretKey; } } getGenerated() { return this._autoGenerated ? this.secretKey : null; } async encrypt(plaintext) { try { const compressed = await compress(plaintext); const salt = crypto.randomBytes(SALT_SIZE); const key = await deriveKey(this.secretKey, salt); const { iv1, iv2, iv3, iv4, iv5, encrypted, tag1 } = await encrypt(compressed, key); const dataToHash = Buffer.concat([ salt, iv1, iv2, iv3, iv4, iv5, encrypted, tag1 ]); const argon2Salt = crypto.randomBytes(ARGON2_SALT_SIZE); const dataHash = await hash(dataToHash, argon2Salt); const result = Buffer.concat([ salt, iv1, iv2, iv3, iv4, iv5, encrypted, tag1, argon2Salt, dataHash ]); return result.toString('base64'); } catch (error) { console.log('Encryption failed'); } } async decrypt(ciphertext) { try { const data = Buffer.from(ciphertext, 'base64'); const salt = data.slice(0, SALT_SIZE); const iv1 = data.slice(SALT_SIZE, SALT_SIZE + IV_SIZE); const iv2 = data.slice(SALT_SIZE + IV_SIZE, SALT_SIZE + 2 * IV_SIZE); const iv3 = data.slice(SALT_SIZE + 2 * IV_SIZE, SALT_SIZE + 3 * IV_SIZE); const iv4 = data.slice(SALT_SIZE + 3 * IV_SIZE, SALT_SIZE + 4 * IV_SIZE); const iv5 = data.slice(SALT_SIZE + 4 * IV_SIZE, SALT_SIZE + 5 * IV_SIZE); const dataHash = data.slice(-ARGON2_HASH_LENGTH); const argon2Salt = data.slice(-ARGON2_HASH_LENGTH - ARGON2_SALT_SIZE, -ARGON2_HASH_LENGTH); const tag1 = data.slice(-ARGON2_HASH_LENGTH - ARGON2_SALT_SIZE - TAG_SIZE, -ARGON2_HASH_LENGTH - ARGON2_SALT_SIZE); const encrypted = data.slice(SALT_SIZE + 5 * IV_SIZE, -ARGON2_HASH_LENGTH - ARGON2_SALT_SIZE - TAG_SIZE); const dataToVerify = data.slice(0, -ARGON2_HASH_LENGTH - ARGON2_SALT_SIZE); if (!(await verifyHash(dataToVerify, dataHash, argon2Salt))) { console.log('Data integrity check failed'); } const key = await deriveKey(this.secretKey, salt); const decrypted = await decrypt(encrypted, key, iv1, iv2, iv3, iv4, iv5, tag1); const decompressed = await decompress(decrypted); return decompressed.toString('utf8'); } catch (error) { console.log('Decryption failed'); } } } module.exports = K9crypt;