mirror of
https://github.com/silicoflare/confidant.git
synced 2026-05-26 20:48:01 +05:30
feat: new encrypt
This commit is contained in:
22
confidant.ts
22
confidant.ts
@@ -1,15 +1,15 @@
|
|||||||
#!/bin/env bun
|
#!/bin/env bun
|
||||||
|
|
||||||
import { checkbox, input, password, select } from "@inquirer/prompts";
|
import { input, password } from "@inquirer/prompts";
|
||||||
import { $ } from "bun";
|
import { $ } from "bun";
|
||||||
import chalk from "chalk-template";
|
import chalk from "chalk-template";
|
||||||
import { Command } from "commander";
|
import { Command } from "commander";
|
||||||
import { decrypt_diary, encrypt_diary, initialize, recovery } from "./src/main";
|
import { decrypt_vault, encrypt_vault, initialize, recovery } from "./src/main";
|
||||||
import { existsSync } from "fs";
|
import { existsSync } from "fs";
|
||||||
import checkForFiles, {
|
import checkForFiles, {
|
||||||
|
getDecryptedName,
|
||||||
getDirectoryNames,
|
getDirectoryNames,
|
||||||
getVaultName,
|
getVaultName,
|
||||||
log,
|
|
||||||
panic,
|
panic,
|
||||||
} from "./src/utils";
|
} from "./src/utils";
|
||||||
|
|
||||||
@@ -47,7 +47,6 @@ program
|
|||||||
.option("-l, --live", "decrypt in live mode")
|
.option("-l, --live", "decrypt in live mode")
|
||||||
.option("-v, --vault <name>", "name of the vault to decrypt")
|
.option("-v, --vault <name>", "name of the vault to decrypt")
|
||||||
.action(async (args) => {
|
.action(async (args) => {
|
||||||
let files: string[];
|
|
||||||
if (!args.vault) {
|
if (!args.vault) {
|
||||||
args.vault = await getVaultName();
|
args.vault = await getVaultName();
|
||||||
}
|
}
|
||||||
@@ -56,12 +55,12 @@ program
|
|||||||
message: chalk`{reset {yellow Enter the password:}}`,
|
message: chalk`{reset {yellow Enter the password:}}`,
|
||||||
mask: "•",
|
mask: "•",
|
||||||
});
|
});
|
||||||
await decrypt_diary(pass, args.vault);
|
await decrypt_vault(pass, args.vault);
|
||||||
if (args.live) {
|
if (args.live) {
|
||||||
await input({
|
await input({
|
||||||
message: chalk`{yellow Live mode started. Press ENTER to encrypt}`,
|
message: chalk`{yellow Live mode started. Press ENTER to encrypt}`,
|
||||||
});
|
});
|
||||||
await encrypt_diary();
|
await encrypt_vault(args.vault);
|
||||||
console.log(chalk`{green Successfully encrypted!}`);
|
console.log(chalk`{green Successfully encrypted!}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(chalk`{green Decrypted sucessfully!}`);
|
console.log(chalk`{green Decrypted sucessfully!}`);
|
||||||
@@ -71,14 +70,13 @@ program
|
|||||||
program
|
program
|
||||||
.command("encrypt")
|
.command("encrypt")
|
||||||
.description("encrypt the vault")
|
.description("encrypt the vault")
|
||||||
.action(async () => {
|
.option("-v, --vault <name>", "name of the vault to decrypt")
|
||||||
checkForFiles();
|
.action(async (args) => {
|
||||||
|
if (!args.vault) {
|
||||||
if (!existsSync(".confidant")) {
|
args.vault = await getDecryptedName();
|
||||||
panic`The vault was not decrypted yet!`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await encrypt_diary();
|
await encrypt_vault(args.vault);
|
||||||
console.log(chalk`{green Successfully encrypted!}`);
|
console.log(chalk`{green Successfully encrypted!}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
24
src/main.ts
24
src/main.ts
@@ -94,7 +94,7 @@ confidant.zip
|
|||||||
writeFileSync(`.gitignore`, gitignore);
|
writeFileSync(`.gitignore`, gitignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function decrypt_diary(password: string, dirname: string) {
|
export async function decrypt_vault(password: string, dirname: string) {
|
||||||
// Read and split the vault file
|
// Read and split the vault file
|
||||||
const combined = readFileSync(`${dirname}.vault`);
|
const combined = readFileSync(`${dirname}.vault`);
|
||||||
const index = combined.indexOf(separator);
|
const index = combined.indexOf(separator);
|
||||||
@@ -130,17 +130,27 @@ export async function decrypt_diary(password: string, dirname: string) {
|
|||||||
await $`unzip confidant.zip > /dev/null && rm confidant.zip`;
|
await $`unzip confidant.zip > /dev/null && rm confidant.zip`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function encrypt_diary() {
|
export async function encrypt_vault(dirname: string) {
|
||||||
const { dirname, key }: { dirname: string; key: string } = JSON.parse(
|
const D = decrypt(
|
||||||
decrypt(readFileSync(".confidant"), buffer(env.AUTH_KEY)).toString("utf8"),
|
readFileSync(`.${dirname}.confidant`),
|
||||||
|
buffer(env.AUTH_KEY),
|
||||||
);
|
);
|
||||||
const D = buffer(key);
|
// create zip file and encrypt it
|
||||||
await $`zip -r9 confidant.zip ${dirname} > /dev/null`;
|
await $`zip -r9 confidant.zip ${dirname} > /dev/null`;
|
||||||
await $`rm -rf ${dirname}`;
|
await $`rm -rf ${dirname}`;
|
||||||
const Z = readFileSync("confidant.zip");
|
const Z = readFileSync("confidant.zip");
|
||||||
const E_Z = encrypt_file(Z, D);
|
const E_Z = encrypt_file(Z, D);
|
||||||
writeFileSync(`vault.ant`, E_Z);
|
|
||||||
await $`rm confidant.zip .confidant`;
|
// read original vault file to get header data
|
||||||
|
const vaultfile = readFileSync(`${dirname}.vault`);
|
||||||
|
const index = vaultfile.indexOf(separator);
|
||||||
|
|
||||||
|
// write new data to vault
|
||||||
|
writeFileSync(
|
||||||
|
`${dirname}.vault`,
|
||||||
|
Buffer.concat([vaultfile.subarray(0, index), separator, E_Z]),
|
||||||
|
);
|
||||||
|
await $`rm confidant.zip .${dirname}.confidant`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function recovery(recoverystring: string) {
|
export async function recovery(recoverystring: string) {
|
||||||
|
|||||||
71
src/utils.ts
71
src/utils.ts
@@ -4,7 +4,7 @@ import { generatePrivate, getPublic } from "eccrypto";
|
|||||||
import { generate } from "random-words";
|
import { generate } from "random-words";
|
||||||
import chalk from "chalk-template";
|
import chalk from "chalk-template";
|
||||||
import { $ } from "bun";
|
import { $ } from "bun";
|
||||||
import { existsSync } from "fs";
|
import { existsSync, readdirSync } from "fs";
|
||||||
import { select } from "@inquirer/prompts";
|
import { select } from "@inquirer/prompts";
|
||||||
|
|
||||||
export function buffer(input: string): Buffer;
|
export function buffer(input: string): Buffer;
|
||||||
@@ -106,6 +106,32 @@ export function print(key: string, value: string) {
|
|||||||
console.log(chalk`{green ${key}:} {blue ${value}}`);
|
console.log(chalk`{green ${key}:} {blue ${value}}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class Files {
|
||||||
|
data: string[] | null = null;
|
||||||
|
|
||||||
|
constructor(regex: RegExp | string) {
|
||||||
|
try {
|
||||||
|
const data = readdirSync(".").filter((x) => x.match(regex));
|
||||||
|
this.data = data ? data.map((x) => x.replace(regex, "$1")) : null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error executing command:", error);
|
||||||
|
this.data = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
return `[ ${this.data ? this.data.join(", ") : "empty"} ]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
intersection(a: Files) {
|
||||||
|
return Array.from(new Set(this.data).intersection(new Set(a.data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
difference(a: Files) {
|
||||||
|
return Array.from(new Set(this.data).difference(new Set(a.data)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function getDirectoryNames() {
|
export async function getDirectoryNames() {
|
||||||
const dirlist = (await $`ls -d */`.text()).trim();
|
const dirlist = (await $`ls -d */`.text()).trim();
|
||||||
|
|
||||||
@@ -147,12 +173,25 @@ export async function getVaultName() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keyList = (await $`ls *.key`.text())
|
||||||
|
.trim()
|
||||||
|
.match(/.*\.key/g) as string[];
|
||||||
|
if (!keyList) {
|
||||||
|
panic`No vaults with keys found in the current directory.`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vaults = Array.from(
|
||||||
|
new Set(vaultList.map((x) => x.replace(".vault", ""))).intersection(
|
||||||
|
new Set(keyList.map((x) => x.replace(".key", ""))),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
let files: string[];
|
let files: string[];
|
||||||
const decryptedList = (await $`bash -c "ls .*.confidant"`.text())
|
const decryptedList = (await $`bash -c "ls .*.confidant"`.text())
|
||||||
.trim()
|
.trim()
|
||||||
.match(/\.(.*)\.confidant/g);
|
.match(/\.(.*)\.confidant/g);
|
||||||
if (decryptedList) {
|
if (decryptedList) {
|
||||||
const vaults = vaultList.map((x) => x.replace(".vault", ""));
|
|
||||||
const decs = decryptedList.map((x) => x.replace(/\.(.*)\.confidant/, "$1"));
|
const decs = decryptedList.map((x) => x.replace(/\.(.*)\.confidant/, "$1"));
|
||||||
files = Array.from(new Set(vaults).difference(new Set(decs)));
|
files = Array.from(new Set(vaults).difference(new Set(decs)));
|
||||||
} else {
|
} else {
|
||||||
@@ -171,3 +210,31 @@ export async function getVaultName() {
|
|||||||
});
|
});
|
||||||
return vault;
|
return vault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getDecryptedName() {
|
||||||
|
const dec = new Files(/\.(.*)\.confidant/g);
|
||||||
|
if (dec.data === null || dec.data.length === 0) {
|
||||||
|
panic`No decrypted vaults found.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vaults = new Files(/(.*).vault/g);
|
||||||
|
if (vaults.data === null) {
|
||||||
|
panic`No vaults found.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const decrypted = dec.intersection(vaults);
|
||||||
|
|
||||||
|
if (decrypted.length === 1) {
|
||||||
|
return decrypted[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const vault = await select({
|
||||||
|
message: "Select vault to encrypt:",
|
||||||
|
choices: decrypted.map((x) => ({
|
||||||
|
name: x.replace(".vault", ""),
|
||||||
|
value: x.replace(".vault", ""),
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
return vault;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user