nuralem-bult-sdk 1.1.0 → 1.2.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/dist/NuralemBult.d.ts +12 -7
- package/dist/NuralemBult.js +194 -110
- package/package.json +1 -1
package/dist/NuralemBult.d.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.
|
|
3
|
+
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.2.0 - Enterprise Grade Security Hardening)
|
|
4
4
|
* Copyright (c) 2026 Tulen Nursayat. All rights reserved.
|
|
5
5
|
* Created by Tulen Nursayat (CTO & Principal Systems Engineer)
|
|
6
6
|
*
|
|
7
|
-
* Бұл нұсқада келесі
|
|
8
|
-
* 1.
|
|
9
|
-
*
|
|
10
|
-
* 2.
|
|
11
|
-
*
|
|
7
|
+
* Бұл нұсқада келесі халықаралық банк деңгейіндегі қауіпсіздік қалқандары енгізілді:
|
|
8
|
+
* 1. PBKDF2 Key Derivation Function: Әлсіз SHA-256 хэштеуді тоқтатып, пайдаланушы кілтін қорғау үшін
|
|
9
|
+
* HMAC-SHA256, 100,000 итерация және бірегей "Salt" негізіндегі нативті PBKDF2 алгоритмі біріктірілді.
|
|
10
|
+
* 2. Keystream CSPRNG Steganography: Mulberry32 (ойыншық PRNG) толық жойылып, оның орнына
|
|
11
|
+
* Web Crypto API нативті AES-GCM (Keystream) негізіндегі детерминистік криптографиялық қауіпсіз
|
|
12
|
+
* кездейсоқ секіру (CSPRNG Spacing) алгоритмі әзірленді.
|
|
13
|
+
* 3. Encrypted L2 Cache (IndexedDB): Кэштегі деректерді XSS шабуылдары мен зиянды кеңейтілімдерден қорғау үшін,
|
|
14
|
+
* ашық мәтін (plaintext) сақтау тоқтатылды. IndexedDB қоймасына жазылатын әрбір мәлімет
|
|
15
|
+
* тек браузердің белсенді жадында (Session Runtime Memory) өмір сүретін AES-256-GCM кілтімен шифрланады.
|
|
12
16
|
*/
|
|
13
17
|
export declare class NuralemBult {
|
|
14
18
|
private static instance;
|
|
@@ -46,11 +50,12 @@ export declare class NuralemBult {
|
|
|
46
50
|
* OPAQUE RGB STEGANOGRAPHY (Түстердің қысылуы мен аномалиясынан 100% қорғалған)
|
|
47
51
|
* Деректер тек R, G, B арналарының LSB-іне жазылады, ал Alpha арнасы қатаң түрде 255 болып қалады.
|
|
48
52
|
* Түстердің қысылуынан (Color Quantization) қорғау үшін 32-байттық Padding және CRC32 Checksum енгізілген.
|
|
53
|
+
* Mulberry32 PRNG орнына Web Crypto API нативті AES (Keystream) негізіндегі детерминистік CSPRNG біріктірілген.
|
|
49
54
|
*/
|
|
50
55
|
private injectBytesToPngNative;
|
|
51
56
|
/**
|
|
52
57
|
* OPAQUE RGB STEGANOGRAPHY арқылы жазылған деректі пиксельдерден оқу
|
|
53
|
-
* CRC32 бақылау қосындысын және белсенді Padding құрылымын автоматты түрде тексереді.
|
|
58
|
+
* CRC32 бақылау қосындысын және белсенді Padding құрылымын автоматты түрде CSPRNG арқылы тексереді.
|
|
54
59
|
*/
|
|
55
60
|
private extractBytesFromPngNative;
|
|
56
61
|
private mergeUint8Arrays;
|
package/dist/NuralemBult.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.
|
|
3
|
+
* Nuralem Bult Ecosystem - NuralemBult SDK (v1.2.0 - Enterprise Grade Security Hardening)
|
|
4
4
|
* Copyright (c) 2026 Tulen Nursayat. All rights reserved.
|
|
5
5
|
* Created by Tulen Nursayat (CTO & Principal Systems Engineer)
|
|
6
6
|
*
|
|
7
|
-
* Бұл нұсқада келесі
|
|
8
|
-
* 1.
|
|
9
|
-
*
|
|
10
|
-
* 2.
|
|
11
|
-
*
|
|
7
|
+
* Бұл нұсқада келесі халықаралық банк деңгейіндегі қауіпсіздік қалқандары енгізілді:
|
|
8
|
+
* 1. PBKDF2 Key Derivation Function: Әлсіз SHA-256 хэштеуді тоқтатып, пайдаланушы кілтін қорғау үшін
|
|
9
|
+
* HMAC-SHA256, 100,000 итерация және бірегей "Salt" негізіндегі нативті PBKDF2 алгоритмі біріктірілді.
|
|
10
|
+
* 2. Keystream CSPRNG Steganography: Mulberry32 (ойыншық PRNG) толық жойылып, оның орнына
|
|
11
|
+
* Web Crypto API нативті AES-GCM (Keystream) негізіндегі детерминистік криптографиялық қауіпсіз
|
|
12
|
+
* кездейсоқ секіру (CSPRNG Spacing) алгоритмі әзірленді.
|
|
13
|
+
* 3. Encrypted L2 Cache (IndexedDB): Кэштегі деректерді XSS шабуылдары мен зиянды кеңейтілімдерден қорғау үшін,
|
|
14
|
+
* ашық мәтін (plaintext) сақтау тоқтатылды. IndexedDB қоймасына жазылатын әрбір мәлімет
|
|
15
|
+
* тек браузердің белсенді жадында (Session Runtime Memory) өмір сүретін AES-256-GCM кілтімен шифрланады.
|
|
12
16
|
*/
|
|
13
17
|
// =========================================================================
|
|
14
18
|
// БАЗАЛЫҚ БАЙТТЫҚ КОНВЕРТОРЛАР (BASE64)
|
|
@@ -30,20 +34,6 @@ function base64ToBytes(base64) {
|
|
|
30
34
|
}
|
|
31
35
|
return bytes;
|
|
32
36
|
}
|
|
33
|
-
// Mulberry32 құпия кілт негізіндегі кездейсоқ сандар генераторы (Deterministic Seeded PRNG)
|
|
34
|
-
function createRng(seedStr) {
|
|
35
|
-
let h = 2166136261 >>> 0;
|
|
36
|
-
for (let i = 0; i < seedStr.length; i++) {
|
|
37
|
-
h = Math.imul(h ^ seedStr.charCodeAt(i), 16777619);
|
|
38
|
-
}
|
|
39
|
-
let seed = h >>> 0;
|
|
40
|
-
return function () {
|
|
41
|
-
let t = seed += 0x6D2B79F5;
|
|
42
|
-
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
43
|
-
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
44
|
-
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
37
|
// CRC32 бақылау қосындысын (Checksum) есептеу алгоритмі
|
|
48
38
|
function crc32(bytes) {
|
|
49
39
|
const table = new Uint32Array(256);
|
|
@@ -61,13 +51,36 @@ function crc32(bytes) {
|
|
|
61
51
|
return (crc ^ -1) >>> 0;
|
|
62
52
|
}
|
|
63
53
|
// =========================================================================
|
|
64
|
-
// WEB CRYPTO API БРАУЗЕРЛІК КРИПТОГРАФИЯ (AES-256-GCM)
|
|
54
|
+
// WEB CRYPTO API БРАУЗЕРЛІК КРИПТОГРАФИЯ (PBKDF2 & AES-256-GCM)
|
|
65
55
|
// =========================================================================
|
|
56
|
+
/**
|
|
57
|
+
* Пайдаланушының құпия сөзінен PBKDF2 (HMAC-SHA256, 100,000 iterations)
|
|
58
|
+
* арқылы жоғары энтропиялы AES-256-GCM кілтін алу.
|
|
59
|
+
*/
|
|
66
60
|
async function deriveAesKey(secretKey) {
|
|
67
61
|
const encoder = new TextEncoder();
|
|
68
62
|
const keyData = encoder.encode(secretKey);
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
// Бастапқы шифрды PBKDF2 үшін импорттау
|
|
64
|
+
const baseKey = await crypto.subtle.importKey("raw", keyData, { name: "PBKDF2" }, false, ["deriveKey"]);
|
|
65
|
+
// Тұрақты бірегей Enterprise Salt
|
|
66
|
+
const salt = encoder.encode("nuralem_bult_enterprise_salt_2026");
|
|
67
|
+
return await crypto.subtle.deriveKey({
|
|
68
|
+
name: "PBKDF2",
|
|
69
|
+
salt: salt,
|
|
70
|
+
iterations: 100000,
|
|
71
|
+
hash: "SHA-256"
|
|
72
|
+
}, baseKey, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Web Crypto API AES-GCM көмегімен детерминистік криптографиялық қауіпсіз
|
|
76
|
+
* кездейсоқ байттар ағынын (keystream) генерациялау.
|
|
77
|
+
*/
|
|
78
|
+
async function generateDeterministicKeystream(aesKey, length) {
|
|
79
|
+
const emptyBuffer = new Uint8Array(length);
|
|
80
|
+
// Детерминистік IV (тек қана CSPRNG keystream алу үшін қолданылады)
|
|
81
|
+
const iv = new Uint8Array(12); // барлығы 0
|
|
82
|
+
const encryptedBuffer = await crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, aesKey, emptyBuffer);
|
|
83
|
+
return new Uint8Array(encryptedBuffer).slice(0, length);
|
|
71
84
|
}
|
|
72
85
|
async function encryptDataNative(payloadJson, secretKey) {
|
|
73
86
|
const cryptoKey = await deriveAesKey(secretKey);
|
|
@@ -91,14 +104,53 @@ async function decryptDataNative(encryptedBytes, secretKey) {
|
|
|
91
104
|
const decryptedBuffer = await crypto.subtle.decrypt({ name: "AES-GCM", iv: iv }, cryptoKey, ciphertext);
|
|
92
105
|
return new TextDecoder().decode(decryptedBuffer);
|
|
93
106
|
}
|
|
107
|
+
// =========================================================================
|
|
108
|
+
// L2 CACHE DATA ENCRYPTION FOR INDEXEDDB SECURE STORAGE
|
|
109
|
+
// =========================================================================
|
|
110
|
+
async function encryptCacheData(data, key) {
|
|
111
|
+
const encoder = new TextEncoder();
|
|
112
|
+
const rawJson = JSON.stringify(data);
|
|
113
|
+
const payloadBytes = encoder.encode(rawJson);
|
|
114
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
115
|
+
const encryptedBuffer = await crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, key, payloadBytes);
|
|
116
|
+
const ciphertextBytes = new Uint8Array(encryptedBuffer);
|
|
117
|
+
const finalBytes = new Uint8Array(12 + ciphertextBytes.length);
|
|
118
|
+
finalBytes.set(iv, 0);
|
|
119
|
+
finalBytes.set(ciphertextBytes, 12);
|
|
120
|
+
return bytesToBase64(finalBytes);
|
|
121
|
+
}
|
|
122
|
+
async function decryptCacheData(base64Str, key) {
|
|
123
|
+
const finalBytes = base64ToBytes(base64Str);
|
|
124
|
+
if (finalBytes.length < 12) {
|
|
125
|
+
throw new Error("Decryption failed: Cache block truncated");
|
|
126
|
+
}
|
|
127
|
+
const iv = finalBytes.slice(0, 12);
|
|
128
|
+
const ciphertext = finalBytes.slice(12);
|
|
129
|
+
const decryptedBuffer = await crypto.subtle.decrypt({ name: "AES-GCM", iv: iv }, key, ciphertext);
|
|
130
|
+
const jsonStr = new TextDecoder().decode(decryptedBuffer);
|
|
131
|
+
return JSON.parse(jsonStr);
|
|
132
|
+
}
|
|
94
133
|
class NuralemBultCache {
|
|
95
134
|
dbName = "NuralemBultCache";
|
|
96
135
|
storeName = "documents";
|
|
97
136
|
db = null;
|
|
98
137
|
TTL_DURATION = 24 * 60 * 60 * 1000; // 24 сағат өмір сүру уақыты
|
|
99
138
|
MAX_ITEMS = 100; // LRU үшін максималды құжат саны
|
|
139
|
+
// Тек браузердің белсенді жадында (Session Runtime Memory) өмір сүретін кілт
|
|
140
|
+
sessionKey = null;
|
|
100
141
|
constructor() { }
|
|
101
|
-
async init() {
|
|
142
|
+
async init(secretKey) {
|
|
143
|
+
// 1. Пайдаланушының құпия сөзінен PBKDF2 арқылы L2 кэшті қорғайтын кілтті шығару (derived key)
|
|
144
|
+
const encoder = new TextEncoder();
|
|
145
|
+
const keyData = encoder.encode(secretKey);
|
|
146
|
+
const baseKey = await crypto.subtle.importKey("raw", keyData, { name: "PBKDF2" }, false, ["deriveKey"]);
|
|
147
|
+
const salt = encoder.encode("nuralem_bult_l2_cache_salt_2026");
|
|
148
|
+
this.sessionKey = await crypto.subtle.deriveKey({
|
|
149
|
+
name: "PBKDF2",
|
|
150
|
+
salt: salt,
|
|
151
|
+
iterations: 10000, // Кэш үшін оңтайлы жылдамдық
|
|
152
|
+
hash: "SHA-256"
|
|
153
|
+
}, baseKey, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
102
154
|
return new Promise((resolve, reject) => {
|
|
103
155
|
const request = indexedDB.open(this.dbName, 1);
|
|
104
156
|
request.onupgradeneeded = () => {
|
|
@@ -118,7 +170,7 @@ class NuralemBultCache {
|
|
|
118
170
|
}
|
|
119
171
|
async get(key) {
|
|
120
172
|
return new Promise((resolve, reject) => {
|
|
121
|
-
if (!this.db)
|
|
173
|
+
if (!this.db || !this.sessionKey)
|
|
122
174
|
return resolve(null);
|
|
123
175
|
const transaction = this.db.transaction(this.storeName, "readonly");
|
|
124
176
|
const store = transaction.objectStore(this.storeName);
|
|
@@ -133,30 +185,46 @@ class NuralemBultCache {
|
|
|
133
185
|
await this.delete(key);
|
|
134
186
|
return resolve(null);
|
|
135
187
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
188
|
+
try {
|
|
189
|
+
// Кэштегі деректі дешифрлеу (XSS қорғанысы)
|
|
190
|
+
const decryptedValue = await decryptCacheData(entry.encryptedValue, this.sessionKey);
|
|
191
|
+
// LRU саясаты үшін соңғы қолданылған уақытты жаңарту (асинхронды)
|
|
192
|
+
ctxUpdateLastUsed(this.db, this.storeName, entry);
|
|
193
|
+
resolve(decryptedValue);
|
|
194
|
+
}
|
|
195
|
+
catch (e) {
|
|
196
|
+
console.error(`[NuralemBult Cache] Decryption failed (Key: "${key}"). Purging corrupted cache...`, e);
|
|
197
|
+
await this.delete(key);
|
|
198
|
+
resolve(null);
|
|
199
|
+
}
|
|
139
200
|
};
|
|
140
201
|
request.onerror = () => reject(request.error);
|
|
141
202
|
});
|
|
142
203
|
}
|
|
143
204
|
async set(key, value) {
|
|
144
205
|
return new Promise(async (resolve, reject) => {
|
|
145
|
-
if (!this.db)
|
|
146
|
-
return reject(new Error("IndexedDB database is not initialized
|
|
206
|
+
if (!this.db || !this.sessionKey)
|
|
207
|
+
return reject(new Error("IndexedDB database or sessionKey is not initialized"));
|
|
147
208
|
// Сыйымдылық шегінен (LRU) асса ең ескі құжатты өшіру
|
|
148
209
|
await this.enforceLruEviction();
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
210
|
+
try {
|
|
211
|
+
// Деректі L2 кілтімен шифрлау
|
|
212
|
+
const encryptedValue = await encryptCacheData(value, this.sessionKey);
|
|
213
|
+
const transaction = this.db.transaction(this.storeName, "readwrite");
|
|
214
|
+
const store = transaction.objectStore(this.storeName);
|
|
215
|
+
const entry = {
|
|
216
|
+
key,
|
|
217
|
+
encryptedValue,
|
|
218
|
+
timestamp: Date.now(),
|
|
219
|
+
lastUsed: Date.now()
|
|
220
|
+
};
|
|
221
|
+
const request = store.put(entry);
|
|
222
|
+
request.onsuccess = () => resolve();
|
|
223
|
+
request.onerror = () => reject(request.error);
|
|
224
|
+
}
|
|
225
|
+
catch (e) {
|
|
226
|
+
reject(e);
|
|
227
|
+
}
|
|
160
228
|
});
|
|
161
229
|
}
|
|
162
230
|
async delete(key) {
|
|
@@ -230,9 +298,10 @@ export class NuralemBult {
|
|
|
230
298
|
this.instance.routerUrl = routerUrl.replace(/\/$/, "");
|
|
231
299
|
this.instance.apiKey = apiKey;
|
|
232
300
|
this.instance.secretKey = secretKey;
|
|
233
|
-
|
|
301
|
+
// Кэшті пайдаланушының secretKey кілті арқылы инициализациялау (PBKDF2 L2 Key)
|
|
302
|
+
await this.instance.cache.init(secretKey);
|
|
234
303
|
this.instance.isInitialized = true;
|
|
235
|
-
console.log("[NuralemBult] SDK v1.
|
|
304
|
+
console.log("[NuralemBult] SDK v1.2.0 Enterprise Hardened initialized successfully.");
|
|
236
305
|
}
|
|
237
306
|
return this.instance;
|
|
238
307
|
}
|
|
@@ -434,76 +503,84 @@ export class NuralemBult {
|
|
|
434
503
|
* OPAQUE RGB STEGANOGRAPHY (Түстердің қысылуы мен аномалиясынан 100% қорғалған)
|
|
435
504
|
* Деректер тек R, G, B арналарының LSB-іне жазылады, ал Alpha арнасы қатаң түрде 255 болып қалады.
|
|
436
505
|
* Түстердің қысылуынан (Color Quantization) қорғау үшін 32-байттық Padding және CRC32 Checksum енгізілген.
|
|
506
|
+
* Mulberry32 PRNG орнына Web Crypto API нативті AES (Keystream) негізіндегі детерминистік CSPRNG біріктірілген.
|
|
437
507
|
*/
|
|
438
|
-
injectBytesToPngNative(payloadBytes) {
|
|
508
|
+
async injectBytesToPngNative(payloadBytes) {
|
|
509
|
+
const payloadLen = payloadBytes.length;
|
|
510
|
+
// CRC32 бақылау қосындысын есептеу
|
|
511
|
+
const payloadCrc = crc32(payloadBytes);
|
|
512
|
+
// Браузерлік қысу және шеткі пиксель ауытқуларынан қорғайтын 32-байттық нөлдік Padding
|
|
513
|
+
const paddingLen = 32;
|
|
514
|
+
const paddingBytes = new Uint8Array(paddingLen);
|
|
515
|
+
// Жалпы құрылым: [4 байт: payloadLen] [4 байт: CRC32] [payloadBytes] [32 байт: Padding]
|
|
516
|
+
const totalLen = 4 + 4 + payloadLen + paddingLen;
|
|
517
|
+
const payloadWithLen = new Uint8Array(totalLen);
|
|
518
|
+
// 1. Ұзындығы (Big-Endian)
|
|
519
|
+
const lenBytes = new Uint8Array(new Uint32Array([payloadLen]).buffer).reverse();
|
|
520
|
+
payloadWithLen.set(lenBytes, 0);
|
|
521
|
+
// 2. CRC32 Checksum (Big-Endian)
|
|
522
|
+
const crcBytes = new Uint8Array(new Uint32Array([payloadCrc]).buffer).reverse();
|
|
523
|
+
payloadWithLen.set(crcBytes, 4);
|
|
524
|
+
// 3. Шифрланған негізгі деректер
|
|
525
|
+
payloadWithLen.set(payloadBytes, 8);
|
|
526
|
+
// 4. Тұрақтандырушы Padding
|
|
527
|
+
payloadWithLen.set(paddingBytes, 8 + payloadLen);
|
|
528
|
+
const totalBits = payloadWithLen.length * 8;
|
|
529
|
+
const totalPixels = Math.ceil(totalBits / 3); // Әр пиксельде 3 бит (RGB LSB)
|
|
530
|
+
const size = Math.ceil(Math.sqrt(totalPixels)) + 4;
|
|
531
|
+
const totalRgbBytes = size * size * 3;
|
|
532
|
+
// Нативті PBKDF2 және AES-GCM арқылы детерминистік CSPRNG (Keystream) алу
|
|
533
|
+
const aesKey = await deriveAesKey(this.secretKey);
|
|
534
|
+
const keystream = await generateDeterministicKeystream(aesKey, totalRgbBytes);
|
|
535
|
+
let keystreamIdx = 0;
|
|
536
|
+
const getNextCryptoRand = () => {
|
|
537
|
+
const byteVal = keystream[keystreamIdx++];
|
|
538
|
+
return byteVal / 256; // 0-ден 1-ге дейінгі floating кездейсоқ санын алу
|
|
539
|
+
};
|
|
540
|
+
const canvas = document.createElement("canvas");
|
|
541
|
+
canvas.width = size;
|
|
542
|
+
canvas.height = size;
|
|
543
|
+
// srgb түстік кеңістігін орнату арқылы браузер деңгейіндегі бұрмалаудың алдын алу
|
|
544
|
+
const ctx = canvas.getContext("2d", { colorSpace: "srgb" });
|
|
545
|
+
const grad = ctx.createLinearGradient(0, 0, size, size);
|
|
546
|
+
grad.addColorStop(0, "#1f4068");
|
|
547
|
+
grad.addColorStop(0.5, "#162447");
|
|
548
|
+
grad.addColorStop(1, "#e43f5a");
|
|
549
|
+
ctx.fillStyle = grad;
|
|
550
|
+
ctx.fillRect(0, 0, size, size);
|
|
551
|
+
const imageData = ctx.getImageData(0, 0, size, size);
|
|
552
|
+
const pixels = imageData.data;
|
|
553
|
+
let idx = 0;
|
|
554
|
+
for (let i = 0; i < totalBits; i++) {
|
|
555
|
+
const remainingBytes = totalRgbBytes - idx;
|
|
556
|
+
const remainingBits = totalBits - i;
|
|
557
|
+
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
558
|
+
const step = max_step > 1 ? Math.floor(getNextCryptoRand() * max_step) + 1 : 1;
|
|
559
|
+
idx += step;
|
|
560
|
+
const rgbByteIdx = idx - 1;
|
|
561
|
+
// Битті анықтау
|
|
562
|
+
const bytePos = Math.floor(i / 8);
|
|
563
|
+
const bitPos = 7 - (i % 8);
|
|
564
|
+
const bit = (payloadWithLen[bytePos] >> bitPos) & 1;
|
|
565
|
+
// RGB индексін pixel RGBA индексіне көшіру (Alpha қатаң түрде 255 болып қалады)
|
|
566
|
+
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
567
|
+
const channel = rgbByteIdx % 3; // 0: R, 1: G, 2: B
|
|
568
|
+
const actualFlatIdx = pixelIdx * 4 + channel;
|
|
569
|
+
// Байттың LSB-ін жаңарту
|
|
570
|
+
pixels[actualFlatIdx] = (pixels[actualFlatIdx] & 0xFE) | bit;
|
|
571
|
+
}
|
|
572
|
+
// Alpha арнасын 255 (толық ашық емес) етіп бекіту
|
|
573
|
+
for (let p = 0; p < size * size; p++) {
|
|
574
|
+
pixels[p * 4 + 3] = 255;
|
|
575
|
+
}
|
|
576
|
+
ctx.putImageData(imageData, 0, 0);
|
|
439
577
|
return new Promise((resolve) => {
|
|
440
|
-
const payloadLen = payloadBytes.length;
|
|
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)
|
|
450
|
-
const lenBytes = new Uint8Array(new Uint32Array([payloadLen]).buffer).reverse();
|
|
451
|
-
payloadWithLen.set(lenBytes, 0);
|
|
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);
|
|
459
|
-
const totalBits = payloadWithLen.length * 8;
|
|
460
|
-
const totalPixels = Math.ceil(totalBits / 3); // Әр пиксельде 3 бит (RGB LSB)
|
|
461
|
-
const size = Math.ceil(Math.sqrt(totalPixels)) + 4;
|
|
462
|
-
const canvas = document.createElement("canvas");
|
|
463
|
-
canvas.width = size;
|
|
464
|
-
canvas.height = size;
|
|
465
|
-
// srgb түстік кеңістігін орнату арқылы браузер деңгейіндегі бұрмалаудың алдын алу
|
|
466
|
-
const ctx = canvas.getContext("2d", { colorSpace: "srgb" });
|
|
467
|
-
const grad = ctx.createLinearGradient(0, 0, size, size);
|
|
468
|
-
grad.addColorStop(0, "#1f4068");
|
|
469
|
-
grad.addColorStop(0.5, "#162447");
|
|
470
|
-
grad.addColorStop(1, "#e43f5a");
|
|
471
|
-
ctx.fillStyle = grad;
|
|
472
|
-
ctx.fillRect(0, 0, size, size);
|
|
473
|
-
const imageData = ctx.getImageData(0, 0, size, size);
|
|
474
|
-
const pixels = imageData.data;
|
|
475
|
-
const totalRgbBytes = size * size * 3;
|
|
476
|
-
const rng = createRng(this.secretKey);
|
|
477
|
-
let idx = 0;
|
|
478
|
-
for (let i = 0; i < totalBits; i++) {
|
|
479
|
-
const remainingBytes = totalRgbBytes - idx;
|
|
480
|
-
const remainingBits = totalBits - i;
|
|
481
|
-
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
482
|
-
const step = max_step > 1 ? Math.floor(rng() * max_step) + 1 : 1;
|
|
483
|
-
idx += step;
|
|
484
|
-
const rgbByteIdx = idx - 1;
|
|
485
|
-
// Битті анықтау
|
|
486
|
-
const bytePos = Math.floor(i / 8);
|
|
487
|
-
const bitPos = 7 - (i % 8);
|
|
488
|
-
const bit = (payloadWithLen[bytePos] >> bitPos) & 1;
|
|
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;
|
|
499
|
-
}
|
|
500
|
-
ctx.putImageData(imageData, 0, 0);
|
|
501
578
|
canvas.toBlob((blob) => resolve(blob), "image/png");
|
|
502
579
|
});
|
|
503
580
|
}
|
|
504
581
|
/**
|
|
505
582
|
* OPAQUE RGB STEGANOGRAPHY арқылы жазылған деректі пиксельдерден оқу
|
|
506
|
-
* CRC32 бақылау қосындысын және белсенді Padding құрылымын автоматты түрде тексереді.
|
|
583
|
+
* CRC32 бақылау қосындысын және белсенді Padding құрылымын автоматты түрде CSPRNG арқылы тексереді.
|
|
507
584
|
*/
|
|
508
585
|
async extractBytesFromPngNative(stegoPngBytes) {
|
|
509
586
|
const blob = new Blob([stegoPngBytes], { type: "image/png" });
|
|
@@ -520,7 +597,14 @@ export class NuralemBult {
|
|
|
520
597
|
const imageData = ctx.getImageData(0, 0, img.width, img.height);
|
|
521
598
|
const pixels = imageData.data;
|
|
522
599
|
const totalRgbBytes = img.width * img.height * 3;
|
|
523
|
-
|
|
600
|
+
// Нативті PBKDF2 және AES-GCM арқылы детерминистік CSPRNG (Keystream) алу
|
|
601
|
+
const aesKey = await deriveAesKey(this.secretKey);
|
|
602
|
+
const keystream = await generateDeterministicKeystream(aesKey, totalRgbBytes);
|
|
603
|
+
let keystreamIdx = 0;
|
|
604
|
+
const getNextCryptoRand = () => {
|
|
605
|
+
const byteVal = keystream[keystreamIdx++];
|
|
606
|
+
return byteVal / 256;
|
|
607
|
+
};
|
|
524
608
|
let idx = 0;
|
|
525
609
|
// 1. Ұзындықты оқу (32 бит = 4 байт)
|
|
526
610
|
const lenBytes = new Uint8Array(4);
|
|
@@ -529,7 +613,7 @@ export class NuralemBult {
|
|
|
529
613
|
const remainingBytes = totalRgbBytes - idx;
|
|
530
614
|
const remainingBits = lenBits - i;
|
|
531
615
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
532
|
-
const step = max_step > 1 ? Math.floor(
|
|
616
|
+
const step = max_step > 1 ? Math.floor(getNextCryptoRand() * max_step) + 1 : 1;
|
|
533
617
|
idx += step;
|
|
534
618
|
const rgbByteIdx = idx - 1;
|
|
535
619
|
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
@@ -548,7 +632,7 @@ export class NuralemBult {
|
|
|
548
632
|
const remainingBytes = totalRgbBytes - idx;
|
|
549
633
|
const remainingBits = crcBits - i;
|
|
550
634
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
551
|
-
const step = max_step > 1 ? Math.floor(
|
|
635
|
+
const step = max_step > 1 ? Math.floor(getNextCryptoRand() * max_step) + 1 : 1;
|
|
552
636
|
idx += step;
|
|
553
637
|
const rgbByteIdx = idx - 1;
|
|
554
638
|
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
|
@@ -571,7 +655,7 @@ export class NuralemBult {
|
|
|
571
655
|
const remainingBytes = totalRgbBytes - idx;
|
|
572
656
|
const remainingBits = totalPayloadBits - i;
|
|
573
657
|
const max_step = Math.floor(remainingBytes / remainingBits);
|
|
574
|
-
const step = max_step > 1 ? Math.floor(
|
|
658
|
+
const step = max_step > 1 ? Math.floor(getNextCryptoRand() * max_step) + 1 : 1;
|
|
575
659
|
idx += step;
|
|
576
660
|
const rgbByteIdx = idx - 1;
|
|
577
661
|
const pixelIdx = Math.floor(rgbByteIdx / 3);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuralem-bult-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.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",
|