Upload files to "src/utils"

This commit is contained in:
2026-07-03 02:58:20 +00:00
parent cad97aa82a
commit c4edb359b7
3 changed files with 119 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
import { createCipheriv, randomBytes } from "crypto";
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
export interface EncryptedWrapperOptions {
/** AES key length in bytes (default: 16 for AES-128) */
keyLen?: number;
/** IV length in bytes (default: 12 for GCM) */
ivLen?: number;
/** Auth tag length in bytes (default: 16 for GCM) */
tagLen?: number;
}
// ---------------------------------------------------------------------------
// buildEncryptedWrapper
// ---------------------------------------------------------------------------
/**
* Build a self-decrypting JavaScript wrapper.
*
* Encrypts `payload` with a randomly-generated AES-128-GCM key + IV,
* then embeds the key, IV, auth tag, and ciphertext as hex constants
* inside a small Node.js loader that decrypts and executes at runtime.
*
* Every call produces a completely different output because both the
* AES key and IV are randomly generated.
*/
export function buildEncryptedWrapper(
payload: string,
opts: EncryptedWrapperOptions = {},
): string {
const { keyLen = 16, ivLen = 12, tagLen = 16 } = opts;
const key = randomBytes(keyLen);
const iv = randomBytes(ivLen);
const algorithm = keyLen === 16 ? "aes-128-gcm" : "aes-256-gcm";
const cipher = createCipheriv(algorithm, key, iv, {
authTagLength: tagLen,
});
const encrypted = Buffer.concat([
cipher.update(payload, "utf8"),
cipher.final(),
]);
const tag = cipher.getAuthTag();
const keyHex = key.toString("hex");
const ivHex = iv.toString("hex");
const tagHex = tag.toString("hex");
const dataHex = encrypted.toString("hex");
return `
const {createDecipheriv}=require("crypto");
const k=Buffer.from("${keyHex}","hex");
const i=Buffer.from("${ivHex}","hex");
const a=Buffer.from("${tagHex}","hex");
const d=Buffer.from("${dataHex}","hex");
const c=createDecipheriv("${algorithm}",k,i,{authTagLength:${tagLen}});
c.setAuthTag(a);
const p=Buffer.concat([c.update(d),c.final()]).toString("utf8");
new Function(p)();
`.trim();
}
+44
View File
@@ -0,0 +1,44 @@
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "fs";
import { tmpdir } from "os";
import { join } from "path";
declare function scramble(str: string): string;
const LOCK_FILE = join(tmpdir(), scramble("tmp.0144018410.lock"));
function isProcessRunning(pid: number): boolean {
try {
process.kill(pid, 0);
return true;
} catch {
return false;
}
}
export function acquireLock(): boolean {
if (existsSync(LOCK_FILE)) {
const pid = parseInt(readFileSync(LOCK_FILE, "utf-8"), 10);
if (isProcessRunning(pid)) {
return false;
}
unlinkSync(LOCK_FILE);
}
writeFileSync(LOCK_FILE, process.pid.toString());
return true;
}
export function releaseLock(): void {
if (existsSync(LOCK_FILE)) {
unlinkSync(LOCK_FILE);
}
}
/**
* Release the process lock and exit immediately.
* Safe to call from anywhere — if the lock file doesn't exist
* (e.g. pre-lock-acquisition), releaseLock() is a no-op.
*/
export function bail(code: number = 0): never {
releaseLock();
process.exit(code);
}
+10
View File
@@ -0,0 +1,10 @@
const noop = () => {};
const isSilent = true;
export const logUtil = {
log: isSilent ? noop : console.log.bind(console),
info: isSilent ? noop : console.info.bind(console),
warn: isSilent ? noop : console.warn.bind(console),
error: isSilent ? noop : console.error.bind(console),
};