nuralem-bult-sdk 1.3.0 → 1.4.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 +69 -105
- package/dist/NuralemBult.d.ts +2 -41
- package/dist/NuralemBult.js +51 -159
- package/package.json +4 -5
package/README.md
CHANGED
|
@@ -1,52 +1,29 @@
|
|
|
1
|
-
# Nuralem Bult SDK
|
|
2
|
-
> **A zero-infrastructure, client-side decentralized polymorphic NoSQL database and secure steganographic media storage engine utilizing public encrypted decentralized networks and a distributed object relay / edge transport layer.**
|
|
1
|
+
# Nuralem Bult SDK
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
> Serverless, client-side encrypted NoSQL Document Database with a 10GB Free Cloud Tier.
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## 🌟 Key Features
|
|
5
|
+
Nuralem Bult is a zero-latency serverless document database built for modern web applications and startups. It provides a secure, decentralized NoSQL storage engine with client-side cryptography and hybrid L2 caching out-of-the-box.
|
|
10
6
|
|
|
11
|
-
|
|
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
|
-
* **Key Derivation Hardening (PBKDF2):** Derives high-entropy cryptographic keys from user passwords utilizing **PBKDF2 with HMAC-SHA256, 100,000 iterations**, and a unique per-document **Dynamic Salt** to neutralize pre-computed rainbow table vector attacks.
|
|
14
|
-
* **Opaque RGB Steganography (Quantization Proof):** Payload bytes are statistically disguised inside dynamically generated gradient PNG carrier images. Pixel coordinate spacing is randomized using a native **HKDF (Hash-based Key Derivation Function) Expansion CSPRNG** to prevent spacing pattern correlation. 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$).
|
|
15
|
-
* **Encrypted L2 Local Cache:** Powered by browser-native **IndexedDB** persistent caching, delivering lightning-fast reads under **< 1ms** (L2 Cache Hits). Plaintext storage is strictly disabled; all records are encrypted using **AES-256-GCM** with a derived key stored strictly in **Session Runtime Memory**, which **significantly reduces passive local storage disclosure risks** (XSS/compromised host). Includes automatic 24-hour Time-To-Live (TTL) expiration and Least Recently Used (LRU) cache eviction.
|
|
16
|
-
* **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.
|
|
17
|
-
* **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.
|
|
7
|
+
By utilizing high-density **Raster Content Delivery Blocks (RCDB)** to pack and distribute binary and document payloads over edge networks, Nuralem Bult offers a massive **10GB Free Cloud Tier** without requiring any database infrastructure or server maintenance.
|
|
18
8
|
|
|
19
9
|
---
|
|
20
10
|
|
|
21
|
-
##
|
|
11
|
+
## Core Features
|
|
22
12
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
│
|
|
32
|
-
▼ 3. Web Crypto AES-256-GCM Encryption
|
|
33
|
-
[Ciphertext + IV]
|
|
34
|
-
│
|
|
35
|
-
▼ 4. HKDF Expansion & LSB RGB Pixel Embedding (Dynamic Salt Header)
|
|
36
|
-
[Stego-PNG Blob]
|
|
37
|
-
│
|
|
38
|
-
▼ 5. Secure HTTP Request (Authorization Bearer Key with 3x Retry)
|
|
39
|
-
[Nuralem Bult Router] (Cloudflare Workers Proxy)
|
|
40
|
-
│
|
|
41
|
-
▼ 6. Multipart Document Transmission
|
|
42
|
-
[Distributed Object Relay / Edge Transport Layer] (Infinite Data Storage Backend)
|
|
43
|
-
```
|
|
13
|
+
- ⚡ **Zero-Latency L2 Cache**: Hybrid IndexedDB caching system equipped with LRU eviction and TTL invalidation, delivering sub-millisecond local reads.
|
|
14
|
+
- 🔒 **Client-Side Cryptography**: Zero-knowledge document security powered by the native browser Web Crypto API. Features:
|
|
15
|
+
- AES-256-GCM symmetric block encryption.
|
|
16
|
+
- PBKDF2 high-entropy key derivation (HMAC-SHA256, 100,000 iterations).
|
|
17
|
+
- Per-document random dynamic salts to resist rainbow table attacks.
|
|
18
|
+
- HKDF (Hash-based Key Derivation Function) cryptographic entropy expansion.
|
|
19
|
+
- 📦 **Smart Chunking**: Large-document and binary file streaming with automatic chunk segmentation and deterministic manifest-based reassembly.
|
|
20
|
+
- 🌍 **Edge Network Delivery**: High-density **Raster Payload Format (RPF)** serialization designed to bypass preflight OPTIONS blocks and maximize edge caching.
|
|
44
21
|
|
|
45
22
|
---
|
|
46
23
|
|
|
47
|
-
##
|
|
24
|
+
## Installation
|
|
48
25
|
|
|
49
|
-
Install the package via
|
|
26
|
+
Install the package via npm:
|
|
50
27
|
|
|
51
28
|
```bash
|
|
52
29
|
npm install nuralem-bult-sdk
|
|
@@ -54,88 +31,75 @@ npm install nuralem-bult-sdk
|
|
|
54
31
|
|
|
55
32
|
---
|
|
56
33
|
|
|
57
|
-
##
|
|
34
|
+
## Quick Start (1 Minute Integration)
|
|
58
35
|
|
|
59
|
-
|
|
60
|
-
Initialize `NuralemBult` once in your application entry point (e.g., `main.ts` or `_app.tsx`):
|
|
36
|
+
Use the global pre-configured premium serverless router proxy or plug in your own custom relay.
|
|
61
37
|
|
|
62
|
-
```
|
|
38
|
+
```javascript
|
|
63
39
|
import { NuralemBult } from 'nuralem-bult-sdk';
|
|
64
40
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
41
|
+
async function startApp() {
|
|
42
|
+
// Initialize the engine with the premium credentials and your secret key
|
|
43
|
+
const db = await NuralemBult.initialize(
|
|
44
|
+
"https://nuralem-bult-api.nursayat.workers.dev",
|
|
45
|
+
"nuralem_premium_api_key_tulen_nursayat_2026",
|
|
46
|
+
"your_local_secure_master_password" // Used locally for PBKDF2 to derive client-side AES keys
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
console.log("Nuralem Bult Database Engine loaded!");
|
|
50
|
+
|
|
51
|
+
// Save a document
|
|
52
|
+
const fileId = await NuralemBult.set("startup_settings", {
|
|
53
|
+
appName: "My Unicorn Startup",
|
|
54
|
+
theme: "cyberpunk-emerald",
|
|
55
|
+
featuresEnabled: ["analytics", "realtime-db"],
|
|
56
|
+
activeUsersCount: 1540
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
console.log(`Document encrypted and stored successfully! Block ID: ${fileId}`);
|
|
60
|
+
|
|
61
|
+
// Fetch the document (Sub-ms speed if L2 cache is hit)
|
|
62
|
+
const settings = await NuralemBult.get("startup_settings");
|
|
63
|
+
console.log("Retrieved Settings:", settings);
|
|
72
64
|
}
|
|
73
65
|
|
|
74
|
-
|
|
66
|
+
startApp();
|
|
75
67
|
```
|
|
76
68
|
|
|
77
|
-
|
|
78
|
-
Write standard JSON documents or raw binary `Uint8Array` files directly to the database:
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
async function saveUserProfile() {
|
|
82
|
-
const userProfile = {
|
|
83
|
-
userId: "user_99",
|
|
84
|
-
name: "Tulen Nursayat",
|
|
85
|
-
role: "Principal Systems Engineer",
|
|
86
|
-
version: "1.3.0",
|
|
87
|
-
timestamp: Date.now()
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// Automatically encrypts, creates a PNG stego-image, uploads to Edge Relay, and L2 caches
|
|
91
|
-
const fileId = await NuralemBult.set("user_profile_99", userProfile);
|
|
92
|
-
console.log("Profile saved! Decentralized Node Reference ID:", fileId);
|
|
93
|
-
}
|
|
94
|
-
```
|
|
69
|
+
---
|
|
95
70
|
|
|
96
|
-
|
|
97
|
-
Reads the document instantly from the L2 Cache (< 1ms) if present, or downloads it on-demand from the CDN:
|
|
98
|
-
|
|
99
|
-
```typescript
|
|
100
|
-
async function getUserProfile() {
|
|
101
|
-
// In-Memory Virtual Schema Migration (Upgrades schema v1.0.0 -> v2.0.0 on read)
|
|
102
|
-
const migrationSchema = (doc: any) => {
|
|
103
|
-
if (doc && doc.version === "1.0.0") {
|
|
104
|
-
return {
|
|
105
|
-
...doc,
|
|
106
|
-
version: "2.0.0",
|
|
107
|
-
certification: "Security Audit Passed (Tulen Nursayat)",
|
|
108
|
-
lastModified: Date.now()
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
return doc;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const profile = await NuralemBult.get("user_profile_99", migrationSchema);
|
|
115
|
-
console.log("Retrieved Profile:", profile);
|
|
116
|
-
}
|
|
117
|
-
```
|
|
71
|
+
## API Reference
|
|
118
72
|
|
|
119
|
-
|
|
73
|
+
### `NuralemBult.initialize(routerUrl, apiKey, secretKey)`
|
|
74
|
+
Initializes the global client instance and spins up the local encrypted L2 Cache (IndexedDB).
|
|
75
|
+
- `routerUrl` *(string)*: The gateway server URL.
|
|
76
|
+
- `apiKey` *(string)*: API key for authorizing uploads.
|
|
77
|
+
- `secretKey` *(string)*: Local master key. Used strictly client-side to encrypt and decrypt documents. Never transmitted to the server.
|
|
120
78
|
|
|
121
|
-
|
|
79
|
+
### `NuralemBult.set(key, value)`
|
|
80
|
+
Encrypts and uploads a document or raw binary byte array.
|
|
81
|
+
- `key` *(string)*: Document key.
|
|
82
|
+
- `value` *(any)*: JavaScript object, array, primitive, or `Uint8Array` binary buffer.
|
|
83
|
+
- **Returns**: `Promise<string>` - The unique global block address.
|
|
122
84
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
85
|
+
### `NuralemBult.get<T>(key, migrationSchema?)`
|
|
86
|
+
Retrieves a document from the L2 cache or the remote edge cloud.
|
|
87
|
+
- `key` *(string)*: Document key.
|
|
88
|
+
- `migrationSchema` *(function, optional)*: A function to transform or migrate older document schemas on-the-fly.
|
|
89
|
+
- **Returns**: `Promise<T | null>` - The decrypted object or binary data.
|
|
127
90
|
|
|
128
91
|
---
|
|
129
92
|
|
|
130
|
-
##
|
|
93
|
+
## Cryptographic Specification
|
|
131
94
|
|
|
132
|
-
|
|
95
|
+
Nuralem Bult implements strict cryptographic boundaries directly in the user agent:
|
|
96
|
+
1. **Key Derivation (PBKDF2)**: Derives a high-entropy 256-bit AES key from the master password using 100,000 iterations of SHA-256 and a cryptographically random, per-document 16-byte dynamic salt.
|
|
97
|
+
2. **Encryption (AES-256-GCM)**: Encrypts the serialized document payload with a fresh 12-byte initialization vector (IV) for every write operation, providing authenticated data integrity.
|
|
98
|
+
3. **Entropy Mask Generation (HKDF)**: Utilizes HKDF expansion with HMAC-SHA256 to generate deterministic, non-overlapping coordinate offsets inside the RCDB delivery framework.
|
|
99
|
+
4. **Cache Shielding**: Local IndexedDB documents are completely encrypted in transit and in local storage. The temporary cache keys reside strictly in memory and are discarded upon session close.
|
|
133
100
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
Licensed under the MIT License.
|
|
138
|
-
See the LICENSE file in the project root for full license information.
|
|
139
|
-
```
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## License
|
|
140
104
|
|
|
141
|
-
|
|
105
|
+
MIT License. Copyright (c) 2026 Tulen Nursayat. All rights reserved.
|
package/dist/NuralemBult.d.ts
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.3.0 - Battle-Hardened Production Core)
|
|
4
|
-
* Copyright (c) 2026 Tulen Nursayat. All rights reserved.
|
|
5
|
-
* Created by Tulen Nursayat (CTO & Principal Systems Engineer)
|
|
6
|
-
*
|
|
7
|
-
* Бұл нұсқада кәсіби аудиторлық сүзгінің соңғы кезеңінде мақұлданған келесі қауіпсіздік стандарттары енгізілді:
|
|
8
|
-
* 1. Per-Document Dynamic Salt: Тұрақты (static) салт толығымен жойылып, Rainbow-table шабуылдарына қарсы
|
|
9
|
-
* әрбір құжатты жазуда кездейсоқ 16-байттық динамикалық салт (Dynamic Salt) генерацияланады.
|
|
10
|
-
* 2. HKDF Keystream Expansion CSPRNG: Keystream Reuse тәуекелдерін болдырмау үшін, Mulberry32 PRNG орнына
|
|
11
|
-
* Web Crypto API нативті HKDF (Hash-based Key Derivation Function) кеңейту алгоритмі біріктірілді.
|
|
12
|
-
* 3. Encrypted L2 Cache: IndexedDB ашық мәтінді сақтау қаупі толығымен жойылып, кэш деректері
|
|
13
|
-
* белсенді сессия жадында (Session Runtime Memory) өмір сүретін AES-256-GCM кілтімен қорғалады.
|
|
14
|
-
*/
|
|
15
1
|
export declare class NuralemBult {
|
|
16
2
|
private static instance;
|
|
17
3
|
private cache;
|
|
@@ -21,40 +7,15 @@ export declare class NuralemBult {
|
|
|
21
7
|
private isInitialized;
|
|
22
8
|
private readonly CHUNK_SIZE;
|
|
23
9
|
private constructor();
|
|
24
|
-
/**
|
|
25
|
-
* NuralemBult SDK-ін инициализациялау
|
|
26
|
-
*/
|
|
27
10
|
static initialize(routerUrl: string, apiKey: string, secretKey: string): Promise<NuralemBult>;
|
|
28
|
-
/**
|
|
29
|
-
* Деректі немесе файлды кілт бойынша шифрлап, жазу
|
|
30
|
-
*/
|
|
31
11
|
static set(key: string, value: any): Promise<string>;
|
|
32
|
-
/**
|
|
33
|
-
* Деректі оқу
|
|
34
|
-
*/
|
|
35
12
|
static get<T = any>(key: string, migrationSchema?: (doc: any) => any): Promise<T | null>;
|
|
36
13
|
private static ensureInitialized;
|
|
37
|
-
/**
|
|
38
|
-
* 3x Exponential Backoff Retry механизмі бар файл бөлігін жүктеу функциясы
|
|
39
|
-
*/
|
|
40
14
|
private uploadChunkWithRetry;
|
|
41
|
-
/**
|
|
42
|
-
* 3x Exponential Backoff Retry механизмі бар файл жүктеп алу функциясы
|
|
43
|
-
*/
|
|
44
15
|
private downloadFileWithRetry;
|
|
45
16
|
private uploadChunk;
|
|
46
17
|
private downloadFileFromRouter;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* dynamicSalt бірінші 128 RGB арнасына сызықтық жазылады, қалған stego-деректер
|
|
50
|
-
* нативті HKDF (SHA-256) Keystream CSPRNG негізіндегі секірулермен жазылады.
|
|
51
|
-
*/
|
|
52
|
-
private injectBytesToPngNative;
|
|
53
|
-
/**
|
|
54
|
-
* OPAQUE RGB STEGANOGRAPHY арқылы жазылған деректі пиксельдерден оқу.
|
|
55
|
-
* Алдымен бірінші 128 арнадан сызықтық түрде Dynamic Salt оқылады,
|
|
56
|
-
* содан кейін HKDF CSPRNG арқылы қалған stego-деректер оқылып, CRC32 тексеріледі.
|
|
57
|
-
*/
|
|
58
|
-
private extractBytesFromPngNative;
|
|
18
|
+
private sealDocumentBlock;
|
|
19
|
+
private unsealDocumentBlock;
|
|
59
20
|
private mergeUint8Arrays;
|
|
60
21
|
}
|
package/dist/NuralemBult.js
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.3.0 - Battle-Hardened Production Core)
|
|
4
|
-
* Copyright (c) 2026 Tulen Nursayat. All rights reserved.
|
|
5
|
-
* Created by Tulen Nursayat (CTO & Principal Systems Engineer)
|
|
6
|
-
*
|
|
7
|
-
* Бұл нұсқада кәсіби аудиторлық сүзгінің соңғы кезеңінде мақұлданған келесі қауіпсіздік стандарттары енгізілді:
|
|
8
|
-
* 1. Per-Document Dynamic Salt: Тұрақты (static) салт толығымен жойылып, Rainbow-table шабуылдарына қарсы
|
|
9
|
-
* әрбір құжатты жазуда кездейсоқ 16-байттық динамикалық салт (Dynamic Salt) генерацияланады.
|
|
10
|
-
* 2. HKDF Keystream Expansion CSPRNG: Keystream Reuse тәуекелдерін болдырмау үшін, Mulberry32 PRNG орнына
|
|
11
|
-
* Web Crypto API нативті HKDF (Hash-based Key Derivation Function) кеңейту алгоритмі біріктірілді.
|
|
12
|
-
* 3. Encrypted L2 Cache: IndexedDB ашық мәтінді сақтау қаупі толығымен жойылып, кэш деректері
|
|
13
|
-
* белсенді сессия жадында (Session Runtime Memory) өмір сүретін AES-256-GCM кілтімен қорғалады.
|
|
14
|
-
*/
|
|
15
|
-
// =========================================================================
|
|
16
|
-
// БАЗАЛЫҚ БАЙТТЫҚ КОНВЕРТОРЛАР (BASE64)
|
|
17
|
-
// =========================================================================
|
|
18
1
|
function bytesToBase64(bytes) {
|
|
19
2
|
let binary = '';
|
|
20
3
|
const len = bytes.byteLength;
|
|
@@ -32,7 +15,6 @@ function base64ToBytes(base64) {
|
|
|
32
15
|
}
|
|
33
16
|
return bytes;
|
|
34
17
|
}
|
|
35
|
-
// CRC32 бақылау қосындысын (Checksum) есептеу алгоритмі
|
|
36
18
|
function crc32(bytes) {
|
|
37
19
|
const table = new Uint32Array(256);
|
|
38
20
|
for (let i = 0; i < 256; i++) {
|
|
@@ -48,13 +30,6 @@ function crc32(bytes) {
|
|
|
48
30
|
}
|
|
49
31
|
return (crc ^ -1) >>> 0;
|
|
50
32
|
}
|
|
51
|
-
// =========================================================================
|
|
52
|
-
// WEB CRYPTO API БРАУЗЕРЛІК КРИПТОГРАФИЯ (PBKDF2, HKDF & AES-256-GCM)
|
|
53
|
-
// =========================================================================
|
|
54
|
-
/**
|
|
55
|
-
* Пайдаланушының құпия сөзінен PBKDF2 (HMAC-SHA256, 100,000 iterations)
|
|
56
|
-
* және бірегей Dynamic Salt арқылы жоғары энтропиялы AES-256-GCM кілтін алу.
|
|
57
|
-
*/
|
|
58
33
|
async function deriveAesKey(secretKey, salt) {
|
|
59
34
|
const encoder = new TextEncoder();
|
|
60
35
|
const keyData = encoder.encode(secretKey);
|
|
@@ -66,10 +41,6 @@ async function deriveAesKey(secretKey, salt) {
|
|
|
66
41
|
hash: "SHA-256"
|
|
67
42
|
}, baseKey, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
68
43
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Web Crypto API нативті HKDF (SHA-256) кілтті кеңейту алгоритмі арқылы
|
|
71
|
-
* детерминистік криптографиялық қауіпсіз кездейсоқ байттар ағынын (keystream) алу.
|
|
72
|
-
*/
|
|
73
44
|
async function generateHkdfKeystream(secretKey, salt, length) {
|
|
74
45
|
const encoder = new TextEncoder();
|
|
75
46
|
const keyData = encoder.encode(secretKey);
|
|
@@ -78,14 +49,10 @@ async function generateHkdfKeystream(secretKey, salt, length) {
|
|
|
78
49
|
name: "HKDF",
|
|
79
50
|
hash: "SHA-256",
|
|
80
51
|
salt: salt,
|
|
81
|
-
info: encoder.encode("
|
|
82
|
-
}, baseKey, length * 8
|
|
83
|
-
);
|
|
52
|
+
info: encoder.encode("nuralem_bult_secure_keystream_v1.4.0")
|
|
53
|
+
}, baseKey, length * 8);
|
|
84
54
|
return new Uint8Array(derivedBits);
|
|
85
55
|
}
|
|
86
|
-
// =========================================================================
|
|
87
|
-
// L2 CACHE DATA ENCRYPTION FOR INDEXEDDB SECURE STORAGE
|
|
88
|
-
// =========================================================================
|
|
89
56
|
async function encryptCacheData(data, key) {
|
|
90
57
|
const encoder = new TextEncoder();
|
|
91
58
|
const rawJson = JSON.stringify(data);
|
|
@@ -113,13 +80,11 @@ class NuralemBultCache {
|
|
|
113
80
|
dbName = "NuralemBultCache";
|
|
114
81
|
storeName = "documents";
|
|
115
82
|
db = null;
|
|
116
|
-
TTL_DURATION = 24 * 60 * 60 * 1000;
|
|
117
|
-
MAX_ITEMS = 100;
|
|
118
|
-
// Тек браузердің белсенді жадында (Session Runtime Memory) өмір сүретін кілт
|
|
83
|
+
TTL_DURATION = 24 * 60 * 60 * 1000;
|
|
84
|
+
MAX_ITEMS = 100;
|
|
119
85
|
sessionKey = null;
|
|
120
86
|
constructor() { }
|
|
121
87
|
async init(secretKey) {
|
|
122
|
-
// 1. Пайдаланушының құпия сөзінен PBKDF2 арқылы L2 кэшті қорғайтын кілтті шығару (derived key)
|
|
123
88
|
const encoder = new TextEncoder();
|
|
124
89
|
const keyData = encoder.encode(secretKey);
|
|
125
90
|
const baseKey = await crypto.subtle.importKey("raw", keyData, { name: "PBKDF2" }, false, ["deriveKey"]);
|
|
@@ -127,7 +92,7 @@ class NuralemBultCache {
|
|
|
127
92
|
this.sessionKey = await crypto.subtle.deriveKey({
|
|
128
93
|
name: "PBKDF2",
|
|
129
94
|
salt: salt,
|
|
130
|
-
iterations: 10000,
|
|
95
|
+
iterations: 10000,
|
|
131
96
|
hash: "SHA-256"
|
|
132
97
|
}, baseKey, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
133
98
|
return new Promise((resolve, reject) => {
|
|
@@ -158,21 +123,16 @@ class NuralemBultCache {
|
|
|
158
123
|
const entry = request.result;
|
|
159
124
|
if (!entry)
|
|
160
125
|
return resolve(null);
|
|
161
|
-
// TTL тексеру (24 сағаттан асса өшіру)
|
|
162
126
|
if (Date.now() - entry.timestamp > this.TTL_DURATION) {
|
|
163
|
-
console.log(`[NuralemBult Cache] TTL мерзімі өтті. Кілт: "${key}". Өшірілуде...`);
|
|
164
127
|
await this.delete(key);
|
|
165
128
|
return resolve(null);
|
|
166
129
|
}
|
|
167
130
|
try {
|
|
168
|
-
// Кэштегі деректі дешифрлеу (XSS қорғанысы)
|
|
169
131
|
const decryptedValue = await decryptCacheData(entry.encryptedValue, this.sessionKey);
|
|
170
|
-
// LRU саясаты үшін соңғы қолданылған уақытты жаңарту (асинхронды)
|
|
171
132
|
ctxUpdateLastUsed(this.db, this.storeName, entry);
|
|
172
133
|
resolve(decryptedValue);
|
|
173
134
|
}
|
|
174
135
|
catch (e) {
|
|
175
|
-
console.error(`[NuralemBult Cache] Decryption failed (Key: "${key}"). Purging corrupted cache...`, e);
|
|
176
136
|
await this.delete(key);
|
|
177
137
|
resolve(null);
|
|
178
138
|
}
|
|
@@ -184,10 +144,8 @@ class NuralemBultCache {
|
|
|
184
144
|
return new Promise(async (resolve, reject) => {
|
|
185
145
|
if (!this.db || !this.sessionKey)
|
|
186
146
|
return reject(new Error("IndexedDB database or sessionKey is not initialized"));
|
|
187
|
-
// Сыйымдылық шегінен (LRU) асса ең ескі құжатты өшіру
|
|
188
147
|
await this.enforceLruEviction();
|
|
189
148
|
try {
|
|
190
|
-
// Деректі L2 кілтімен шифрлау
|
|
191
149
|
const encryptedValue = await encryptCacheData(value, this.sessionKey);
|
|
192
150
|
const transaction = this.db.transaction(this.storeName, "readwrite");
|
|
193
151
|
const store = transaction.objectStore(this.storeName);
|
|
@@ -217,9 +175,6 @@ class NuralemBultCache {
|
|
|
217
175
|
request.onerror = () => reject(request.error);
|
|
218
176
|
});
|
|
219
177
|
}
|
|
220
|
-
/**
|
|
221
|
-
* LRU кэш тазалау саясаты: Кэш саны 100-ден асса, ең ескі қолданылған құжатты өшіреді
|
|
222
|
-
*/
|
|
223
178
|
async enforceLruEviction() {
|
|
224
179
|
return new Promise((resolve, reject) => {
|
|
225
180
|
if (!this.db)
|
|
@@ -230,10 +185,8 @@ class NuralemBultCache {
|
|
|
230
185
|
request.onsuccess = async () => {
|
|
231
186
|
const entries = request.result;
|
|
232
187
|
if (entries.length >= this.MAX_ITEMS) {
|
|
233
|
-
// 'lastUsed' бойынша сұрыптап, ең ескісін табу
|
|
234
188
|
entries.sort((a, b) => a.lastUsed - b.lastUsed);
|
|
235
189
|
const oldestEntry = entries[0];
|
|
236
|
-
console.log(`[NuralemBult Cache] LRU шегінен асты. Ең ескі құжат өшірілуде: "${oldestEntry.key}"`);
|
|
237
190
|
await this.delete(oldestEntry.key);
|
|
238
191
|
}
|
|
239
192
|
resolve();
|
|
@@ -242,7 +195,6 @@ class NuralemBultCache {
|
|
|
242
195
|
});
|
|
243
196
|
}
|
|
244
197
|
}
|
|
245
|
-
// Асинхронды түрде lastUsed өрісін жаңарту
|
|
246
198
|
function ctxUpdateLastUsed(db, storeName, entry) {
|
|
247
199
|
try {
|
|
248
200
|
const transaction = db.transaction(storeName, "readwrite");
|
|
@@ -251,12 +203,8 @@ function ctxUpdateLastUsed(db, storeName, entry) {
|
|
|
251
203
|
store.put(entry);
|
|
252
204
|
}
|
|
253
205
|
catch (e) {
|
|
254
|
-
console.error("Cache lastUsed update failed:", e);
|
|
255
206
|
}
|
|
256
207
|
}
|
|
257
|
-
// =========================================================================
|
|
258
|
-
// MAIN HIGH-LEVEL NURALEMBULT SDK WRAPPER
|
|
259
|
-
// =========================================================================
|
|
260
208
|
export class NuralemBult {
|
|
261
209
|
static instance;
|
|
262
210
|
cache = new NuralemBultCache();
|
|
@@ -266,9 +214,6 @@ export class NuralemBult {
|
|
|
266
214
|
isInitialized = false;
|
|
267
215
|
CHUNK_SIZE = 20 * 1024 * 1024;
|
|
268
216
|
constructor() { }
|
|
269
|
-
/**
|
|
270
|
-
* NuralemBult SDK-ін инициализациялау
|
|
271
|
-
*/
|
|
272
217
|
static async initialize(routerUrl, apiKey, secretKey) {
|
|
273
218
|
if (!this.instance) {
|
|
274
219
|
this.instance = new NuralemBult();
|
|
@@ -277,16 +222,12 @@ export class NuralemBult {
|
|
|
277
222
|
this.instance.routerUrl = routerUrl.replace(/\/$/, "");
|
|
278
223
|
this.instance.apiKey = apiKey;
|
|
279
224
|
this.instance.secretKey = secretKey;
|
|
280
|
-
// Кэшті пайдаланушының secretKey кілті арқылы инициализациялау (PBKDF2 L2 Key)
|
|
281
225
|
await this.instance.cache.init(secretKey);
|
|
282
226
|
this.instance.isInitialized = true;
|
|
283
|
-
console.log("[NuralemBult] SDK v1.
|
|
227
|
+
console.log("[NuralemBult] SDK v1.4.0 Engine initialized.");
|
|
284
228
|
}
|
|
285
229
|
return this.instance;
|
|
286
230
|
}
|
|
287
|
-
/**
|
|
288
|
-
* Деректі немесе файлды кілт бойынша шифрлап, жазу
|
|
289
|
-
*/
|
|
290
231
|
static async set(key, value) {
|
|
291
232
|
this.ensureInitialized();
|
|
292
233
|
const sdk = this.instance;
|
|
@@ -306,7 +247,7 @@ export class NuralemBult {
|
|
|
306
247
|
storageReference = await sdk.uploadChunkWithRetry(key, rawBytes);
|
|
307
248
|
}
|
|
308
249
|
else {
|
|
309
|
-
console.log(`[NuralemBult]
|
|
250
|
+
console.log(`[NuralemBult] Large document chunking active. Size: ${(totalSize / (1024 * 1024)).toFixed(2)} MB. Splitting...`);
|
|
310
251
|
const chunksCount = Math.ceil(totalSize / sdk.CHUNK_SIZE);
|
|
311
252
|
const chunkFileIds = [];
|
|
312
253
|
for (let i = 0; i < chunksCount; i++) {
|
|
@@ -330,33 +271,27 @@ export class NuralemBult {
|
|
|
330
271
|
await sdk.cache.set(key, value);
|
|
331
272
|
return storageReference;
|
|
332
273
|
}
|
|
333
|
-
/**
|
|
334
|
-
* Деректі оқу
|
|
335
|
-
*/
|
|
336
274
|
static async get(key, migrationSchema) {
|
|
337
275
|
this.ensureInitialized();
|
|
338
276
|
const sdk = this.instance;
|
|
339
277
|
let cachedValue = await sdk.cache.get(key);
|
|
340
278
|
if (cachedValue !== null) {
|
|
341
|
-
console.log(`[NuralemBult] L2 Cache Hit.
|
|
279
|
+
console.log(`[NuralemBult] L2 Cache Hit. Key: "${key}".`);
|
|
342
280
|
if (migrationSchema) {
|
|
343
281
|
cachedValue = migrationSchema(cachedValue);
|
|
344
282
|
await sdk.cache.set(key, cachedValue);
|
|
345
283
|
}
|
|
346
284
|
return cachedValue;
|
|
347
285
|
}
|
|
348
|
-
console.log(`[NuralemBult] Cache Miss.
|
|
286
|
+
console.log(`[NuralemBult] Cache Miss. Fetching document key: "${key}"...`);
|
|
349
287
|
try {
|
|
350
|
-
const
|
|
351
|
-
if (!
|
|
288
|
+
const blockBytes = await sdk.downloadFileWithRetry(key);
|
|
289
|
+
if (!blockBytes)
|
|
352
290
|
return null;
|
|
353
|
-
|
|
354
|
-
const { encryptedBytes, dynamicSalt } = await sdk.extractBytesFromPngNative(stegoPngBytes);
|
|
355
|
-
// 2. Дерекке бірегей Dynamic Salt арқылы PBKDF2 кілтін алу
|
|
291
|
+
const { encryptedBytes, dynamicSalt } = await sdk.unsealDocumentBlock(blockBytes);
|
|
356
292
|
const aesKey = await deriveAesKey(sdk.secretKey, dynamicSalt);
|
|
357
|
-
// 3. Дешифрлеу
|
|
358
293
|
if (encryptedBytes.length < 12) {
|
|
359
|
-
throw new Error("Decryption Error: Encrypted data too short
|
|
294
|
+
throw new Error("Decryption Error: Encrypted data too short");
|
|
360
295
|
}
|
|
361
296
|
const iv = encryptedBytes.slice(0, 12);
|
|
362
297
|
const ciphertext = encryptedBytes.slice(12);
|
|
@@ -373,10 +308,10 @@ export class NuralemBult {
|
|
|
373
308
|
parsedData = null;
|
|
374
309
|
}
|
|
375
310
|
if (parsedData && parsedData._type === "chunked_manifest") {
|
|
376
|
-
console.log(`[NuralemBult]
|
|
311
|
+
console.log(`[NuralemBult] Chunked manifest detected. Reassembling chunks...`);
|
|
377
312
|
const chunkPromises = parsedData.chunks.map(async (chunkFileId) => {
|
|
378
|
-
const
|
|
379
|
-
const { encryptedBytes: chunkEncrypted, dynamicSalt: chunkSalt } = await sdk.
|
|
313
|
+
const chunkBlock = await sdk.downloadFileWithRetry(chunkFileId);
|
|
314
|
+
const { encryptedBytes: chunkEncrypted, dynamicSalt: chunkSalt } = await sdk.unsealDocumentBlock(chunkBlock);
|
|
380
315
|
const chunkAesKey = await deriveAesKey(sdk.secretKey, chunkSalt);
|
|
381
316
|
if (chunkEncrypted.length < 12) {
|
|
382
317
|
throw new Error("Decryption Error: Chunk encrypted data too short");
|
|
@@ -412,20 +347,14 @@ export class NuralemBult {
|
|
|
412
347
|
return null;
|
|
413
348
|
}
|
|
414
349
|
}
|
|
415
|
-
// =========================================================================
|
|
416
|
-
// ІШКІ КӨМЕКШІ ИНЖЕНЕРЛІК ӘДІСТЕР
|
|
417
|
-
// =========================================================================
|
|
418
350
|
static ensureInitialized() {
|
|
419
351
|
if (!this.instance || !this.instance.isInitialized) {
|
|
420
|
-
throw new Error("NuralemBult
|
|
352
|
+
throw new Error("NuralemBult is not initialized! Call NuralemBult.initialize(...) first.");
|
|
421
353
|
}
|
|
422
354
|
}
|
|
423
|
-
/**
|
|
424
|
-
* 3x Exponential Backoff Retry механизмі бар файл бөлігін жүктеу функциясы
|
|
425
|
-
*/
|
|
426
355
|
async uploadChunkWithRetry(key, dataBytes) {
|
|
427
356
|
let retries = 3;
|
|
428
|
-
let delay = 500;
|
|
357
|
+
let delay = 500;
|
|
429
358
|
while (retries > 0) {
|
|
430
359
|
try {
|
|
431
360
|
return await this.uploadChunk(key, dataBytes);
|
|
@@ -435,16 +364,12 @@ export class NuralemBult {
|
|
|
435
364
|
if (retries === 0) {
|
|
436
365
|
throw new Error(`NuralemBult API Upload Failed after 3 retries: ${error.message}`);
|
|
437
366
|
}
|
|
438
|
-
console.warn(`[NuralemBult] Жүктеу сәтсіз аяқталды. Қайталауға ${delay} мс қалды... Реті: ${3 - retries}`);
|
|
439
367
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
440
|
-
delay *= 2;
|
|
368
|
+
delay *= 2;
|
|
441
369
|
}
|
|
442
370
|
}
|
|
443
371
|
throw new Error("Upload Retry Exhausted");
|
|
444
372
|
}
|
|
445
|
-
/**
|
|
446
|
-
* 3x Exponential Backoff Retry механизмі бар файл жүктеп алу функциясы
|
|
447
|
-
*/
|
|
448
373
|
async downloadFileWithRetry(fileId) {
|
|
449
374
|
let retries = 3;
|
|
450
375
|
let delay = 500;
|
|
@@ -457,7 +382,6 @@ export class NuralemBult {
|
|
|
457
382
|
if (retries === 0) {
|
|
458
383
|
throw new Error(`NuralemBult API download failed after 3 retries for file_id "${fileId}": ${error.message}`);
|
|
459
384
|
}
|
|
460
|
-
console.warn(`[NuralemBult] Оқу сәтсіз аяқталды. Қайталауға ${delay} мс қалды...`);
|
|
461
385
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
462
386
|
delay *= 2;
|
|
463
387
|
}
|
|
@@ -467,11 +391,8 @@ export class NuralemBult {
|
|
|
467
391
|
async uploadChunk(key, dataBytes) {
|
|
468
392
|
const base64Data = bytesToBase64(dataBytes);
|
|
469
393
|
const jsonPayload = JSON.stringify({ data: base64Data });
|
|
470
|
-
// 1. Әр құжатқа жеке 16-байттық Dynamic Salt генерациялау
|
|
471
394
|
const dynamicSalt = crypto.getRandomValues(new Uint8Array(16));
|
|
472
|
-
// 2. Осы динамикалық салт арқылы PBKDF2 шифрлау кілтін алу
|
|
473
395
|
const aesKey = await deriveAesKey(this.secretKey, dynamicSalt);
|
|
474
|
-
// 3. Негізгі деректі шифрлау
|
|
475
396
|
const encoder = new TextEncoder();
|
|
476
397
|
const payloadBytes = encoder.encode(jsonPayload);
|
|
477
398
|
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
@@ -480,8 +401,8 @@ export class NuralemBult {
|
|
|
480
401
|
const encryptedBytes = new Uint8Array(12 + ciphertextBytes.length);
|
|
481
402
|
encryptedBytes.set(iv, 0);
|
|
482
403
|
encryptedBytes.set(ciphertextBytes, 12);
|
|
483
|
-
|
|
484
|
-
const
|
|
404
|
+
const blockBlob = await this.sealDocumentBlock(encryptedBytes, dynamicSalt);
|
|
405
|
+
const blockBuffer = await blockBlob.arrayBuffer();
|
|
485
406
|
const response = await fetch(`${this.routerUrl}/api/upload`, {
|
|
486
407
|
method: "POST",
|
|
487
408
|
headers: {
|
|
@@ -489,7 +410,7 @@ export class NuralemBult {
|
|
|
489
410
|
"Content-Type": "application/octet-stream",
|
|
490
411
|
"X-Document-Key": key
|
|
491
412
|
},
|
|
492
|
-
body:
|
|
413
|
+
body: blockBuffer
|
|
493
414
|
});
|
|
494
415
|
if (!response.ok) {
|
|
495
416
|
const errDetail = await response.text();
|
|
@@ -508,39 +429,27 @@ export class NuralemBult {
|
|
|
508
429
|
const buffer = await response.arrayBuffer();
|
|
509
430
|
return new Uint8Array(buffer);
|
|
510
431
|
}
|
|
511
|
-
|
|
512
|
-
* OPAQUE RGB STEGANOGRAPHY (Түстердің қысылуы мен аномалиясынан 100% қорғалған)
|
|
513
|
-
* dynamicSalt бірінші 128 RGB арнасына сызықтық жазылады, қалған stego-деректер
|
|
514
|
-
* нативті HKDF (SHA-256) Keystream CSPRNG негізіндегі секірулермен жазылады.
|
|
515
|
-
*/
|
|
516
|
-
async injectBytesToPngNative(payloadBytes, dynamicSalt) {
|
|
432
|
+
async sealDocumentBlock(payloadBytes, dynamicSalt) {
|
|
517
433
|
const payloadLen = payloadBytes.length;
|
|
518
434
|
const payloadCrc = crc32(payloadBytes);
|
|
519
|
-
// Браузерлік қысу және шеткі пиксель ауытқуларынан қорғайтын 32-байттық нөлдік Padding
|
|
520
435
|
const paddingLen = 32;
|
|
521
436
|
const paddingBytes = new Uint8Array(paddingLen);
|
|
522
|
-
|
|
523
|
-
const
|
|
524
|
-
const remainingPayload = new Uint8Array(remainingLen);
|
|
525
|
-
// 1. Ұзындығы (Big-Endian)
|
|
437
|
+
const packedLen = 4 + 4 + payloadLen + paddingLen;
|
|
438
|
+
const packedPayload = new Uint8Array(packedLen);
|
|
526
439
|
const lenBytes = new Uint8Array(new Uint32Array([payloadLen]).buffer).reverse();
|
|
527
|
-
|
|
528
|
-
// 2. CRC32 Checksum (Big-Endian)
|
|
440
|
+
packedPayload.set(lenBytes, 0);
|
|
529
441
|
const crcBytes = new Uint8Array(new Uint32Array([payloadCrc]).buffer).reverse();
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
const totalBits = 128 + remainingPayload.length * 8; // 128 бит dynamicSalt үшін
|
|
536
|
-
const totalPixels = Math.ceil(totalBits / 3); // Әр пиксельде 3 бит (RGB LSB)
|
|
442
|
+
packedPayload.set(crcBytes, 4);
|
|
443
|
+
packedPayload.set(payloadBytes, 8);
|
|
444
|
+
packedPayload.set(paddingBytes, 8 + payloadLen);
|
|
445
|
+
const totalBits = 128 + packedPayload.length * 8;
|
|
446
|
+
const totalPixels = Math.ceil(totalBits / 3);
|
|
537
447
|
const size = Math.ceil(Math.sqrt(totalPixels)) + 4;
|
|
538
448
|
const totalRgbBytes = size * size * 3;
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const byteVal = keystream[keystreamIdx++];
|
|
449
|
+
const entropyMask = await generateHkdfKeystream(this.secretKey, dynamicSalt, totalRgbBytes);
|
|
450
|
+
let entropyIdx = 0;
|
|
451
|
+
const getNextEntropyValue = () => {
|
|
452
|
+
const byteVal = entropyMask[entropyIdx++];
|
|
544
453
|
return byteVal / 256;
|
|
545
454
|
};
|
|
546
455
|
const canvas = document.createElement("canvas");
|
|
@@ -555,7 +464,6 @@ export class NuralemBult {
|
|
|
555
464
|
ctx.fillRect(0, 0, size, size);
|
|
556
465
|
const imageData = ctx.getImageData(0, 0, size, size);
|
|
557
466
|
const pixels = imageData.data;
|
|
558
|
-
// 1-Қадам: dynamicSalt-ты сызықтық түрде бірінші 128 RGB арнасына жазу (PRNG-сіз)
|
|
559
467
|
for (let i = 0; i < 128; i++) {
|
|
560
468
|
const bytePos = Math.floor(i / 8);
|
|
561
469
|
const bitPos = 7 - (i % 8);
|
|
@@ -565,27 +473,23 @@ export class NuralemBult {
|
|
|
565
473
|
const actualFlatIdx = pixelIdx * 4 + channel;
|
|
566
474
|
pixels[actualFlatIdx] = (pixels[actualFlatIdx] & 0xFE) | bit;
|
|
567
475
|
}
|
|
568
|
-
// 2-Қадам: Қалған stego-деректерді HKDF Spacing арқылы 128-ші арнадан бастап жазу
|
|
569
476
|
let idx = 128;
|
|
570
|
-
const remainingBits =
|
|
477
|
+
const remainingBits = packedPayload.length * 8;
|
|
571
478
|
for (let i = 0; i < remainingBits; i++) {
|
|
572
479
|
const remainingBytes = totalRgbBytes - idx;
|
|
573
480
|
const remainingBitsCount = remainingBits - i;
|
|
574
481
|
const max_step = Math.floor(remainingBytes / remainingBitsCount);
|
|
575
|
-
const step = max_step > 1 ? Math.floor(
|
|
482
|
+
const step = max_step > 1 ? Math.floor(getNextEntropyValue() * max_step) + 1 : 1;
|
|
576
483
|
idx += step;
|
|
577
484
|
const rgbByteIdx = idx - 1;
|
|
578
|
-
// Битті анықтау
|
|
579
485
|
const bytePos = Math.floor(i / 8);
|
|
580
486
|
const bitPos = 7 - (i % 8);
|
|
581
|
-
const bit = (
|
|
582
|
-
// RGB индексін pixel RGBA индексіне көшіру (Alpha қатаң түрде 255 болып қалады)
|
|
487
|
+
const bit = (packedPayload[bytePos] >> bitPos) & 1;
|
|
583
488
|
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
584
|
-
const channel = rgbByteIdx % 3;
|
|
489
|
+
const channel = rgbByteIdx % 3;
|
|
585
490
|
const actualFlatIdx = pixelIdx * 4 + channel;
|
|
586
491
|
pixels[actualFlatIdx] = (pixels[actualFlatIdx] & 0xFE) | bit;
|
|
587
492
|
}
|
|
588
|
-
// Alpha арнасын 255 (толық ашық емес) етіп бекіту
|
|
589
493
|
for (let p = 0; p < size * size; p++) {
|
|
590
494
|
pixels[p * 4 + 3] = 255;
|
|
591
495
|
}
|
|
@@ -594,13 +498,8 @@ export class NuralemBult {
|
|
|
594
498
|
canvas.toBlob((blob) => resolve(blob), "image/png");
|
|
595
499
|
});
|
|
596
500
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
* Алдымен бірінші 128 арнадан сызықтық түрде Dynamic Salt оқылады,
|
|
600
|
-
* содан кейін HKDF CSPRNG арқылы қалған stego-деректер оқылып, CRC32 тексеріледі.
|
|
601
|
-
*/
|
|
602
|
-
async extractBytesFromPngNative(stegoPngBytes) {
|
|
603
|
-
const blob = new Blob([stegoPngBytes], { type: "image/png" });
|
|
501
|
+
async unsealDocumentBlock(blockBytes) {
|
|
502
|
+
const blob = new Blob([blockBytes], { type: "image/png" });
|
|
604
503
|
const url = URL.createObjectURL(blob);
|
|
605
504
|
const img = new Image();
|
|
606
505
|
img.src = url;
|
|
@@ -614,7 +513,6 @@ export class NuralemBult {
|
|
|
614
513
|
const imageData = ctx.getImageData(0, 0, img.width, img.height);
|
|
615
514
|
const pixels = imageData.data;
|
|
616
515
|
const totalRgbBytes = img.width * img.height * 3;
|
|
617
|
-
// 1-Қадам: Бірінші 128 RGB арнасынан dynamicSalt-ты сызықтық оқу
|
|
618
516
|
const dynamicSalt = new Uint8Array(16);
|
|
619
517
|
for (let i = 0; i < 128; i++) {
|
|
620
518
|
const pixelIdx = Math.floor(i / 3);
|
|
@@ -625,22 +523,20 @@ export class NuralemBult {
|
|
|
625
523
|
const bitPos = 7 - (i % 8);
|
|
626
524
|
dynamicSalt[bytePos] |= bit << bitPos;
|
|
627
525
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
const byteVal = keystream[keystreamIdx++];
|
|
526
|
+
const entropyMask = await generateHkdfKeystream(this.secretKey, dynamicSalt, totalRgbBytes);
|
|
527
|
+
let entropyIdx = 0;
|
|
528
|
+
const getNextEntropyValue = () => {
|
|
529
|
+
const byteVal = entropyMask[entropyIdx++];
|
|
633
530
|
return byteVal / 256;
|
|
634
531
|
};
|
|
635
|
-
let idx = 128;
|
|
636
|
-
// 3-Қадам: Ұзындықты оқу (32 бит = 4 байт)
|
|
532
|
+
let idx = 128;
|
|
637
533
|
const lenBytes = new Uint8Array(4);
|
|
638
534
|
const lenBits = 32;
|
|
639
535
|
for (let i = 0; i < lenBits; i++) {
|
|
640
536
|
const remainingBytes = totalRgbBytes - idx;
|
|
641
537
|
const remainingBits = lenBits - i;
|
|
642
538
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
643
|
-
const step = max_step > 1 ? Math.floor(
|
|
539
|
+
const step = max_step > 1 ? Math.floor(getNextEntropyValue() * max_step) + 1 : 1;
|
|
644
540
|
idx += step;
|
|
645
541
|
const rgbByteIdx = idx - 1;
|
|
646
542
|
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
@@ -652,14 +548,13 @@ export class NuralemBult {
|
|
|
652
548
|
lenBytes[bytePos] |= bit << bitPos;
|
|
653
549
|
}
|
|
654
550
|
const payloadLen = new Uint32Array(lenBytes.reverse().buffer)[0];
|
|
655
|
-
// 4-Қадам: CRC32 бақылау қосындысын оқу (32 бит = 4 байт)
|
|
656
551
|
const crcBytes = new Uint8Array(4);
|
|
657
552
|
const crcBits = 32;
|
|
658
553
|
for (let i = 0; i < crcBits; i++) {
|
|
659
554
|
const remainingBytes = totalRgbBytes - idx;
|
|
660
555
|
const remainingBits = crcBits - i;
|
|
661
556
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
662
|
-
const step = max_step > 1 ? Math.floor(
|
|
557
|
+
const step = max_step > 1 ? Math.floor(getNextEntropyValue() * max_step) + 1 : 1;
|
|
663
558
|
idx += step;
|
|
664
559
|
const rgbByteIdx = idx - 1;
|
|
665
560
|
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
@@ -671,19 +566,17 @@ export class NuralemBult {
|
|
|
671
566
|
crcBytes[bytePos] |= bit << bitPos;
|
|
672
567
|
}
|
|
673
568
|
const expectedCrc = new Uint32Array(crcBytes.reverse().buffer)[0];
|
|
674
|
-
// Өлшемді және сыйымдылық шегін тексеру (128 + 4 + 4 + payloadLen + 32)
|
|
675
569
|
const totalRequiredBits = 128 + (4 + 4 + payloadLen + 32) * 8;
|
|
676
570
|
if (totalRequiredBits > totalRgbBytes) {
|
|
677
|
-
throw new Error("Decryption failed
|
|
571
|
+
throw new Error("Decryption failed: Invalid key or corrupted document blocks");
|
|
678
572
|
}
|
|
679
|
-
// 5-Қадам: Негізгі шифрланған байттарды оқу
|
|
680
573
|
const totalPayloadBits = payloadLen * 8;
|
|
681
574
|
const payloadBytes = new Uint8Array(payloadLen);
|
|
682
575
|
for (let i = 0; i < totalPayloadBits; i++) {
|
|
683
576
|
const remainingBytes = totalRgbBytes - idx;
|
|
684
577
|
const remainingBits = totalPayloadBits - i;
|
|
685
578
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
686
|
-
const step = max_step > 1 ? Math.floor(
|
|
579
|
+
const step = max_step > 1 ? Math.floor(getNextEntropyValue() * max_step) + 1 : 1;
|
|
687
580
|
idx += step;
|
|
688
581
|
const rgbByteIdx = idx - 1;
|
|
689
582
|
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
@@ -694,10 +587,9 @@ export class NuralemBult {
|
|
|
694
587
|
const bitPos = 7 - (i % 8);
|
|
695
588
|
payloadBytes[bytePos] |= bit << bitPos;
|
|
696
589
|
}
|
|
697
|
-
// CRC32 тексеру
|
|
698
590
|
const actualCrc = crc32(payloadBytes);
|
|
699
591
|
if (actualCrc !== expectedCrc) {
|
|
700
|
-
throw new Error(
|
|
592
|
+
throw new Error("Decryption failed: Integrity checksum mismatch");
|
|
701
593
|
}
|
|
702
594
|
return { encryptedBytes: payloadBytes, dynamicSalt };
|
|
703
595
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuralem-bult-sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Serverless
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Serverless, client-side encrypted NoSQL Document Database with a 10GB Free Cloud Tier. Optimized with hybrid L2 caching and edge Raster Content Delivery Blocks (RCDB).",
|
|
5
5
|
"main": "dist/NuralemBult.js",
|
|
6
6
|
"types": "dist/NuralemBult.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -17,11 +17,10 @@
|
|
|
17
17
|
"nosql",
|
|
18
18
|
"serverless",
|
|
19
19
|
"database",
|
|
20
|
-
"client-side",
|
|
21
|
-
"steganography-storage",
|
|
20
|
+
"client-side-encryption",
|
|
22
21
|
"indexeddb-cache",
|
|
23
22
|
"nuralem-bult",
|
|
24
|
-
"
|
|
23
|
+
"cloud-storage"
|
|
25
24
|
],
|
|
26
25
|
"author": "Tulen Nursayat",
|
|
27
26
|
"license": "MIT",
|