@xec-sh/cli
Version:
Xec: The Universal Shell for TypeScript
81 lines • 2.57 kB
JavaScript
import { promisify } from 'util';
import { scrypt, createHash, randomBytes, createCipheriv, createDecipheriv } from 'crypto';
const scryptAsync = promisify(scrypt);
const ALGORITHM = 'aes-256-gcm';
const SALT_LENGTH = 32;
const IV_LENGTH = 16;
const TAG_LENGTH = 16;
const KEY_LENGTH = 32;
const SCRYPT_OPTIONS = {
N: 16384,
r: 8,
p: 1,
};
export async function deriveKey(machineId, salt, passphrase) {
const secret = passphrase ? `${machineId}:${passphrase}` : machineId;
const key = await scryptAsync(secret, salt, KEY_LENGTH);
return key;
}
export async function encrypt(value, machineId, passphrase) {
const salt = randomBytes(SALT_LENGTH);
const iv = randomBytes(IV_LENGTH);
const key = await deriveKey(machineId, salt, passphrase);
const cipher = createCipheriv(ALGORITHM, key, iv);
const encrypted = Buffer.concat([
cipher.update(value, 'utf8'),
cipher.final()
]);
const authTag = cipher.getAuthTag();
return {
encrypted,
salt,
iv,
authTag
};
}
export async function decrypt(encrypted, salt, iv, authTag, machineId, passphrase) {
const key = await deriveKey(machineId, salt, passphrase);
const decipher = createDecipheriv(ALGORITHM, key, iv);
decipher.setAuthTag(authTag);
const decrypted = Buffer.concat([
decipher.update(encrypted),
decipher.final()
]);
return decrypted.toString('utf8');
}
export function hashKey(key) {
return createHash('sha256').update(key).digest('hex');
}
export function createFingerprint(data) {
const hash = createHash('sha256');
hash.update(typeof data === 'string' ? Buffer.from(data) : data);
return hash.digest('hex').substring(0, 16);
}
export function encode(buffer) {
return buffer.toString('base64');
}
export function decode(data) {
return Buffer.from(data, 'base64');
}
export function secureCompare(a, b) {
if (a.length !== b.length) {
return false;
}
let result = 0;
for (let i = 0; i < a.length; i++) {
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
}
return result === 0;
}
export function generateSecret(length = 32) {
if (length <= 0) {
throw new Error('Length must be greater than 0');
}
if (length > 1024) {
throw new Error('Length must be less than or equal to 1024');
}
const bytesNeeded = Math.ceil(length * 3 / 4);
const randomData = randomBytes(bytesNeeded);
return randomData.toString('base64').substring(0, length);
}
//# sourceMappingURL=crypto.js.map