@abhedyam/sdk 1.0.5

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.
Files changed (4) hide show
  1. package/README.md +69 -0
  2. package/index.js +146 -0
  3. package/package.json +21 -0
  4. package/test.js +35 -0
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # Abhedya SDK for Node.js
2
+
3
+ **Unmatched Speed. Unbreakable Security.**
4
+
5
+ Abhedya is a high-performance Post-Quantum Cryptography (PQC) library enabling **Sanskrit-Encoded** encryption. This SDK provides Node.js bindings to the optimized Rust core.
6
+
7
+ ## Features
8
+
9
+ - **Quantum Safety**: Lattice-based LWE implementation ($N=768$).
10
+ - **Dual Mode**:
11
+ - **Standard**: High-throughput binary encryption.
12
+ - **Metered**: Steganographic mode producing Sanskrit-metered ciphertexts.
13
+ - **Performance**: High-speed C-FFI using `koffi` (Node.js 25+ compatible).
14
+ - **Zero-Copy**: Efficient buffer management.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install abhedya-sdk
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```javascript
25
+ const { Abhedya, EncryptionMode } = require("abhedya-sdk");
26
+
27
+ // Initialize
28
+ const sdk = new Abhedya();
29
+
30
+ // 1. Generate KeyPair
31
+ console.log("Generating Keys...");
32
+ const keys = sdk.keygen();
33
+ // keys.publicKey, keys.secretKey (Buffers)
34
+
35
+ // 2. Encrypt
36
+ const message = "The quick brown fox";
37
+ const ciphertext = sdk.encrypt(
38
+ keys.publicKey,
39
+ message,
40
+ EncryptionMode.STANDARD,
41
+ );
42
+
43
+ // 3. Decrypt
44
+ const plaintext = sdk.decrypt(keys.secretKey, ciphertext);
45
+ console.log("Decrypted:", plaintext.toString());
46
+ ```
47
+
48
+ ## API
49
+
50
+ ### `keygen()`
51
+
52
+ Returns `{ publicKey: Buffer, secretKey: Buffer }`.
53
+
54
+ ### `encrypt(publicKey, message, mode)`
55
+
56
+ - `publicKey`: Buffer
57
+ - `message`: String or Buffer
58
+ - `mode`: `EncryptionMode.STANDARD` (0) or `EncryptionMode.METERED` (1)
59
+ - Returns: `Buffer` (Ciphertext)
60
+
61
+ ### `decrypt(secretKey, ciphertext)`
62
+
63
+ - `secretKey`: Buffer
64
+ - `ciphertext`: Buffer
65
+ - Returns: `Buffer`
66
+
67
+ ## License
68
+
69
+ MIT License.
package/index.js ADDED
@@ -0,0 +1,146 @@
1
+ const koffi = require('koffi');
2
+ const path = require('path');
3
+ const os = require('os');
4
+
5
+ const EncryptionMode = {
6
+ STANDARD: 0,
7
+ METERED: 1
8
+ };
9
+
10
+ class Abhedya {
11
+ constructor(libPath) {
12
+ if (!libPath) {
13
+ libPath = this._findLibrary();
14
+ }
15
+
16
+ try {
17
+ this.lib = koffi.load(libPath);
18
+ } catch (e) {
19
+ throw new Error(`Failed to load library at ${libPath}: ${e.message}`);
20
+ }
21
+
22
+ // Define Types
23
+ // Rust boolean is usually 1 byte, but C bool can be int.
24
+ // We use size_t for lengths.
25
+
26
+ // KeyGen: (pk_buf, pk_len, sk_buf, sk_len) -> int
27
+ this.fn_keygen = this.lib.func('abhedya_keygen', 'int', ['uint8*', '_Inout_ size_t*', 'uint8*', '_Inout_ size_t*']);
28
+
29
+ // Encrypt: (pk, pk_len, msg, msg_len, mode, out, out_len) -> int
30
+ this.fn_encrypt = this.lib.func('abhedya_encrypt', 'int', ['uint8*', 'size_t', 'uint8*', 'size_t', 'int', 'uint8*', '_Inout_ size_t*']);
31
+
32
+ // Decrypt: (sk, sk_len, ct, ct_len, out, out_len) -> int
33
+ this.fn_decrypt = this.lib.func('abhedya_decrypt', 'int', ['uint8*', 'size_t', 'uint8*', 'size_t', 'uint8*', '_Inout_ size_t*']);
34
+ }
35
+
36
+ _findLibrary() {
37
+ const platform = os.platform();
38
+ let name = 'libabhedya_ffi';
39
+ let ext = '';
40
+
41
+ if (platform === 'darwin') {
42
+ ext = '.dylib';
43
+ } else if (platform === 'win32') {
44
+ name = 'abhedya_ffi';
45
+ ext = '.dll';
46
+ } else {
47
+ ext = '.so';
48
+ }
49
+
50
+ const filename = name + ext;
51
+
52
+ // Search paths:
53
+ // 1. Env var ABHEDYA_LIB
54
+ // 2. Local debug/release targets (dev mode)
55
+ // 3. System paths (production)
56
+
57
+ if (process.env.ABHEDYA_LIB) return process.env.ABHEDYA_LIB;
58
+
59
+ const devRelease = path.join(__dirname, '../../target/release', filename);
60
+ if (require('fs').existsSync(devRelease)) return devRelease;
61
+
62
+ const devDebug = path.join(__dirname, '../../target/debug', filename);
63
+ if (require('fs').existsSync(devDebug)) return devDebug;
64
+
65
+ // Fallback to expecting it in current dir or globally loadable
66
+ return filename;
67
+ }
68
+
69
+ keygen() {
70
+ // Prepare output buffers
71
+ // Kyber-768/Abhedya keys are approx: PK=1184, SK=2400.
72
+ // We allocate slightly more to be safe.
73
+ const PK_CAP = 2048;
74
+ const SK_CAP = 4096;
75
+
76
+ let pk = Buffer.alloc(PK_CAP);
77
+ let sk = Buffer.alloc(SK_CAP);
78
+
79
+ // We need pointers to lengths
80
+ let pk_len = [PK_CAP];
81
+ let sk_len = [SK_CAP];
82
+
83
+ const res = this.fn_keygen(pk, pk_len, sk, sk_len);
84
+
85
+ if (res !== 0) {
86
+ throw new Error(`KeyGen failed with code ${res}`);
87
+ }
88
+
89
+ // Slice to actual size
90
+ // koffi updates the array/object passed for Inout
91
+ return {
92
+ publicKey: pk.subarray(0, pk_len[0]),
93
+ secretKey: sk.subarray(0, sk_len[0])
94
+ };
95
+ }
96
+
97
+ encrypt(pk, msg, mode = EncryptionMode.STANDARD) {
98
+ if (!Buffer.isBuffer(pk)) pk = Buffer.from(pk);
99
+ if (!Buffer.isBuffer(msg)) msg = Buffer.from(msg);
100
+
101
+ // Estimate ciphertext size
102
+ // Standard ~1KB, Metered can be larger.
103
+ // 2x message size + overhead should be plenty for safety,
104
+ // or just a fixed large buffer (e.g. 16KB) if unsure.
105
+ // For Abhedya, CT is fixed size for a block, but let's assume worst case.
106
+ const CT_CAP = 1024 * 64; // 64KB safe upper bound
107
+ let ct = Buffer.alloc(CT_CAP);
108
+ let ct_len = [CT_CAP];
109
+
110
+ const res = this.fn_encrypt(
111
+ pk, pk.length,
112
+ msg, msg.length,
113
+ mode,
114
+ ct, ct_len
115
+ );
116
+
117
+ if (res !== 0) {
118
+ throw new Error(`Encrypt failed with code ${res}`);
119
+ }
120
+
121
+ return ct.subarray(0, ct_len[0]);
122
+ }
123
+
124
+ decrypt(sk, ct) {
125
+ if (!Buffer.isBuffer(sk)) sk = Buffer.from(sk);
126
+ if (!Buffer.isBuffer(ct)) ct = Buffer.from(ct);
127
+
128
+ const OUT_CAP = 1024 * 64;
129
+ let out = Buffer.alloc(OUT_CAP);
130
+ let out_len = [OUT_CAP];
131
+
132
+ const res = this.fn_decrypt(
133
+ sk, sk.length,
134
+ ct, ct.length,
135
+ out, out_len
136
+ );
137
+
138
+ if (res !== 0) {
139
+ throw new Error(`Decrypt failed with code ${res}`);
140
+ }
141
+
142
+ return out.subarray(0, out_len[0]);
143
+ }
144
+ }
145
+
146
+ module.exports = { Abhedya, EncryptionMode };
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@abhedyam/sdk",
3
+ "version": "1.0.5",
4
+ "description": "Node.js SDK for Abhedya: Sanskrit-Encoded Post-Quantum Cryptography",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "index.js",
9
+ "scripts": {
10
+ "test": "node test.js"
11
+ },
12
+ "dependencies": {
13
+ "koffi": "^2.9.0"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/ParamTatva-org/abhedyam.git"
18
+ },
19
+ "author": "Abhedyam Project",
20
+ "license": "MIT"
21
+ }
package/test.js ADDED
@@ -0,0 +1,35 @@
1
+ const { Abhedya, EncryptionMode } = require('./index');
2
+
3
+ console.log("--- Testing Abhedya Node.js SDK ---");
4
+
5
+ try {
6
+ const crypto = new Abhedya();
7
+
8
+ // 1. KeyGen
9
+ console.log("Generating Keys...");
10
+ const keys = crypto.keygen();
11
+ console.log(`KeyGen Success. PK Size: ${keys.publicKey.length}, SK Size: ${keys.secretKey.length}`);
12
+
13
+ // 2. Encrypt
14
+ const msg = "Hello from Node.js!";
15
+ console.log(`Encrypting message: "${msg}"`);
16
+ const ct = crypto.encrypt(keys.publicKey, msg, EncryptionMode.STANDARD);
17
+ console.log(`Encryption Success. CT Size: ${ct.length}`);
18
+
19
+ // 3. Decrypt
20
+ console.log("Decrypting...");
21
+ const recovered = crypto.decrypt(keys.secretKey, ct);
22
+ const recoveredStr = recovered.toString('utf8').replace(/\0/g, ''); // Trim nulls
23
+ console.log(`Decrypted: "${recoveredStr}"`);
24
+
25
+ if (recovered.includes(Buffer.from(msg))) {
26
+ console.log("PASS: Decrypted message matches original.");
27
+ } else {
28
+ console.log("FAIL: Mismatch.");
29
+ }
30
+
31
+ } catch (e) {
32
+ console.error("Test Failed:", e.message);
33
+ // Note: This will fail if ffi-napi is not installed.
34
+ // This is expected in this environment if npm install hasn't run.
35
+ }