@aleph-ai/tinyaleph 1.3.0 → 1.4.1

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.
@@ -1,9 +1,15 @@
1
1
  /**
2
2
  * Cryptographic Backend - Prime-based hashing, encryption, and key derivation
3
+ *
4
+ * Enhanced with QuPrimes concepts:
5
+ * - Prime-State Key Generation using resonance phases
6
+ * - Holographic Key Distribution
7
+ * - Entropy-Sensitive Encryption
3
8
  */
4
9
  const { Backend } = require('../interface');
5
10
  const { Hypercomplex } = require('../../core/hypercomplex');
6
- const { GaussianInteger, primeToFrequency, isPrime, firstNPrimes } = require('../../core/prime');
11
+ const { GaussianInteger, primeToFrequency, isPrime, firstNPrimes, factorize } = require('../../core/prime');
12
+ const { Complex, PrimeState } = require('../../core/hilbert');
7
13
 
8
14
  class CryptographicBackend extends Backend {
9
15
  constructor(config) {
@@ -193,4 +199,451 @@ class CryptographicBackend extends Backend {
193
199
  }
194
200
  }
195
201
 
196
- module.exports = { CryptographicBackend };
202
+ // ============================================================================
203
+ // PRIME-STATE KEY GENERATION (from qprimes.md)
204
+ // ============================================================================
205
+
206
+ /**
207
+ * PrimeStateKeyGenerator
208
+ *
209
+ * Generates cryptographic keys using the prime resonance framework from qprimes.md:
210
+ *
211
+ * For a state |n⟩ = Σ √(a_i/A) |p_i⟩, derive a key:
212
+ * K = Σ_i θ_{p_i} mod 2π, where θ_{p_i} = 2π log_{p_i}(n)
213
+ *
214
+ * Security relies on the difficulty of inverting phase relationships
215
+ * without the prime state, resisting quantum attacks.
216
+ */
217
+ class PrimeStateKeyGenerator {
218
+ /**
219
+ * @param {Object} options - Configuration
220
+ */
221
+ constructor(options = {}) {
222
+ this.primes = options.primes || firstNPrimes(64);
223
+ this.keyLength = options.keyLength || 32;
224
+ this.phi = (1 + Math.sqrt(5)) / 2; // Golden ratio for phase shifts
225
+ }
226
+
227
+ /**
228
+ * Compute resonance phase θ_p = 2π log_p(n)
229
+ * @param {number} p - Prime base
230
+ * @param {number} n - Number to compute phase for
231
+ * @returns {number} Phase angle in radians
232
+ */
233
+ resonancePhase(p, n) {
234
+ if (n <= 0 || p <= 1) return 0;
235
+ return 2 * Math.PI * Math.log(n) / Math.log(p);
236
+ }
237
+
238
+ /**
239
+ * Create canonical prime state from number n
240
+ * |n⟩ = Σ √(a_i/A) |p_i⟩ for n = Π p_i^{a_i}
241
+ *
242
+ * @param {number} n - Input number
243
+ * @returns {PrimeState} Canonical prime state
244
+ */
245
+ createPrimeState(n) {
246
+ const state = new PrimeState(this.primes);
247
+ const factors = factorize(n);
248
+
249
+ // Total exponent count
250
+ const A = Object.values(factors).reduce((sum, exp) => sum + exp, 0);
251
+
252
+ if (A === 0) {
253
+ // n = 1, return uniform state
254
+ return PrimeState.uniform(this.primes);
255
+ }
256
+
257
+ // Set amplitudes based on factorization
258
+ for (const [p, exp] of Object.entries(factors)) {
259
+ const prime = parseInt(p);
260
+ if (state.amplitudes.has(prime)) {
261
+ const amplitude = Math.sqrt(exp / A);
262
+ state.set(prime, new Complex(amplitude, 0));
263
+ }
264
+ }
265
+
266
+ return state.normalize();
267
+ }
268
+
269
+ /**
270
+ * Generate key from prime state using phase summation
271
+ * K = Σ_i θ_{p_i} mod 2π
272
+ *
273
+ * @param {number} n - Input number to derive key from
274
+ * @returns {Object} Key with numeric and buffer forms
275
+ */
276
+ generateKey(n) {
277
+ const state = this.createPrimeState(n);
278
+ const phases = [];
279
+
280
+ // Compute resonance phase for each prime with non-zero amplitude
281
+ for (const p of this.primes) {
282
+ const amp = state.get(p);
283
+ if (amp.norm() > 1e-10) {
284
+ const phase = this.resonancePhase(p, n);
285
+ phases.push({
286
+ prime: p,
287
+ phase,
288
+ amplitude: amp.norm(),
289
+ complex: Complex.fromPolar(amp.norm(), phase)
290
+ });
291
+ }
292
+ }
293
+
294
+ // Sum phases modulo 2π
295
+ const rawKey = phases.reduce((sum, p) => sum + p.phase * p.amplitude, 0);
296
+ const keyModulo = rawKey % (2 * Math.PI);
297
+
298
+ // Expand to key bytes using phase-derived values
299
+ const keyBytes = this.expandToBytes(phases, this.keyLength);
300
+
301
+ return {
302
+ state,
303
+ phases,
304
+ rawKey,
305
+ keyModulo,
306
+ keyBuffer: Buffer.from(keyBytes),
307
+ keyHex: Buffer.from(keyBytes).toString('hex'),
308
+ entropy: state.entropy()
309
+ };
310
+ }
311
+
312
+ /**
313
+ * Expand phase information to key bytes
314
+ * @param {Array} phases - Phase data
315
+ * @param {number} length - Desired key length
316
+ */
317
+ expandToBytes(phases, length) {
318
+ const bytes = [];
319
+
320
+ for (let i = 0; i < length; i++) {
321
+ const phaseIdx = i % phases.length;
322
+ const phase = phases[phaseIdx];
323
+
324
+ // Derive byte from phase and position
325
+ const val = (phase.phase + i * this.phi) * phase.amplitude;
326
+ const normalized = ((Math.sin(val) + 1) / 2) * 255;
327
+ bytes.push(Math.floor(normalized) & 0xFF);
328
+ }
329
+
330
+ return bytes;
331
+ }
332
+
333
+ /**
334
+ * Generate key pair (public/private) using prime resonance
335
+ *
336
+ * The public key is the prime indices and amplitudes.
337
+ * The private key includes the phase information.
338
+ *
339
+ * @param {number} seed - Seed for key generation
340
+ */
341
+ generateKeyPair(seed) {
342
+ // Use seed to create a complex number
343
+ const n = Math.abs(seed) + 1;
344
+ const privateData = this.generateKey(n);
345
+
346
+ // Public key: amplitudes without phases
347
+ const publicKey = {
348
+ primes: privateData.phases.map(p => p.prime),
349
+ amplitudes: privateData.phases.map(p => p.amplitude),
350
+ entropy: privateData.entropy
351
+ };
352
+
353
+ // Private key: full phase information
354
+ const privateKey = {
355
+ seed: n,
356
+ phases: privateData.phases,
357
+ keyBuffer: privateData.keyBuffer
358
+ };
359
+
360
+ return { publicKey, privateKey };
361
+ }
362
+
363
+ /**
364
+ * Derive shared secret from two keys
365
+ * Uses inner product of prime states
366
+ *
367
+ * @param {Object} key1 - First key data
368
+ * @param {Object} key2 - Second key data
369
+ */
370
+ deriveSharedSecret(key1, key2) {
371
+ // Compute inner product of states
372
+ const inner = key1.state.inner(key2.state);
373
+
374
+ // Use magnitude and phase as shared secret basis
375
+ const magnitude = inner.norm();
376
+ const phase = inner.phase();
377
+
378
+ // Generate shared key bytes
379
+ const bytes = [];
380
+ for (let i = 0; i < this.keyLength; i++) {
381
+ const val = Math.sin(phase + i * this.phi) * magnitude;
382
+ const normalized = ((val + 1) / 2) * 255;
383
+ bytes.push(Math.floor(Math.abs(normalized)) & 0xFF);
384
+ }
385
+
386
+ return {
387
+ coherence: magnitude,
388
+ phase,
389
+ sharedKey: Buffer.from(bytes)
390
+ };
391
+ }
392
+ }
393
+
394
+ // ============================================================================
395
+ // ENTROPY-SENSITIVE ENCRYPTION (from qprimes.md)
396
+ // ============================================================================
397
+
398
+ /**
399
+ * EntropySensitiveEncryptor
400
+ *
401
+ * Encrypt messages using entropy-based phase modulation:
402
+ * Ê_K|m⟩ = e^{iK(m)}|m⟩, where K(m) = Σ_{p|m} θ_p
403
+ */
404
+ class EntropySensitiveEncryptor {
405
+ constructor(options = {}) {
406
+ this.keyGen = new PrimeStateKeyGenerator(options);
407
+ this.primes = this.keyGen.primes;
408
+ }
409
+
410
+ /**
411
+ * Encrypt data using phase modulation
412
+ * @param {Buffer|string} data - Data to encrypt
413
+ * @param {number|Buffer} key - Encryption key (number or derived key)
414
+ */
415
+ encrypt(data, key) {
416
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
417
+
418
+ // Get key phase from numeric key
419
+ let keyPhases;
420
+ if (typeof key === 'number') {
421
+ keyPhases = this.keyGen.generateKey(key).phases;
422
+ } else {
423
+ // Use key buffer as seed
424
+ const keySeed = buffer.reduce((sum, b) => sum + b, 0) + 1;
425
+ keyPhases = this.keyGen.generateKey(keySeed).phases;
426
+ }
427
+
428
+ // Encrypt each byte with phase modulation
429
+ const encrypted = Buffer.alloc(buffer.length);
430
+
431
+ for (let i = 0; i < buffer.length; i++) {
432
+ const byte = buffer[i];
433
+
434
+ // Find divisor primes for this byte value
435
+ const phaseSum = keyPhases
436
+ .filter(p => byte % p.prime === 0 || i % p.prime === 0)
437
+ .reduce((sum, p) => sum + p.phase * p.amplitude, 0);
438
+
439
+ // Apply phase-based transformation
440
+ const transform = Math.floor((Math.sin(phaseSum + i) + 1) * 127.5);
441
+ encrypted[i] = (byte + transform) & 0xFF;
442
+ }
443
+
444
+ return encrypted;
445
+ }
446
+
447
+ /**
448
+ * Decrypt data
449
+ * @param {Buffer} encrypted - Encrypted data
450
+ * @param {number|Buffer} key - Decryption key
451
+ */
452
+ decrypt(encrypted, key) {
453
+ // Get key phases
454
+ let keyPhases;
455
+ if (typeof key === 'number') {
456
+ keyPhases = this.keyGen.generateKey(key).phases;
457
+ } else {
458
+ const keySeed = encrypted.reduce((sum, b) => sum + b, 0) + 1;
459
+ keyPhases = this.keyGen.generateKey(keySeed).phases;
460
+ }
461
+
462
+ // Decrypt each byte (inverse of encryption)
463
+ const decrypted = Buffer.alloc(encrypted.length);
464
+
465
+ for (let i = 0; i < encrypted.length; i++) {
466
+ const byte = encrypted[i];
467
+
468
+ // Same phase calculation as encryption
469
+ const phaseSum = keyPhases
470
+ .filter(p => i % p.prime === 0) // Use position-based phases for decryption
471
+ .reduce((sum, p) => sum + p.phase * p.amplitude, 0);
472
+
473
+ const transform = Math.floor((Math.sin(phaseSum + i) + 1) * 127.5);
474
+ decrypted[i] = (byte - transform + 256) & 0xFF;
475
+ }
476
+
477
+ return decrypted;
478
+ }
479
+ }
480
+
481
+ // ============================================================================
482
+ // HOLOGRAPHIC KEY DISTRIBUTION (from qprimes.md)
483
+ // ============================================================================
484
+
485
+ /**
486
+ * HolographicKeyDistributor
487
+ *
488
+ * Encode keys in interference patterns:
489
+ * I(x, y) = Σ_p A_p e^{-S(x,y)} e^{ipθ}
490
+ *
491
+ * Extract keys via Fourier inversion.
492
+ */
493
+ class HolographicKeyDistributor {
494
+ constructor(options = {}) {
495
+ this.gridSize = options.gridSize || 16;
496
+ this.keyGen = new PrimeStateKeyGenerator(options);
497
+ this.primes = this.keyGen.primes;
498
+ }
499
+
500
+ /**
501
+ * Encode key into holographic pattern
502
+ * @param {number} keyValue - Key as number
503
+ * @returns {Object} Holographic encoding
504
+ */
505
+ encodeKey(keyValue) {
506
+ const keyData = this.keyGen.generateKey(keyValue);
507
+
508
+ // Create interference pattern
509
+ const pattern = new Array(this.gridSize);
510
+ for (let x = 0; x < this.gridSize; x++) {
511
+ pattern[x] = new Array(this.gridSize);
512
+ for (let y = 0; y < this.gridSize; y++) {
513
+ let intensity = 0;
514
+ let phase = 0;
515
+
516
+ for (const p of keyData.phases) {
517
+ // Distance-based decay
518
+ const r = Math.sqrt((x - this.gridSize/2)**2 + (y - this.gridSize/2)**2);
519
+ const decay = Math.exp(-r / this.gridSize);
520
+
521
+ // Prime-frequency interference
522
+ const primePhase = p.phase + (x * p.prime / this.gridSize) + (y / p.prime);
523
+ intensity += p.amplitude * decay * Math.cos(primePhase);
524
+ phase += primePhase * p.amplitude;
525
+ }
526
+
527
+ pattern[x][y] = { intensity, phase };
528
+ }
529
+ }
530
+
531
+ return {
532
+ pattern,
533
+ keyData,
534
+ gridSize: this.gridSize
535
+ };
536
+ }
537
+
538
+ /**
539
+ * Decode key from holographic pattern
540
+ * @param {Object} encoding - Holographic encoding
541
+ * @returns {Buffer} Recovered key
542
+ */
543
+ decodeKey(encoding) {
544
+ const { pattern, gridSize } = encoding;
545
+
546
+ // Fourier inversion to extract prime phases
547
+ const extractedPhases = [];
548
+
549
+ for (const p of this.primes.slice(0, 16)) {
550
+ let realSum = 0;
551
+ let imagSum = 0;
552
+
553
+ for (let x = 0; x < gridSize; x++) {
554
+ for (let y = 0; y < gridSize; y++) {
555
+ const cell = pattern[x][y];
556
+ const freq = (x * p / gridSize) + (y / p);
557
+ realSum += cell.intensity * Math.cos(freq);
558
+ imagSum += cell.intensity * Math.sin(freq);
559
+ }
560
+ }
561
+
562
+ const magnitude = Math.sqrt(realSum**2 + imagSum**2) / (gridSize * gridSize);
563
+ const phase = Math.atan2(imagSum, realSum);
564
+
565
+ if (magnitude > 0.01) {
566
+ extractedPhases.push({ prime: p, phase, amplitude: magnitude });
567
+ }
568
+ }
569
+
570
+ // Reconstruct key from extracted phases
571
+ return this.keyGen.expandToBytes(extractedPhases, this.keyGen.keyLength);
572
+ }
573
+
574
+ /**
575
+ * Share key between parties using holographic splitting
576
+ * @param {number} keyValue - Key to share
577
+ * @param {number} numShares - Number of shares to create
578
+ * @param {number} threshold - Minimum shares needed to reconstruct
579
+ */
580
+ createShares(keyValue, numShares = 3, threshold = 2) {
581
+ const encoding = this.encodeKey(keyValue);
582
+ const shares = [];
583
+
584
+ // Split pattern into shares using XOR-like operation
585
+ for (let s = 0; s < numShares; s++) {
586
+ const share = new Array(this.gridSize);
587
+ for (let x = 0; x < this.gridSize; x++) {
588
+ share[x] = new Array(this.gridSize);
589
+ for (let y = 0; y < this.gridSize; y++) {
590
+ const original = encoding.pattern[x][y];
591
+
592
+ // Add share-specific noise
593
+ const noise = Math.sin((x + y + s) * this.keyGen.phi);
594
+ share[x][y] = {
595
+ intensity: original.intensity + noise * (s < numShares - 1 ? 1 : -numShares + 1),
596
+ phase: original.phase + (2 * Math.PI * s / numShares)
597
+ };
598
+ }
599
+ }
600
+
601
+ shares.push({
602
+ index: s,
603
+ pattern: share,
604
+ gridSize: this.gridSize
605
+ });
606
+ }
607
+
608
+ return { shares, threshold };
609
+ }
610
+
611
+ /**
612
+ * Combine shares to recover key
613
+ * @param {Array} shares - Subset of shares to combine
614
+ */
615
+ combineShares(shares) {
616
+ if (shares.length < 2) {
617
+ throw new Error('Need at least 2 shares to reconstruct');
618
+ }
619
+
620
+ // Average the patterns
621
+ const combined = new Array(this.gridSize);
622
+ for (let x = 0; x < this.gridSize; x++) {
623
+ combined[x] = new Array(this.gridSize);
624
+ for (let y = 0; y < this.gridSize; y++) {
625
+ let intensitySum = 0;
626
+ let phaseSum = 0;
627
+
628
+ for (const share of shares) {
629
+ intensitySum += share.pattern[x][y].intensity;
630
+ phaseSum += share.pattern[x][y].phase;
631
+ }
632
+
633
+ combined[x][y] = {
634
+ intensity: intensitySum / shares.length,
635
+ phase: phaseSum / shares.length
636
+ };
637
+ }
638
+ }
639
+
640
+ return this.decodeKey({ pattern: combined, gridSize: this.gridSize });
641
+ }
642
+ }
643
+
644
+ module.exports = {
645
+ CryptographicBackend,
646
+ PrimeStateKeyGenerator,
647
+ EntropySensitiveEncryptor,
648
+ HolographicKeyDistributor
649
+ };