UNPKG

k9crypt

Version:

A special encryption algorithm created for K9Crypt.

95 lines (79 loc) 2.23 kB
const crypto = require('crypto'); const argon2 = require('argon2'); const { HMAC_KEY, ARGON2_HASH_LENGTH, ARGON2_TIME_COST, ARGON2_MEMORY_COST, ARGON2_PARALLELISM } = require('../constants'); // OWASP-aligned Argon2id parameters for integrity hashing const ARGON2_OPTIONS = { timeCost: ARGON2_TIME_COST, memoryCost: ARGON2_MEMORY_COST, parallelism: ARGON2_PARALLELISM, type: argon2.argon2id, hashLength: ARGON2_HASH_LENGTH }; const computeHmac = (data, authKey = null) => { let derivedHmacKey = null; const hmacKey = authKey ? crypto.createHmac('sha512', HMAC_KEY).update(Buffer.isBuffer(authKey) ? authKey : Buffer.from(authKey, 'utf8')).digest() : HMAC_KEY; if (authKey) { derivedHmacKey = hmacKey; } try { const hmac = crypto.createHmac('sha512', hmacKey); hmac.update(data); return hmac.digest(); } finally { if (derivedHmacKey) { derivedHmacKey.fill(0); } } }; exports.hash = async (data, salt, authKey = null) => { const digest = computeHmac(data, authKey); try { return await argon2.hash(digest, { ...ARGON2_OPTIONS, salt, raw: true }); } finally { digest.fill(0); } }; exports.verifyHash = async (data, hash, salt, authKey = null) => { if (!Buffer.isBuffer(hash) || hash.length !== ARGON2_HASH_LENGTH) { return false; } const digest = computeHmac(data, authKey); let expectedHash = null; try { expectedHash = await argon2.hash(digest, { ...ARGON2_OPTIONS, salt, raw: true }); if (expectedHash.length !== hash.length) { return false; } return crypto.timingSafeEqual(hash, expectedHash); } finally { digest.fill(0); if (expectedHash) { expectedHash.fill(0); } } }; exports.macHash = (data, salt, key) => { const hmac = crypto.createHmac('sha512', key); hmac.update(salt); hmac.update(data); return hmac.digest(); }; exports.verifyMacHash = (data, hash, salt, key) => { if (!Buffer.isBuffer(hash) || hash.length !== ARGON2_HASH_LENGTH) { return false; } const expectedHash = exports.macHash(data, salt, key); try { return crypto.timingSafeEqual(hash, expectedHash); } finally { expectedHash.fill(0); } };