import { scrypt as _scrypt, createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
import { writeFileSync, readFileSync, mkdirSync, renameSync, unlinkSync } from "node:fs";
import { dirname, join } from "node:path";
const FORMAT_VERSION = 1;
const SALT_LEN = 32;
const IV_LEN = 12;
const TAG_LEN = 16;
const KEY_LEN = 32;
function deriveKey(machineId, salt) {
  return new Promise((resolve, reject) => {
    _scrypt(machineId, salt, KEY_LEN, { N: 16384, r: 8, p: 1 }, (err, key) => {
      if (err) reject(err);
      else resolve(key);
    });
  });
}
async function encryptSecret(plaintext, machineId) {
  const salt = randomBytes(SALT_LEN);
  const iv = randomBytes(IV_LEN);
  const key = await deriveKey(machineId, salt);
  const cipher = createCipheriv("aes-256-gcm", key, iv);
  const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
  const tag = cipher.getAuthTag();
  const header = Buffer.alloc(4);
  header.writeUInt32BE(FORMAT_VERSION, 0);
  const payload = Buffer.concat([header, salt, iv, tag, encrypted]);
  return payload.toString("base64");
}
async function decryptSecret(blob, machineId) {
  const payload = Buffer.from(blob, "base64");
  if (payload.length < 65) {
    throw new Error("key-crypto: payload too short to be valid");
  }
  const version = payload.readUInt32BE(0);
  if (version !== FORMAT_VERSION) {
    throw new Error(`key-crypto: unsupported format version ${version}`);
  }
  let offset = 4;
  const salt = payload.subarray(offset, offset + SALT_LEN);
  offset += SALT_LEN;
  const iv = payload.subarray(offset, offset + IV_LEN);
  offset += IV_LEN;
  const tag = payload.subarray(offset, offset + TAG_LEN);
  offset += TAG_LEN;
  const ciphertext = payload.subarray(offset);
  const key = await deriveKey(machineId, salt);
  const decipher = createDecipheriv("aes-256-gcm", key, iv);
  decipher.setAuthTag(tag);
  const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
  return decrypted.toString("utf8");
}
async function encryptToFile(plaintext, machineId, filePath) {
  const blob = await encryptSecret(plaintext, machineId);
  const dir = dirname(filePath);
  mkdirSync(dir, { recursive: true, mode: 448 });
  const tmp = join(dir, `.${randomBytes(8).toString("hex")}.tmp`);
  try {
    writeFileSync(tmp, blob, { encoding: "utf8", mode: 384 });
    renameSync(tmp, filePath);
  } catch (err) {
    try {
      unlinkSync(tmp);
    } catch {
    }
    throw err;
  }
}
async function decryptFromFile(machineId, filePath) {
  const blob = readFileSync(filePath, "utf8");
  return decryptSecret(blob.trim(), machineId);
}
export {
  decryptFromFile,
  decryptSecret,
  encryptSecret,
  encryptToFile
};
//# sourceMappingURL=key-crypto.js.map