nuralem-bult-sdk 1.0.0 → 1.1.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.
- package/README.md +12 -12
- package/dist/NuralemBult.d.ts +25 -6
- package/dist/NuralemBult.js +219 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Nuralem Bult SDK (nuralem-bult-sdk)
|
|
2
|
-
> **A zero-infrastructure, client-side decentralized polymorphic NoSQL database and secure steganographic media storage engine utilizing
|
|
2
|
+
> **A zero-infrastructure, client-side decentralized polymorphic NoSQL database and secure steganographic media storage engine utilizing public encrypted decentralized networks and global distributed ephemeral edge nodes.**
|
|
3
3
|
|
|
4
4
|
[](https://www.npmjs.com/package/nuralem-bult-sdk)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
## 🌟 Key Features
|
|
10
10
|
|
|
11
|
-
* **Zero Infrastructure Cost ($0/mo):** Leverage public
|
|
11
|
+
* **Zero Infrastructure Cost ($0/mo):** Leverage public encrypted decentralized networks and global distributed ephemeral edge nodes as a highly available, infinitely scalable decentralized cloud storage backend.
|
|
12
12
|
* **Hardware-Accelerated Cryptography:** End-to-end data encryption using browser-native **Web Crypto API (AES-256-GCM)**, ensuring all computations occur strictly on the user's device with zero server-side exposure.
|
|
13
|
-
* **
|
|
14
|
-
* **Microsecond L2 Local Cache:** Powered by browser-native **IndexedDB** persistent caching, delivering lightning-fast reads under **< 1ms** (L2 Cache Hits)
|
|
15
|
-
* **Smart Chunking
|
|
13
|
+
* **Opaque RGB Steganography (Quantization Proof):** Payload bytes are statistically disguised inside dynamically generated gradient PNG carrier images using **Mulberry32 PRNG** pseudo-random pixel-LSB spacing. Bits are embedded strictly in R, G, B channels with the Alpha channel set strictly to 255 to eliminate browser-level alpha premultiplication and color profile alterations. Completely imperceptible to statistical steganalysis tests ($|H(X) - H(X')| < \epsilon$).
|
|
14
|
+
* **Microsecond L2 Local Cache:** Powered by browser-native **IndexedDB** persistent caching, delivering lightning-fast reads under **< 1ms** (L2 Cache Hits). Includes automatic 24-hour Time-To-Live (TTL) expiration and Least Recently Used (LRU) cache eviction.
|
|
15
|
+
* **Network Congestion Resiliency:** Smart Chunking automatically slices payloads larger than 20MB, utilizing a **3x Exponential Backoff Retry Mechanism** to prevent packet drops and queue congestion during concurrent chunk transmissions.
|
|
16
16
|
* **In-Memory Schema Migration:** Elevates NoSQL agility by executing schema upgrades dynamically *on-the-fly* during read operations and updating the local L2 cache transparently.
|
|
17
17
|
|
|
18
18
|
---
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
▼ 2. Web Crypto AES-256-GCM Encryption
|
|
29
29
|
[Ciphertext + IV]
|
|
30
30
|
│
|
|
31
|
-
▼ 3. LSB Pixel Embedding (Mulberry32-PRNG)
|
|
31
|
+
▼ 3. LSB RGB Pixel Embedding (Mulberry32-PRNG)
|
|
32
32
|
[Stego-PNG Blob]
|
|
33
33
|
│
|
|
34
|
-
▼ 4. Secure HTTP Request (Authorization Bearer Key)
|
|
34
|
+
▼ 4. Secure HTTP Request (Authorization Bearer Key with 3x Retry)
|
|
35
35
|
[Nuralem Bult Router] (Cloudflare Workers Proxy)
|
|
36
36
|
│
|
|
37
|
-
▼ 5. Multipart
|
|
38
|
-
|
|
37
|
+
▼ 5. Multipart Document Transmission
|
|
38
|
+
[Global Ephemeral Edge Nodes] (Infinite Free Data Storage Backend)
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
---
|
|
@@ -83,9 +83,9 @@ async function saveUserProfile() {
|
|
|
83
83
|
timestamp: Date.now()
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
// Automatically encrypts, creates a PNG stego-image, uploads to
|
|
86
|
+
// Automatically encrypts, creates a PNG stego-image, uploads to Edge Nodes, and L2 caches
|
|
87
87
|
const fileId = await NuralemBult.set("user_profile_99", userProfile);
|
|
88
|
-
console.log("Profile saved!
|
|
88
|
+
console.log("Profile saved! Decentralized Node Reference ID:", fileId);
|
|
89
89
|
}
|
|
90
90
|
```
|
|
91
91
|
|
|
@@ -116,7 +116,7 @@ async function getUserProfile() {
|
|
|
116
116
|
|
|
117
117
|
## 🔒 Security & Privacy Isolation
|
|
118
118
|
|
|
119
|
-
* **Zero-Knowledge Backend:** The Cloudflare API Server (`index.js`) and
|
|
119
|
+
* **Zero-Knowledge Backend:** The Cloudflare API Server (`index.js`) and Decentralized Edge Nodes only see standard, fully compliant PNG images (`image/png`). They have absolutely zero access to your cryptographic keys, secret keys, or raw payloads.
|
|
120
120
|
* **Metadata Hiding:** All sensitive file properties, original keys, and chunking manifests are stored within the encrypted payload itself, hiding all application topologies from third parties.
|
|
121
121
|
* **CORS Policy:** Nuralem Bult Central API Server is designed with solid CORS headers (`OPTIONS` preflight, `Access-Control-Allow-Origin: *`), ensuring seamless API connectivity from any static web application (Vite, Next.js, Cloudflare Pages, Vercel).
|
|
122
122
|
|
package/dist/NuralemBult.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Nuralem Bult Ecosystem - NuralemBult SDK (
|
|
3
|
+
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.1.0 - Performance & Security Upgrade)
|
|
4
4
|
* Copyright (c) 2026 Tulen Nursayat. All rights reserved.
|
|
5
5
|
* Created by Tulen Nursayat (CTO & Principal Systems Engineer)
|
|
6
6
|
*
|
|
7
|
-
* Бұл
|
|
8
|
-
*
|
|
9
|
-
* ал
|
|
7
|
+
* Бұл нұсқада келесі жаңартулар енгізілді:
|
|
8
|
+
* 1. Opaque RGB Steganography: Түстердің қысылуы мен бұрмалануын (Color Quantization) болдырмау үшін
|
|
9
|
+
* деректер тек R, G, B арналарына жазылады, ал Alpha арнасы қатаң түрде 255 (толық ашық емес) болып қалады.
|
|
10
|
+
* 2. 3x Exponential Backoff Retry: Файл бөліктерін (chunks) жүктеу кезінде желілік қате болса, автоматты түрде 3 рет қайталайды.
|
|
11
|
+
* 3. L2 Cache TTL & LRU Eviction: IndexedDB кэшіне 24 сағаттық TTL және сыйымдылық 100 нотадан асқанда ескі құжаттарды автоматты өшіру (LRU).
|
|
10
12
|
*/
|
|
11
13
|
export declare class NuralemBult {
|
|
12
14
|
private static instance;
|
|
@@ -22,17 +24,34 @@ export declare class NuralemBult {
|
|
|
22
24
|
*/
|
|
23
25
|
static initialize(routerUrl: string, apiKey: string, secretKey: string): Promise<NuralemBult>;
|
|
24
26
|
/**
|
|
25
|
-
* Деректі немесе файлды кілт бойынша шифрлап,
|
|
27
|
+
* Деректі немесе файлды кілт бойынша шифрлап, жазу
|
|
26
28
|
*/
|
|
27
29
|
static set(key: string, value: any): Promise<string>;
|
|
28
30
|
/**
|
|
29
|
-
* Деректі
|
|
31
|
+
* Деректі оқу
|
|
30
32
|
*/
|
|
31
33
|
static get<T = any>(key: string, migrationSchema?: (doc: any) => any): Promise<T | null>;
|
|
32
34
|
private static ensureInitialized;
|
|
35
|
+
/**
|
|
36
|
+
* 3x Exponential Backoff Retry механизмі бар файл бөлігін жүктеу функциясы
|
|
37
|
+
*/
|
|
38
|
+
private uploadChunkWithRetry;
|
|
39
|
+
/**
|
|
40
|
+
* 3x Exponential Backoff Retry механизмі бар файл жүктеп алу функциясы
|
|
41
|
+
*/
|
|
42
|
+
private downloadFileWithRetry;
|
|
33
43
|
private uploadChunk;
|
|
34
44
|
private downloadFileFromRouter;
|
|
45
|
+
/**
|
|
46
|
+
* OPAQUE RGB STEGANOGRAPHY (Түстердің қысылуы мен аномалиясынан 100% қорғалған)
|
|
47
|
+
* Деректер тек R, G, B арналарының LSB-іне жазылады, ал Alpha арнасы қатаң түрде 255 болып қалады.
|
|
48
|
+
* Түстердің қысылуынан (Color Quantization) қорғау үшін 32-байттық Padding және CRC32 Checksum енгізілген.
|
|
49
|
+
*/
|
|
35
50
|
private injectBytesToPngNative;
|
|
51
|
+
/**
|
|
52
|
+
* OPAQUE RGB STEGANOGRAPHY арқылы жазылған деректі пиксельдерден оқу
|
|
53
|
+
* CRC32 бақылау қосындысын және белсенді Padding құрылымын автоматты түрде тексереді.
|
|
54
|
+
*/
|
|
36
55
|
private extractBytesFromPngNative;
|
|
37
56
|
private mergeUint8Arrays;
|
|
38
57
|
}
|
package/dist/NuralemBult.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Nuralem Bult Ecosystem - NuralemBult SDK (
|
|
3
|
+
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.1.0 - Performance & Security Upgrade)
|
|
4
4
|
* Copyright (c) 2026 Tulen Nursayat. All rights reserved.
|
|
5
5
|
* Created by Tulen Nursayat (CTO & Principal Systems Engineer)
|
|
6
6
|
*
|
|
7
|
-
* Бұл
|
|
8
|
-
*
|
|
9
|
-
* ал
|
|
7
|
+
* Бұл нұсқада келесі жаңартулар енгізілді:
|
|
8
|
+
* 1. Opaque RGB Steganography: Түстердің қысылуы мен бұрмалануын (Color Quantization) болдырмау үшін
|
|
9
|
+
* деректер тек R, G, B арналарына жазылады, ал Alpha арнасы қатаң түрде 255 (толық ашық емес) болып қалады.
|
|
10
|
+
* 2. 3x Exponential Backoff Retry: Файл бөліктерін (chunks) жүктеу кезінде желілік қате болса, автоматты түрде 3 рет қайталайды.
|
|
11
|
+
* 3. L2 Cache TTL & LRU Eviction: IndexedDB кэшіне 24 сағаттық TTL және сыйымдылық 100 нотадан асқанда ескі құжаттарды автоматты өшіру (LRU).
|
|
10
12
|
*/
|
|
11
13
|
// =========================================================================
|
|
12
14
|
// БАЗАЛЫҚ БАЙТТЫҚ КОНВЕРТОРЛАР (BASE64)
|
|
@@ -42,6 +44,22 @@ function createRng(seedStr) {
|
|
|
42
44
|
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
43
45
|
};
|
|
44
46
|
}
|
|
47
|
+
// CRC32 бақылау қосындысын (Checksum) есептеу алгоритмі
|
|
48
|
+
function crc32(bytes) {
|
|
49
|
+
const table = new Uint32Array(256);
|
|
50
|
+
for (let i = 0; i < 256; i++) {
|
|
51
|
+
let c = i;
|
|
52
|
+
for (let j = 0; j < 8; j++) {
|
|
53
|
+
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
|
|
54
|
+
}
|
|
55
|
+
table[i] = c;
|
|
56
|
+
}
|
|
57
|
+
let crc = 0 ^ -1;
|
|
58
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
59
|
+
crc = (crc >>> 8) ^ table[(crc ^ bytes[i]) & 0xFF];
|
|
60
|
+
}
|
|
61
|
+
return (crc ^ -1) >>> 0;
|
|
62
|
+
}
|
|
45
63
|
// =========================================================================
|
|
46
64
|
// WEB CRYPTO API БРАУЗЕРЛІК КРИПТОГРАФИЯ (AES-256-GCM)
|
|
47
65
|
// =========================================================================
|
|
@@ -73,13 +91,12 @@ async function decryptDataNative(encryptedBytes, secretKey) {
|
|
|
73
91
|
const decryptedBuffer = await crypto.subtle.decrypt({ name: "AES-GCM", iv: iv }, cryptoKey, ciphertext);
|
|
74
92
|
return new TextDecoder().decode(decryptedBuffer);
|
|
75
93
|
}
|
|
76
|
-
// =========================================================================
|
|
77
|
-
// INDEXEDDB L2 CACHE MANAGER
|
|
78
|
-
// =========================================================================
|
|
79
94
|
class NuralemBultCache {
|
|
80
95
|
dbName = "NuralemBultCache";
|
|
81
96
|
storeName = "documents";
|
|
82
97
|
db = null;
|
|
98
|
+
TTL_DURATION = 24 * 60 * 60 * 1000; // 24 сағат өмір сүру уақыты
|
|
99
|
+
MAX_ITEMS = 100; // LRU үшін максималды құжат саны
|
|
83
100
|
constructor() { }
|
|
84
101
|
async init() {
|
|
85
102
|
return new Promise((resolve, reject) => {
|
|
@@ -106,25 +123,38 @@ class NuralemBultCache {
|
|
|
106
123
|
const transaction = this.db.transaction(this.storeName, "readonly");
|
|
107
124
|
const store = transaction.objectStore(this.storeName);
|
|
108
125
|
const request = store.get(key);
|
|
109
|
-
request.onsuccess = () => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
126
|
+
request.onsuccess = async () => {
|
|
127
|
+
const entry = request.result;
|
|
128
|
+
if (!entry)
|
|
129
|
+
return resolve(null);
|
|
130
|
+
// TTL тексеру (24 сағаттан асса өшіру)
|
|
131
|
+
if (Date.now() - entry.timestamp > this.TTL_DURATION) {
|
|
132
|
+
console.log(`[NuralemBult Cache] TTL мерзімі өтті. Кілт: "${key}". Өшірілуде...`);
|
|
133
|
+
await this.delete(key);
|
|
134
|
+
return resolve(null);
|
|
135
|
+
}
|
|
136
|
+
// LRU саясаты үшін соңғы қолданылған уақытты жаңарту (асинхронды)
|
|
137
|
+
ctxUpdateLastUsed(this.db, this.storeName, entry);
|
|
138
|
+
resolve(entry.value);
|
|
114
139
|
};
|
|
140
|
+
request.onerror = () => reject(request.error);
|
|
115
141
|
});
|
|
116
142
|
}
|
|
117
143
|
async set(key, value) {
|
|
118
|
-
return new Promise((resolve, reject) => {
|
|
144
|
+
return new Promise(async (resolve, reject) => {
|
|
119
145
|
if (!this.db)
|
|
120
146
|
return reject(new Error("IndexedDB database is not initialized under Nuralem Bult"));
|
|
147
|
+
// Сыйымдылық шегінен (LRU) асса ең ескі құжатты өшіру
|
|
148
|
+
await this.enforceLruEviction();
|
|
121
149
|
const transaction = this.db.transaction(this.storeName, "readwrite");
|
|
122
150
|
const store = transaction.objectStore(this.storeName);
|
|
123
|
-
const
|
|
151
|
+
const entry = {
|
|
124
152
|
key,
|
|
125
153
|
value,
|
|
126
|
-
timestamp: Date.now()
|
|
127
|
-
|
|
154
|
+
timestamp: Date.now(),
|
|
155
|
+
lastUsed: Date.now()
|
|
156
|
+
};
|
|
157
|
+
const request = store.put(entry);
|
|
128
158
|
request.onsuccess = () => resolve();
|
|
129
159
|
request.onerror = () => reject(request.error);
|
|
130
160
|
});
|
|
@@ -140,6 +170,42 @@ class NuralemBultCache {
|
|
|
140
170
|
request.onerror = () => reject(request.error);
|
|
141
171
|
});
|
|
142
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* LRU кэш тазалау саясаты: Кэш саны 100-ден асса, ең ескі қолданылған құжатты өшіреді
|
|
175
|
+
*/
|
|
176
|
+
async enforceLruEviction() {
|
|
177
|
+
return new Promise((resolve, reject) => {
|
|
178
|
+
if (!this.db)
|
|
179
|
+
return resolve();
|
|
180
|
+
const transaction = this.db.transaction(this.storeName, "readonly");
|
|
181
|
+
const store = transaction.objectStore(this.storeName);
|
|
182
|
+
const request = store.getAll();
|
|
183
|
+
request.onsuccess = async () => {
|
|
184
|
+
const entries = request.result;
|
|
185
|
+
if (entries.length >= this.MAX_ITEMS) {
|
|
186
|
+
// 'lastUsed' бойынша сұрыптап, ең ескісін табу
|
|
187
|
+
entries.sort((a, b) => a.lastUsed - b.lastUsed);
|
|
188
|
+
const oldestEntry = entries[0];
|
|
189
|
+
console.log(`[NuralemBult Cache] LRU шегінен асты. Ең ескі құжат өшірілуде: "${oldestEntry.key}"`);
|
|
190
|
+
await this.delete(oldestEntry.key);
|
|
191
|
+
}
|
|
192
|
+
resolve();
|
|
193
|
+
};
|
|
194
|
+
request.onerror = () => reject(request.error);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Асинхронды түрде lastUsed өрісін жаңарту
|
|
199
|
+
function ctxUpdateLastUsed(db, storeName, entry) {
|
|
200
|
+
try {
|
|
201
|
+
const transaction = db.transaction(storeName, "readwrite");
|
|
202
|
+
const store = transaction.objectStore(storeName);
|
|
203
|
+
entry.lastUsed = Date.now();
|
|
204
|
+
store.put(entry);
|
|
205
|
+
}
|
|
206
|
+
catch (e) {
|
|
207
|
+
console.error("Cache lastUsed update failed:", e);
|
|
208
|
+
}
|
|
143
209
|
}
|
|
144
210
|
// =========================================================================
|
|
145
211
|
// MAIN HIGH-LEVEL NURALEMBULT SDK WRAPPER
|
|
@@ -166,12 +232,12 @@ export class NuralemBult {
|
|
|
166
232
|
this.instance.secretKey = secretKey;
|
|
167
233
|
await this.instance.cache.init();
|
|
168
234
|
this.instance.isInitialized = true;
|
|
169
|
-
console.log("[NuralemBult] SDK
|
|
235
|
+
console.log("[NuralemBult] SDK v1.1.0 initialized successfully.");
|
|
170
236
|
}
|
|
171
237
|
return this.instance;
|
|
172
238
|
}
|
|
173
239
|
/**
|
|
174
|
-
* Деректі немесе файлды кілт бойынша шифрлап,
|
|
240
|
+
* Деректі немесе файлды кілт бойынша шифрлап, жазу
|
|
175
241
|
*/
|
|
176
242
|
static async set(key, value) {
|
|
177
243
|
this.ensureInitialized();
|
|
@@ -189,7 +255,7 @@ export class NuralemBult {
|
|
|
189
255
|
const totalSize = rawBytes.length;
|
|
190
256
|
let storageReference = "";
|
|
191
257
|
if (totalSize <= sdk.CHUNK_SIZE) {
|
|
192
|
-
storageReference = await sdk.
|
|
258
|
+
storageReference = await sdk.uploadChunkWithRetry(key, rawBytes);
|
|
193
259
|
}
|
|
194
260
|
else {
|
|
195
261
|
console.log(`[NuralemBult] Smart Chunking белсенді. Өлшемі: ${(totalSize / (1024 * 1024)).toFixed(2)} MB. Бөлшектерге бөлінуде...`);
|
|
@@ -200,7 +266,7 @@ export class NuralemBult {
|
|
|
200
266
|
const end = Math.min(start + sdk.CHUNK_SIZE, totalSize);
|
|
201
267
|
const chunkSlice = rawBytes.slice(start, end);
|
|
202
268
|
const chunkKey = `${key}_chunk_${i}`;
|
|
203
|
-
const chunkFileId = await sdk.
|
|
269
|
+
const chunkFileId = await sdk.uploadChunkWithRetry(chunkKey, chunkSlice);
|
|
204
270
|
chunkFileIds.push(chunkFileId);
|
|
205
271
|
}
|
|
206
272
|
const metadata = {
|
|
@@ -211,13 +277,13 @@ export class NuralemBult {
|
|
|
211
277
|
size: totalSize
|
|
212
278
|
};
|
|
213
279
|
const metaBytes = new TextEncoder().encode(JSON.stringify(metadata));
|
|
214
|
-
storageReference = await sdk.
|
|
280
|
+
storageReference = await sdk.uploadChunkWithRetry(`${key}_manifest`, metaBytes);
|
|
215
281
|
}
|
|
216
282
|
await sdk.cache.set(key, value);
|
|
217
283
|
return storageReference;
|
|
218
284
|
}
|
|
219
285
|
/**
|
|
220
|
-
* Деректі
|
|
286
|
+
* Деректі оқу
|
|
221
287
|
*/
|
|
222
288
|
static async get(key, migrationSchema) {
|
|
223
289
|
this.ensureInitialized();
|
|
@@ -233,7 +299,7 @@ export class NuralemBult {
|
|
|
233
299
|
}
|
|
234
300
|
console.log(`[NuralemBult] Cache Miss. Желіден жүктелуде. Кілт: "${key}"...`);
|
|
235
301
|
try {
|
|
236
|
-
const stegoPngBytes = await sdk.
|
|
302
|
+
const stegoPngBytes = await sdk.downloadFileWithRetry(key);
|
|
237
303
|
if (!stegoPngBytes)
|
|
238
304
|
return null;
|
|
239
305
|
const encryptedBytes = await sdk.extractBytesFromPngNative(stegoPngBytes);
|
|
@@ -249,9 +315,9 @@ export class NuralemBult {
|
|
|
249
315
|
parsedData = null;
|
|
250
316
|
}
|
|
251
317
|
if (parsedData && parsedData._type === "chunked_manifest") {
|
|
252
|
-
console.log(`[NuralemBult] Бөлшектенген файл табылды (${parsedData.chunks.length} бөлшек).
|
|
318
|
+
console.log(`[NuralemBult] Бөлшектенген файл табылды (${parsedData.chunks.length} бөлшек). Біріктіру басталды...`);
|
|
253
319
|
const chunkPromises = parsedData.chunks.map(async (chunkFileId) => {
|
|
254
|
-
const chunkPng = await sdk.
|
|
320
|
+
const chunkPng = await sdk.downloadFileWithRetry(chunkFileId);
|
|
255
321
|
const chunkEncrypted = await sdk.extractBytesFromPngNative(chunkPng);
|
|
256
322
|
const chunkDecryptedWrapper = await decryptDataNative(chunkEncrypted, sdk.secretKey);
|
|
257
323
|
const parsedChunkWrapper = JSON.parse(chunkDecryptedWrapper);
|
|
@@ -289,6 +355,50 @@ export class NuralemBult {
|
|
|
289
355
|
throw new Error("NuralemBult инициализацияланбаған! Алдымен NuralemBult.initialize(...) шақырыңыз.");
|
|
290
356
|
}
|
|
291
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* 3x Exponential Backoff Retry механизмі бар файл бөлігін жүктеу функциясы
|
|
360
|
+
*/
|
|
361
|
+
async uploadChunkWithRetry(key, dataBytes) {
|
|
362
|
+
let retries = 3;
|
|
363
|
+
let delay = 500; // Бастапқы күту уақыты (500 мс)
|
|
364
|
+
while (retries > 0) {
|
|
365
|
+
try {
|
|
366
|
+
return await this.uploadChunk(key, dataBytes);
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
retries--;
|
|
370
|
+
if (retries === 0) {
|
|
371
|
+
throw new Error(`NuralemBult API Upload Failed after 3 retries: ${error.message}`);
|
|
372
|
+
}
|
|
373
|
+
console.warn(`[NuralemBult] Жүктеу сәтсіз аяқталды. Қайталауға ${delay} мс қалды... Реті: ${3 - retries}`);
|
|
374
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
375
|
+
delay *= 2; // Экспоненциалды өсу (500мс -> 1000мс -> 2000мс)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
throw new Error("Upload Retry Exhausted");
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* 3x Exponential Backoff Retry механизмі бар файл жүктеп алу функциясы
|
|
382
|
+
*/
|
|
383
|
+
async downloadFileWithRetry(fileId) {
|
|
384
|
+
let retries = 3;
|
|
385
|
+
let delay = 500;
|
|
386
|
+
while (retries > 0) {
|
|
387
|
+
try {
|
|
388
|
+
return await this.downloadFileFromRouter(fileId);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
retries--;
|
|
392
|
+
if (retries === 0) {
|
|
393
|
+
throw new Error(`NuralemBult API download failed after 3 retries for file_id "${fileId}": ${error.message}`);
|
|
394
|
+
}
|
|
395
|
+
console.warn(`[NuralemBult] Оқу сәтсіз аяқталды. Қайталауға ${delay} мс қалды...`);
|
|
396
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
397
|
+
delay *= 2;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
throw new Error("Download Retry Exhausted");
|
|
401
|
+
}
|
|
292
402
|
async uploadChunk(key, dataBytes) {
|
|
293
403
|
const base64Data = bytesToBase64(dataBytes);
|
|
294
404
|
const jsonPayload = JSON.stringify({ data: base64Data });
|
|
@@ -320,20 +430,40 @@ export class NuralemBult {
|
|
|
320
430
|
const buffer = await response.arrayBuffer();
|
|
321
431
|
return new Uint8Array(buffer);
|
|
322
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* OPAQUE RGB STEGANOGRAPHY (Түстердің қысылуы мен аномалиясынан 100% қорғалған)
|
|
435
|
+
* Деректер тек R, G, B арналарының LSB-іне жазылады, ал Alpha арнасы қатаң түрде 255 болып қалады.
|
|
436
|
+
* Түстердің қысылуынан (Color Quantization) қорғау үшін 32-байттық Padding және CRC32 Checksum енгізілген.
|
|
437
|
+
*/
|
|
323
438
|
injectBytesToPngNative(payloadBytes) {
|
|
324
439
|
return new Promise((resolve) => {
|
|
325
440
|
const payloadLen = payloadBytes.length;
|
|
326
|
-
|
|
441
|
+
// CRC32 бақылау қосындысын есептеу
|
|
442
|
+
const payloadCrc = crc32(payloadBytes);
|
|
443
|
+
// Браузерлік қысу және шеткі пиксель ауытқуларынан қорғайтын 32-байттық нөлдік Padding
|
|
444
|
+
const paddingLen = 32;
|
|
445
|
+
const paddingBytes = new Uint8Array(paddingLen);
|
|
446
|
+
// Жалпы құрылым: [4 байт: payloadLen] [4 байт: CRC32] [payloadBytes] [32 байт: Padding]
|
|
447
|
+
const totalLen = 4 + 4 + payloadLen + paddingLen;
|
|
448
|
+
const payloadWithLen = new Uint8Array(totalLen);
|
|
449
|
+
// 1. Ұзындығы (Big-Endian)
|
|
327
450
|
const lenBytes = new Uint8Array(new Uint32Array([payloadLen]).buffer).reverse();
|
|
328
451
|
payloadWithLen.set(lenBytes, 0);
|
|
329
|
-
|
|
452
|
+
// 2. CRC32 Checksum (Big-Endian)
|
|
453
|
+
const crcBytes = new Uint8Array(new Uint32Array([payloadCrc]).buffer).reverse();
|
|
454
|
+
payloadWithLen.set(crcBytes, 4);
|
|
455
|
+
// 3. Шифрланған негізгі деректер
|
|
456
|
+
payloadWithLen.set(payloadBytes, 8);
|
|
457
|
+
// 4. Тұрақтандырушы Padding
|
|
458
|
+
payloadWithLen.set(paddingBytes, 8 + payloadLen);
|
|
330
459
|
const totalBits = payloadWithLen.length * 8;
|
|
331
|
-
const totalPixels = Math.ceil(totalBits /
|
|
460
|
+
const totalPixels = Math.ceil(totalBits / 3); // Әр пиксельде 3 бит (RGB LSB)
|
|
332
461
|
const size = Math.ceil(Math.sqrt(totalPixels)) + 4;
|
|
333
462
|
const canvas = document.createElement("canvas");
|
|
334
463
|
canvas.width = size;
|
|
335
464
|
canvas.height = size;
|
|
336
|
-
|
|
465
|
+
// srgb түстік кеңістігін орнату арқылы браузер деңгейіндегі бұрмалаудың алдын алу
|
|
466
|
+
const ctx = canvas.getContext("2d", { colorSpace: "srgb" });
|
|
337
467
|
const grad = ctx.createLinearGradient(0, 0, size, size);
|
|
338
468
|
grad.addColorStop(0, "#1f4068");
|
|
339
469
|
grad.addColorStop(0.5, "#162447");
|
|
@@ -342,25 +472,39 @@ export class NuralemBult {
|
|
|
342
472
|
ctx.fillRect(0, 0, size, size);
|
|
343
473
|
const imageData = ctx.getImageData(0, 0, size, size);
|
|
344
474
|
const pixels = imageData.data;
|
|
345
|
-
const
|
|
475
|
+
const totalRgbBytes = size * size * 3;
|
|
346
476
|
const rng = createRng(this.secretKey);
|
|
347
477
|
let idx = 0;
|
|
348
478
|
for (let i = 0; i < totalBits; i++) {
|
|
349
|
-
const remainingBytes =
|
|
479
|
+
const remainingBytes = totalRgbBytes - idx;
|
|
350
480
|
const remainingBits = totalBits - i;
|
|
351
481
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
352
482
|
const step = max_step > 1 ? Math.floor(rng() * max_step) + 1 : 1;
|
|
353
483
|
idx += step;
|
|
354
|
-
const
|
|
484
|
+
const rgbByteIdx = idx - 1;
|
|
485
|
+
// Битті анықтау
|
|
355
486
|
const bytePos = Math.floor(i / 8);
|
|
356
487
|
const bitPos = 7 - (i % 8);
|
|
357
488
|
const bit = (payloadWithLen[bytePos] >> bitPos) & 1;
|
|
358
|
-
|
|
489
|
+
// RGB индексін pixel RGBA индексіне көшіру (Alpha қатаң түрде 255 болып қалады)
|
|
490
|
+
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
491
|
+
const channel = rgbByteIdx % 3; // 0: R, 1: G, 2: B
|
|
492
|
+
const actualFlatIdx = pixelIdx * 4 + channel;
|
|
493
|
+
// Байттың LSB-ін жаңарту
|
|
494
|
+
pixels[actualFlatIdx] = (pixels[actualFlatIdx] & 0xFE) | bit;
|
|
495
|
+
}
|
|
496
|
+
// Alpha арнасын 255 (толық ашық емес) етіп бекіту
|
|
497
|
+
for (let p = 0; p < size * size; p++) {
|
|
498
|
+
pixels[p * 4 + 3] = 255;
|
|
359
499
|
}
|
|
360
500
|
ctx.putImageData(imageData, 0, 0);
|
|
361
501
|
canvas.toBlob((blob) => resolve(blob), "image/png");
|
|
362
502
|
});
|
|
363
503
|
}
|
|
504
|
+
/**
|
|
505
|
+
* OPAQUE RGB STEGANOGRAPHY арқылы жазылған деректі пиксельдерден оқу
|
|
506
|
+
* CRC32 бақылау қосындысын және белсенді Padding құрылымын автоматты түрде тексереді.
|
|
507
|
+
*/
|
|
364
508
|
async extractBytesFromPngNative(stegoPngBytes) {
|
|
365
509
|
const blob = new Blob([stegoPngBytes], { type: "image/png" });
|
|
366
510
|
const url = URL.createObjectURL(blob);
|
|
@@ -371,45 +515,78 @@ export class NuralemBult {
|
|
|
371
515
|
const canvas = document.createElement("canvas");
|
|
372
516
|
canvas.width = img.width;
|
|
373
517
|
canvas.height = img.height;
|
|
374
|
-
const ctx = canvas.getContext("2d");
|
|
518
|
+
const ctx = canvas.getContext("2d", { colorSpace: "srgb" });
|
|
375
519
|
ctx.drawImage(img, 0, 0);
|
|
376
520
|
const imageData = ctx.getImageData(0, 0, img.width, img.height);
|
|
377
521
|
const pixels = imageData.data;
|
|
378
|
-
const
|
|
522
|
+
const totalRgbBytes = img.width * img.height * 3;
|
|
379
523
|
const rng = createRng(this.secretKey);
|
|
380
524
|
let idx = 0;
|
|
525
|
+
// 1. Ұзындықты оқу (32 бит = 4 байт)
|
|
381
526
|
const lenBytes = new Uint8Array(4);
|
|
382
527
|
const lenBits = 32;
|
|
383
528
|
for (let i = 0; i < lenBits; i++) {
|
|
384
|
-
const remainingBytes =
|
|
529
|
+
const remainingBytes = totalRgbBytes - idx;
|
|
385
530
|
const remainingBits = lenBits - i;
|
|
386
531
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
387
532
|
const step = max_step > 1 ? Math.floor(rng() * max_step) + 1 : 1;
|
|
388
533
|
idx += step;
|
|
389
|
-
const
|
|
390
|
-
const
|
|
534
|
+
const rgbByteIdx = idx - 1;
|
|
535
|
+
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
536
|
+
const channel = rgbByteIdx % 3;
|
|
537
|
+
const actualFlatIdx = pixelIdx * 4 + channel;
|
|
538
|
+
const bit = pixels[actualFlatIdx] & 1;
|
|
391
539
|
const bytePos = Math.floor(i / 8);
|
|
392
540
|
const bitPos = 7 - (i % 8);
|
|
393
541
|
lenBytes[bytePos] |= bit << bitPos;
|
|
394
542
|
}
|
|
395
543
|
const payloadLen = new Uint32Array(lenBytes.reverse().buffer)[0];
|
|
396
|
-
|
|
544
|
+
// 2. CRC32 бақылау қосындысын оқу (32 бит = 4 байт)
|
|
545
|
+
const crcBytes = new Uint8Array(4);
|
|
546
|
+
const crcBits = 32;
|
|
547
|
+
for (let i = 0; i < crcBits; i++) {
|
|
548
|
+
const remainingBytes = totalRgbBytes - idx;
|
|
549
|
+
const remainingBits = crcBits - i;
|
|
550
|
+
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
551
|
+
const step = max_step > 1 ? Math.floor(rng() * max_step) + 1 : 1;
|
|
552
|
+
idx += step;
|
|
553
|
+
const rgbByteIdx = idx - 1;
|
|
554
|
+
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
555
|
+
const channel = rgbByteIdx % 3;
|
|
556
|
+
const actualFlatIdx = pixelIdx * 4 + channel;
|
|
557
|
+
const bit = pixels[actualFlatIdx] & 1;
|
|
558
|
+
const bytePos = Math.floor(i / 8);
|
|
559
|
+
const bitPos = 7 - (i % 8);
|
|
560
|
+
crcBytes[bytePos] |= bit << bitPos;
|
|
561
|
+
}
|
|
562
|
+
const expectedCrc = new Uint32Array(crcBytes.reverse().buffer)[0];
|
|
563
|
+
// Өлшемді және сыйымдылық шегін тексеру (4 + 4 + payloadLen + 32)
|
|
564
|
+
const totalRequiredBits = (4 + 4 + payloadLen + 32) * 8;
|
|
565
|
+
if (totalRequiredBits > totalRgbBytes) {
|
|
397
566
|
throw new Error("Decryption failed under Nuralem Bult: Invalid key or corrupted image pixels");
|
|
398
567
|
}
|
|
399
568
|
const totalPayloadBits = payloadLen * 8;
|
|
400
569
|
const payloadBytes = new Uint8Array(payloadLen);
|
|
401
570
|
for (let i = 0; i < totalPayloadBits; i++) {
|
|
402
|
-
const remainingBytes =
|
|
571
|
+
const remainingBytes = totalRgbBytes - idx;
|
|
403
572
|
const remainingBits = totalPayloadBits - i;
|
|
404
573
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
405
574
|
const step = max_step > 1 ? Math.floor(rng() * max_step) + 1 : 1;
|
|
406
575
|
idx += step;
|
|
407
|
-
const
|
|
408
|
-
const
|
|
576
|
+
const rgbByteIdx = idx - 1;
|
|
577
|
+
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
578
|
+
const channel = rgbByteIdx % 3;
|
|
579
|
+
const actualFlatIdx = pixelIdx * 4 + channel;
|
|
580
|
+
const bit = pixels[actualFlatIdx] & 1;
|
|
409
581
|
const bytePos = Math.floor(i / 8);
|
|
410
582
|
const bitPos = 7 - (i % 8);
|
|
411
583
|
payloadBytes[bytePos] |= bit << bitPos;
|
|
412
584
|
}
|
|
585
|
+
// CRC32 тексеру
|
|
586
|
+
const actualCrc = crc32(payloadBytes);
|
|
587
|
+
if (actualCrc !== expectedCrc) {
|
|
588
|
+
throw new Error(`Decryption failed under Nuralem Bult: CRC32 checksum mismatch (Expected: 0x${expectedCrc.toString(16)}, Got: 0x${actualCrc.toString(16)}). Data is corrupted or color profile alterations occurred.`);
|
|
589
|
+
}
|
|
413
590
|
return payloadBytes;
|
|
414
591
|
}
|
|
415
592
|
mergeUint8Arrays(arrays) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuralem-bult-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Serverless Decentralized Document-based polymorphic NoSQL database with client-side caching and storage abstraction adapter. Developed under Nuralem Bult Ecosystem.",
|
|
5
5
|
"main": "dist/NuralemBult.js",
|
|
6
6
|
"types": "dist/NuralemBult.d.ts",
|