chomot 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ interface CryptoConfig {
2
+ privateKeyFilePath: string;
3
+ publicKeyFilePath: string;
4
+ }
5
+ export declare function setCryptoConfig(newConfig: CryptoConfig): void;
6
+ export declare function getCryptoConfig(): CryptoConfig;
7
+ export {};
@@ -0,0 +1,13 @@
1
+ // Step 1: Make it `let` to allow reassignment
2
+ let cryptoConfig = {
3
+ privateKeyFilePath: "./crypto/private.crypto",
4
+ publicKeyFilePath: "./crypto/public.crypto",
5
+ };
6
+ // Step 2: Function to update it
7
+ export function setCryptoConfig(newConfig) {
8
+ cryptoConfig = { ...newConfig };
9
+ }
10
+ // Optional: Function to get it
11
+ export function getCryptoConfig() {
12
+ return cryptoConfig;
13
+ }
@@ -0,0 +1 @@
1
+ export * from "./crypto";
@@ -0,0 +1 @@
1
+ export * from "./crypto";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { decrypt, encrypt } from "../crypto/operations";
3
+ describe("encryption", () => {
4
+ it("can encrypt symetrically", async () => {
5
+ const plain = "secret";
6
+ const encryptedText = await encrypt(plain);
7
+ const decryptedText = await decrypt(encryptedText);
8
+ expect(plain).not.toEqual(encryptedText);
9
+ expect(decryptedText).toEqual(plain);
10
+ });
11
+ it("can encrypt asymetrically", async () => {
12
+ const plain = "secret";
13
+ const encryptedText = await encrypt(plain, "Asymetric");
14
+ const decryptedText = await decrypt(encryptedText, "Asymetric");
15
+ expect(plain).not.toEqual(encryptedText);
16
+ expect(decryptedText).toEqual(plain);
17
+ });
18
+ });
@@ -0,0 +1,10 @@
1
+ export declare const appCryptography: {
2
+ publicKey?: Uint8Array;
3
+ privateKey?: Uint8Array;
4
+ symetricKey?: Uint8Array;
5
+ salt?: Uint8Array;
6
+ };
7
+ export declare function getPrivateKey(): Promise<Uint8Array<ArrayBufferLike>>;
8
+ export declare function getPublicKey(): Promise<Uint8Array<ArrayBufferLike>>;
9
+ export declare function getSymetricKey(): Promise<Uint8Array<ArrayBufferLike>>;
10
+ export default function run(): Promise<void>;
@@ -0,0 +1,59 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getCryptoConfig } from "../config/crypto";
4
+ import { getSodium } from "../crypto/sodium";
5
+ const cryptoConfig = getCryptoConfig();
6
+ export const appCryptography = {};
7
+ function loadCryptoKey(path) {
8
+ if (!existsSync(path)) {
9
+ throw new Error("Encryption key is not found");
10
+ }
11
+ return readFileSync(path);
12
+ }
13
+ export async function getPrivateKey() {
14
+ if (!appCryptography.privateKey) {
15
+ appCryptography.privateKey = loadCryptoKey(cryptoConfig.privateKeyFilePath);
16
+ }
17
+ return appCryptography.privateKey;
18
+ }
19
+ export async function getPublicKey() {
20
+ if (!appCryptography.publicKey) {
21
+ appCryptography.publicKey = loadCryptoKey(cryptoConfig.publicKeyFilePath);
22
+ }
23
+ return appCryptography.publicKey;
24
+ }
25
+ async function getSalt() {
26
+ if (!appCryptography.salt) {
27
+ const sodium = await getSodium();
28
+ appCryptography.salt = sodium.randombytes_buf(sodium.crypto_pwhash_SALTBYTES);
29
+ }
30
+ return appCryptography.salt;
31
+ }
32
+ export async function getSymetricKey() {
33
+ if (!appCryptography.symetricKey) {
34
+ const sodium = await getSodium();
35
+ const privateKey = await getPrivateKey();
36
+ const salt = await getSalt();
37
+ appCryptography.symetricKey = sodium.crypto_pwhash(sodium.crypto_secretbox_KEYBYTES, // 32 byte output
38
+ privateKey, salt, sodium.crypto_pwhash_OPSLIMIT_MODERATE, sodium.crypto_pwhash_MEMLIMIT_MODERATE, sodium.crypto_pwhash_ALG_DEFAULT);
39
+ }
40
+ return appCryptography.symetricKey;
41
+ }
42
+ export default async function run() {
43
+ const sodium = await getSodium();
44
+ const { publicKey, privateKey } = sodium.crypto_box_keypair();
45
+ const rootDir = process.cwd();
46
+ const certDir = join(rootDir, "crypto");
47
+ // Buat folder 'crypto' jika belum ada
48
+ mkdirSync(certDir, { recursive: true });
49
+ const privateKeyPath = join(certDir, "private.crypto");
50
+ const publicKeyPath = join(certDir, "public.crypto");
51
+ writeFileSync(privateKeyPath, privateKey);
52
+ writeFileSync(publicKeyPath, publicKey);
53
+ console.log("✅ Key pair berhasil dibuat di folder /cert:");
54
+ console.log(`🔐 ${privateKeyPath}`);
55
+ console.log(`🔓 ${publicKeyPath}`);
56
+ }
57
+ if (import.meta.main) {
58
+ run();
59
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./genkey";
2
+ export * from "./operations";
@@ -0,0 +1,2 @@
1
+ export * from "./genkey";
2
+ export * from "./operations";
@@ -0,0 +1,3 @@
1
+ export type EncryptionType = "Symetric" | "Asymetric";
2
+ export declare function decrypt(encrypted: string, type?: EncryptionType): Promise<string>;
3
+ export declare function encrypt(plain: string, type?: EncryptionType): Promise<string>;
@@ -0,0 +1,41 @@
1
+ import { getSodium } from "../crypto/sodium";
2
+ import { getPrivateKey, getPublicKey, getSymetricKey } from "./genkey";
3
+ export async function decrypt(encrypted, type = "Symetric") {
4
+ const sodium = await getSodium();
5
+ const publicKey = await getPublicKey();
6
+ const privateKey = await getPrivateKey();
7
+ if (type === "Asymetric") {
8
+ return sodium.to_string(sodium.crypto_box_seal_open(sodium.from_base64(encrypted, sodium.base64_variants.ORIGINAL), publicKey, privateKey));
9
+ }
10
+ else {
11
+ const symetricKey = await getSymetricKey();
12
+ if (!symetricKey)
13
+ throw new Error("Key not initialized, call deriveKeyFromPassword() first");
14
+ const combined = sodium.from_base64(encrypted);
15
+ const nonce = combined.slice(0, sodium.crypto_secretbox_NONCEBYTES);
16
+ const ciphertext = combined.slice(sodium.crypto_secretbox_NONCEBYTES);
17
+ const decrypted = sodium.crypto_secretbox_open_easy(ciphertext, nonce, symetricKey);
18
+ if (!decrypted)
19
+ throw new Error("Decryption failed");
20
+ return sodium.to_string(decrypted);
21
+ }
22
+ }
23
+ export async function encrypt(plain, type = "Symetric") {
24
+ const sodium = await getSodium();
25
+ const publicKey = await getPublicKey();
26
+ if (type === "Asymetric") {
27
+ // transmit base64
28
+ return sodium.to_base64(sodium.crypto_box_seal(sodium.from_string(plain), publicKey), sodium.base64_variants.ORIGINAL);
29
+ }
30
+ else {
31
+ const symetricKey = await getSymetricKey();
32
+ if (!symetricKey)
33
+ throw new Error("Key not initialized, call deriveKeyFromPassword() first");
34
+ const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
35
+ const ciphertext = sodium.crypto_secretbox_easy(sodium.from_string(plain), nonce, symetricKey);
36
+ const combined = new Uint8Array(nonce.length + ciphertext.length);
37
+ combined.set(nonce);
38
+ combined.set(ciphertext, nonce.length);
39
+ return sodium.to_base64(combined);
40
+ }
41
+ }
@@ -0,0 +1,2 @@
1
+ import _sodium from "libsodium-wrappers-sumo";
2
+ export declare function getSodium(): Promise<typeof _sodium>;
@@ -0,0 +1,9 @@
1
+ import _sodium from "libsodium-wrappers-sumo";
2
+ let sodium;
3
+ export async function getSodium() {
4
+ if (!sodium) {
5
+ await _sodium.ready;
6
+ sodium = _sodium;
7
+ }
8
+ return sodium;
9
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "chomot",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build",
10
+ "test": "vitest"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "keywords": [],
16
+ "author": "smwgn1331",
17
+ "license": "ISC",
18
+ "devDependencies": {
19
+ "@types/libsodium-wrappers-sumo": "^0.7.8",
20
+ "@types/node": "^24.7.2",
21
+ "tsx": "^4.20.6",
22
+ "typescript": "^5.9.3",
23
+ "vitest": "^3.2.4"
24
+ },
25
+ "dependencies": {
26
+ "libsodium-wrappers-sumo": "^0.7.15"
27
+ }
28
+ }