yakmesh 2.9.0 → 3.0.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/CHANGELOG.md +637 -0
- package/Caddyfile +77 -0
- package/README.md +119 -29
- package/content/api.js +50 -41
- package/content/index.js +1 -2
- package/content/store.js +323 -177
- package/dashboard/index.html +19 -3
- package/database/replication.js +117 -37
- package/docs/CRYPTO-AGILITY.md +204 -0
- package/docs/MTLS-RESEARCH.md +367 -0
- package/docs/NAMCHE-SPEC.md +681 -0
- package/docs/PEERQUANTA-YAKMESH-INTEGRATION.md +407 -0
- package/docs/PRECISION-DISCLOSURE.md +96 -0
- package/docs/README.md +76 -0
- package/docs/ROADMAP-2.4.0.md +447 -0
- package/docs/ROADMAP-2.5.0.md +244 -0
- package/docs/SECURITY-AUDIT-REPORT.md +306 -0
- package/docs/SST-INTEGRATION.md +712 -0
- package/docs/STEADYWATCH-IMPLEMENTATION.md +303 -0
- package/docs/TERNARY-AUDIT-REPORT.md +247 -0
- package/docs/TME-FAQ.md +221 -0
- package/docs/WHITEPAPER.md +623 -0
- package/docs/adapters.html +1001 -0
- package/docs/advanced-systems.html +1045 -0
- package/docs/annex.html +1046 -0
- package/docs/api.html +970 -0
- package/docs/business/response-templates.md +160 -0
- package/docs/c2c.html +1225 -0
- package/docs/cli.html +1332 -0
- package/docs/configuration.html +1248 -0
- package/docs/darshan.html +1085 -0
- package/docs/dharma.html +966 -0
- package/docs/docs-bundle.html +1075 -0
- package/docs/docs.css +3120 -0
- package/docs/docs.js +556 -0
- package/docs/doko.html +969 -0
- package/docs/geo-proof.html +858 -0
- package/docs/getting-started.html +840 -0
- package/docs/gumba-tutorial.html +1144 -0
- package/docs/gumba.html +1098 -0
- package/docs/index.html +914 -0
- package/docs/jhilke.html +1312 -0
- package/docs/karma.html +1100 -0
- package/docs/katha.html +1037 -0
- package/docs/lama.html +978 -0
- package/docs/mandala.html +1067 -0
- package/docs/mani.html +964 -0
- package/docs/mantra.html +967 -0
- package/docs/mesh.html +1409 -0
- package/docs/nakpak.html +869 -0
- package/docs/namche.html +928 -0
- package/docs/nav-order.json +53 -0
- package/docs/prahari.html +1043 -0
- package/docs/prism-bash.min.js +1 -0
- package/docs/prism-javascript.min.js +1 -0
- package/docs/prism-json.min.js +1 -0
- package/docs/prism-tomorrow.min.css +1 -0
- package/docs/prism.min.js +1 -0
- package/docs/privacy.html +699 -0
- package/docs/quick-reference.html +1181 -0
- package/docs/sakshi.html +1402 -0
- package/docs/sandboxing.md +386 -0
- package/docs/seva.html +911 -0
- package/docs/sherpa.html +871 -0
- package/docs/studio.html +860 -0
- package/docs/stupa.html +995 -0
- package/docs/tailwind.min.css +2 -0
- package/docs/tattva.html +1332 -0
- package/docs/terms.html +686 -0
- package/docs/time-server-deployment.md +166 -0
- package/docs/time-sources.html +1392 -0
- package/docs/tivra.html +1127 -0
- package/docs/trademark-policy.html +686 -0
- package/docs/tribhuj.html +1183 -0
- package/docs/trust-security.html +1029 -0
- package/docs/tutorials/backup-recovery.html +654 -0
- package/docs/tutorials/dashboard.html +604 -0
- package/docs/tutorials/domain-setup.html +605 -0
- package/docs/tutorials/host-website.html +456 -0
- package/docs/tutorials/mesh-network.html +505 -0
- package/docs/tutorials/mobile-access.html +445 -0
- package/docs/tutorials/privacy.html +467 -0
- package/docs/tutorials/raspberry-pi.html +600 -0
- package/docs/tutorials/security-basics.html +539 -0
- package/docs/tutorials/share-files.html +431 -0
- package/docs/tutorials/troubleshooting.html +637 -0
- package/docs/tutorials/trust-karma.html +419 -0
- package/docs/tutorials/yak-protocol.html +456 -0
- package/docs/tutorials.html +1034 -0
- package/docs/vani.html +1270 -0
- package/docs/webserver.html +809 -0
- package/docs/yak-protocol.html +940 -0
- package/docs/yak-timeserver-design.md +475 -0
- package/docs/yakapp.html +1015 -0
- package/docs/ypc27.html +1069 -0
- package/docs/yurt.html +1344 -0
- package/embedded-docs/bundle.js +274 -114
- package/gossip/protocol.js +247 -27
- package/identity/key-resolver.js +262 -0
- package/identity/machine-seed.js +632 -0
- package/identity/node-key.js +669 -368
- package/identity/tribhuj-ratchet.js +506 -0
- package/knowledge-base.js +37 -8
- package/launcher/yakmesh.bat +62 -0
- package/launcher/yakmesh.sh +70 -0
- package/mesh/annex.js +462 -108
- package/mesh/beacon-broadcast.js +4 -1
- package/mesh/darshan.js +17 -5
- package/mesh/gumba.js +47 -13
- package/mesh/jhilke.js +651 -0
- package/mesh/katha.js +5 -2
- package/mesh/nakpak-routing.js +8 -5
- package/mesh/network.js +724 -34
- package/mesh/pulse-sync.js +4 -1
- package/mesh/seva.js +526 -0
- package/mesh/sherpa-discovery.js +89 -8
- package/mesh/sybil-defense.js +19 -5
- package/mesh/temporal-encoder.js +4 -3
- package/mesh/yurt.js +72 -17
- package/models/entropy-sentinel.onnx +0 -0
- package/models/karma-trust.onnx +0 -0
- package/models/manifest.json +43 -0
- package/models/sakshi-anomaly.onnx +0 -0
- package/oracle/code-proof-protocol.js +7 -6
- package/oracle/codebase-lock.js +257 -28
- package/oracle/index.js +74 -15
- package/oracle/ma902-snmp.js +678 -0
- package/oracle/module-sealer.js +5 -3
- package/oracle/packet-checksum.js +201 -0
- package/oracle/ternary-144t.js +714 -0
- package/oracle/ternary-ml.js +481 -0
- package/oracle/time-api.js +239 -0
- package/oracle/time-source.js +137 -47
- package/oracle/validation-oracle-hardened.js +1111 -1071
- package/oracle/validation-oracle.js +4 -2
- package/oracle/ypc27.js +211 -0
- package/package.json +20 -3
- package/protocol/yak-handler.js +35 -9
- package/protocol/yak-protocol.js +6 -5
- package/reference/cpp/yakmesh_mceliece_shard.cpp +168 -0
- package/reference/cpp/yakmesh_ypc27.cpp +179 -0
- package/sbom.json +87 -0
- package/scripts/security-audit.mjs +264 -0
- package/scripts/update-docs-sidebar.cjs +164 -0
- package/security/crypto-config.js +4 -3
- package/security/dharma-moderation.js +4 -3
- package/security/doko-identity.js +193 -143
- package/security/domain-consensus.js +86 -85
- package/security/fs-hardening.js +620 -0
- package/security/hardware-attestation.js +5 -3
- package/security/hybrid-trust.js +227 -87
- package/security/karma-rate-limiter.js +692 -0
- package/security/khata-protocol.js +22 -21
- package/security/khata-trust-integration.js +277 -150
- package/security/memory-safety.js +635 -0
- package/security/mesh-auth.js +11 -10
- package/security/mesh-revocation.js +18 -5
- package/security/namche-gateway.js +298 -69
- package/security/sakshi.js +102 -3
- package/security/sangha.js +770 -0
- package/security/secure-config.js +473 -0
- package/security/silicon-parity.js +13 -10
- package/security/steadywatch.js +1142 -0
- package/security/strike-system.js +32 -3
- package/security/temporal-signing.js +488 -0
- package/security/trit-commitment.js +464 -0
- package/server/crypto/annex.js +247 -0
- package/server/darshan-api.js +343 -0
- package/server/index.js +3259 -362
- package/server/komm-api.js +668 -0
- package/utils/accel.js +2273 -0
- package/utils/ternary-id.js +79 -0
- package/utils/verify-worker.js +57 -0
- package/webserver/index.js +95 -5
- package/assets/yakmesh-logo.png +0 -0
- package/assets/yakmesh-logo.svg +0 -80
- package/assets/yakmesh-logo2.png +0 -0
- package/assets/yakmesh-logo2sm.png +0 -0
- package/assets/ymsm.png +0 -0
- package/scripts/update-docs-nav.cjs +0 -194
- package/update-docs-nav.cjs +0 -18
- package/update-nav.ps1 +0 -16
- package/website/assets/silhouettes/adapters.svg +0 -107
- package/website/assets/silhouettes/api-endpoints.svg +0 -115
- package/website/assets/silhouettes/atomic-clock.svg +0 -83
- package/website/assets/silhouettes/base-camp.svg +0 -81
- package/website/assets/silhouettes/bridge.svg +0 -69
- package/website/assets/silhouettes/docs-bundle.svg +0 -113
- package/website/assets/silhouettes/doko-basket.svg +0 -70
- package/website/assets/silhouettes/fortress.svg +0 -93
- package/website/assets/silhouettes/gateway.svg +0 -54
- package/website/assets/silhouettes/gears.svg +0 -93
- package/website/assets/silhouettes/globe-satellite.svg +0 -67
- package/website/assets/silhouettes/karma-wheel.svg +0 -137
- package/website/assets/silhouettes/lama-council.svg +0 -141
- package/website/assets/silhouettes/mandala-network.svg +0 -169
- package/website/assets/silhouettes/mani-stones.svg +0 -149
- package/website/assets/silhouettes/mantra-wheel.svg +0 -116
- package/website/assets/silhouettes/mesh-nodes.svg +0 -113
- package/website/assets/silhouettes/nakpak.svg +0 -56
- package/website/assets/silhouettes/peak-lightning.svg +0 -73
- package/website/assets/silhouettes/sherpa.svg +0 -69
- package/website/assets/silhouettes/stupa-tower.svg +0 -119
- package/website/assets/silhouettes/tattva-eye.svg +0 -78
- package/website/assets/silhouettes/terminal.svg +0 -74
- package/website/assets/silhouettes/webserver.svg +0 -145
- package/website/assets/silhouettes/yak.svg +0 -78
- package/website/assets/yakmesh-logo.png +0 -0
- package/website/assets/yakmesh-logo.webp +0 -0
- package/website/assets/yakmesh-logo128x140.webp +0 -0
- package/website/assets/yakmesh-logo2.png +0 -0
- package/website/assets/yakmesh-logo2.svg +0 -51
- package/website/assets/yakmesh-logo40x44.webp +0 -0
- package/website/assets/yakmesh.gif +0 -0
- package/website/assets/yakmesh.ico +0 -0
- package/website/assets/yakmesh.jpg +0 -0
- package/website/assets/yakmesh.pdf +0 -0
- package/website/assets/yakmesh.png +0 -0
- package/website/assets/yakmesh.svg +0 -70
- package/website/assets/yakmesh128.webp +0 -0
- package/website/assets/yakmesh32.png +0 -0
- package/website/assets/yakmesh32.svg +0 -65
- package/website/assets/yakmesh32o.ico +0 -2
- package/website/assets/yakmesh32o.svg +0 -65
- package/website/assets/yakmesh32o.svgz +0 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TRIBHUJ Key Ratchet — Trinary Rotating Keypairs
|
|
3
|
+
*
|
|
4
|
+
* त्रिभुज (Tribhuj) = Triangle, three-pointed
|
|
5
|
+
*
|
|
6
|
+
* A Fibonacci-style key ratchet using TRIBHUJ balanced ternary principles.
|
|
7
|
+
* Two ML-DSA-65 keypairs are generated at genesis (the triangle's base).
|
|
8
|
+
* All subsequent keys are derived by amalgamating the previous two:
|
|
9
|
+
*
|
|
10
|
+
* K₀ = genesis left (random seed)
|
|
11
|
+
* K₁ = genesis right (random seed)
|
|
12
|
+
* K₂ = derive(K₀, K₁) — SHA3-256(secret₀ ‖ secret₁) → seed → keygen
|
|
13
|
+
* K₃ = derive(K₁, K₂)
|
|
14
|
+
* Kₙ = derive(Kₙ₋₂, Kₙ₋₁)
|
|
15
|
+
*
|
|
16
|
+
* At any point, the ratchet holds THREE states (the triangle):
|
|
17
|
+
* - previous: accepted for verification (transition grace period)
|
|
18
|
+
* - current: used for signing, accepted for verification
|
|
19
|
+
* - next: pre-computed, ready to rotate into current
|
|
20
|
+
*
|
|
21
|
+
* The "take away the treasure" principle:
|
|
22
|
+
* - Compromising the current key reveals NOTHING about previous keys
|
|
23
|
+
* (SHA3-256 is one-way; you can't reverse the amalgamation)
|
|
24
|
+
* - The attacker gets ONE key, not a history
|
|
25
|
+
* - Rotation makes even that key useless within one interval
|
|
26
|
+
*
|
|
27
|
+
* TRIBHUJ synergy: the ternary state {previous, current, next} maps
|
|
28
|
+
* directly to balanced ternary {-1, 0, +1} / {past, present, future}.
|
|
29
|
+
* The ratchet IS a TRIBHUJ operation — three states, rotating forward.
|
|
30
|
+
*
|
|
31
|
+
* @module identity/tribhuj-ratchet
|
|
32
|
+
* @license MIT
|
|
33
|
+
* @copyright 2026 YAKMESH™ Contributors
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { ml_dsa65 } from '@noble/post-quantum/ml-dsa.js';
|
|
37
|
+
import { sha3_256 as _nobleSha3 } from '@noble/hashes/sha3.js';
|
|
38
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
|
|
39
|
+
import { createLogger } from '../utils/logger.js';
|
|
40
|
+
|
|
41
|
+
// ACCEL: Hardware-accelerated crypto (native SHA3 via OpenSSL/SHA-NI, future liboqs)
|
|
42
|
+
import { sha3_256, mlDsa65Sign, mlDsa65Verify } from '../utils/accel.js';
|
|
43
|
+
|
|
44
|
+
const log = createLogger('identity:tribhuj-ratchet');
|
|
45
|
+
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// CONFIGURATION
|
|
48
|
+
// =============================================================================
|
|
49
|
+
|
|
50
|
+
const RATCHET_CONFIG = {
|
|
51
|
+
// Rotation interval (default: 5 minutes)
|
|
52
|
+
rotationInterval: 300000,
|
|
53
|
+
|
|
54
|
+
// Grace period: how long to accept signatures from the previous key
|
|
55
|
+
// (allows in-flight messages signed with old key to still verify)
|
|
56
|
+
gracePeriod: 60000,
|
|
57
|
+
|
|
58
|
+
// Max rotations before forcing a full re-genesis
|
|
59
|
+
// (defense-in-depth: limits the derivation chain length)
|
|
60
|
+
maxChainLength: 1000,
|
|
61
|
+
|
|
62
|
+
// Algorithm identifier
|
|
63
|
+
algorithm: 'TRIBHUJ-ML-DSA-65',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// TRIBHUJ KEY RATCHET
|
|
68
|
+
// =============================================================================
|
|
69
|
+
|
|
70
|
+
export class TribhujRatchet {
|
|
71
|
+
/**
|
|
72
|
+
* @param {Object} options
|
|
73
|
+
* @param {number} [options.rotationInterval] - Ms between rotations
|
|
74
|
+
* @param {number} [options.gracePeriod] - Ms to accept old key
|
|
75
|
+
* @param {number} [options.maxChainLength] - Max rotations before re-genesis
|
|
76
|
+
*/
|
|
77
|
+
constructor(options = {}) {
|
|
78
|
+
this.config = { ...RATCHET_CONFIG, ...options };
|
|
79
|
+
|
|
80
|
+
// The triangle: three keypair slots
|
|
81
|
+
this._previous = null; // {publicKey, secretKey, epoch}
|
|
82
|
+
this._current = null; // {publicKey, secretKey, epoch}
|
|
83
|
+
this._next = null; // {publicKey, secretKey, epoch}
|
|
84
|
+
|
|
85
|
+
this._epoch = 0; // Rotation counter
|
|
86
|
+
this._chainLength = 0; // Current chain derivation depth
|
|
87
|
+
this._rotationTimer = null;
|
|
88
|
+
this._genesisSeeds = null; // Zeroed after first rotation
|
|
89
|
+
|
|
90
|
+
this._initialized = false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Initialize the ratchet — generates the two genesis keypairs.
|
|
95
|
+
* This is the only time raw keygen happens (the "double overhead").
|
|
96
|
+
*/
|
|
97
|
+
async initialize() {
|
|
98
|
+
log.info('TRIBHUJ ratchet initializing — generating genesis keypairs');
|
|
99
|
+
|
|
100
|
+
// Genesis: two independent random keypairs
|
|
101
|
+
const seedA = crypto.getRandomValues(new Uint8Array(32));
|
|
102
|
+
const seedB = crypto.getRandomValues(new Uint8Array(32));
|
|
103
|
+
|
|
104
|
+
const kpA = ml_dsa65.keygen(seedA);
|
|
105
|
+
const kpB = ml_dsa65.keygen(seedB);
|
|
106
|
+
|
|
107
|
+
this._previous = {
|
|
108
|
+
publicKey: kpA.publicKey,
|
|
109
|
+
secretKey: kpA.secretKey,
|
|
110
|
+
epoch: 0,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
this._current = {
|
|
114
|
+
publicKey: kpB.publicKey,
|
|
115
|
+
secretKey: kpB.secretKey,
|
|
116
|
+
epoch: 1,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Pre-compute next by amalgamating A + B
|
|
120
|
+
this._next = this._deriveNext(this._previous, this._current, 2);
|
|
121
|
+
|
|
122
|
+
this._epoch = 1;
|
|
123
|
+
this._chainLength = 0;
|
|
124
|
+
this._initialized = true;
|
|
125
|
+
|
|
126
|
+
// Zero genesis seeds (they're no longer needed)
|
|
127
|
+
seedA.fill(0);
|
|
128
|
+
seedB.fill(0);
|
|
129
|
+
|
|
130
|
+
log.info('TRIBHUJ ratchet ready — triangle formed', {
|
|
131
|
+
epoch: this._epoch,
|
|
132
|
+
pubKeyPrev: bytesToHex(this._previous.publicKey).slice(0, 24) + '...',
|
|
133
|
+
pubKeyCurr: bytesToHex(this._current.publicKey).slice(0, 24) + '...',
|
|
134
|
+
pubKeyNext: bytesToHex(this._next.publicKey).slice(0, 24) + '...',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Start automatic rotation on a timer.
|
|
142
|
+
*/
|
|
143
|
+
startAutoRotation() {
|
|
144
|
+
if (this._rotationTimer) return;
|
|
145
|
+
|
|
146
|
+
this._rotationTimer = setInterval(() => {
|
|
147
|
+
this.rotate();
|
|
148
|
+
}, this.config.rotationInterval);
|
|
149
|
+
|
|
150
|
+
log.info(`TRIBHUJ auto-rotation started (every ${this.config.rotationInterval / 1000}s)`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Stop automatic rotation.
|
|
155
|
+
*/
|
|
156
|
+
stopAutoRotation() {
|
|
157
|
+
if (this._rotationTimer) {
|
|
158
|
+
clearInterval(this._rotationTimer);
|
|
159
|
+
this._rotationTimer = null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Rotate the triangle forward: previous ← current, current ← next, next ← derive(current, next)
|
|
165
|
+
*
|
|
166
|
+
* This is the TRIBHUJ operation: the triangle slides forward through time.
|
|
167
|
+
* {past, present, future} → {present, future, derive(present, future)}
|
|
168
|
+
*/
|
|
169
|
+
rotate() {
|
|
170
|
+
if (!this._initialized) {
|
|
171
|
+
throw new Error('TRIBHUJ ratchet not initialized');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this._chainLength++;
|
|
175
|
+
|
|
176
|
+
// Check chain length limit
|
|
177
|
+
if (this._chainLength >= this.config.maxChainLength) {
|
|
178
|
+
log.warn('TRIBHUJ chain limit reached, performing re-genesis');
|
|
179
|
+
this.initialize();
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Zero the outgoing previous secret key — "take away the treasure"
|
|
184
|
+
if (this._previous?.secretKey) {
|
|
185
|
+
this._previous.secretKey.fill(0);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const newEpoch = this._epoch + 1;
|
|
189
|
+
|
|
190
|
+
// Slide the triangle forward
|
|
191
|
+
this._previous = {
|
|
192
|
+
publicKey: this._current.publicKey,
|
|
193
|
+
secretKey: null, // Only need public key for verification
|
|
194
|
+
epoch: this._current.epoch,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
this._current = this._next;
|
|
198
|
+
this._next = this._deriveNext(this._previous, this._current, newEpoch + 1);
|
|
199
|
+
this._epoch = newEpoch;
|
|
200
|
+
|
|
201
|
+
log.debug('TRIBHUJ rotated', {
|
|
202
|
+
epoch: this._epoch,
|
|
203
|
+
chainLength: this._chainLength,
|
|
204
|
+
currentPubKey: bytesToHex(this._current.publicKey).slice(0, 24) + '...',
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
epoch: this._epoch,
|
|
209
|
+
publicKey: bytesToHex(this._current.publicKey),
|
|
210
|
+
previousPublicKey: bytesToHex(this._previous.publicKey),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Derive the next keypair from two parent keypairs (the TRIBHUJ amalgamation).
|
|
216
|
+
*
|
|
217
|
+
* seed = SHA3-256(epochBytes ‖ parentA.publicKey ‖ parentB.secretKey)
|
|
218
|
+
*
|
|
219
|
+
* Uses the public key of one parent and secret key of the other to ensure:
|
|
220
|
+
* - Both parents contribute entropy
|
|
221
|
+
* - An observer with only public keys cannot predict the next key
|
|
222
|
+
* - The derivation is deterministic given the triangle state
|
|
223
|
+
*/
|
|
224
|
+
_deriveNext(parentA, parentB, epoch) {
|
|
225
|
+
// Build the amalgamation input
|
|
226
|
+
const epochBytes = new Uint8Array(4);
|
|
227
|
+
new DataView(epochBytes.buffer).setUint32(0, epoch, false);
|
|
228
|
+
|
|
229
|
+
// Combine: epoch ‖ pubA ‖ secretB (or pubA if secretB unavailable)
|
|
230
|
+
const material = parentB.secretKey || parentB.publicKey;
|
|
231
|
+
const combined = new Uint8Array(4 + parentA.publicKey.length + material.length);
|
|
232
|
+
combined.set(epochBytes, 0);
|
|
233
|
+
combined.set(parentA.publicKey, 4);
|
|
234
|
+
combined.set(material, 4 + parentA.publicKey.length);
|
|
235
|
+
|
|
236
|
+
// Derive seed via SHA3-256
|
|
237
|
+
const seed = sha3_256(combined);
|
|
238
|
+
|
|
239
|
+
// Zero intermediate material
|
|
240
|
+
combined.fill(0);
|
|
241
|
+
|
|
242
|
+
// Generate new keypair from derived seed
|
|
243
|
+
const kp = ml_dsa65.keygen(seed);
|
|
244
|
+
|
|
245
|
+
// Zero the seed
|
|
246
|
+
seed.fill(0);
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
publicKey: kp.publicKey,
|
|
250
|
+
secretKey: kp.secretKey,
|
|
251
|
+
epoch,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ===========================================================================
|
|
256
|
+
// SIGNING & VERIFICATION
|
|
257
|
+
// ===========================================================================
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Sign a message with the current key.
|
|
261
|
+
* Returns the signature + epoch so verifiers know which key to check.
|
|
262
|
+
*/
|
|
263
|
+
sign(message) {
|
|
264
|
+
if (!this._initialized || !this._current?.secretKey) {
|
|
265
|
+
throw new Error('TRIBHUJ ratchet not ready for signing');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const messageBytes = typeof message === 'string'
|
|
269
|
+
? new TextEncoder().encode(message)
|
|
270
|
+
: message;
|
|
271
|
+
|
|
272
|
+
const signature = mlDsa65Sign(messageBytes, this._current.secretKey);
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
signature: bytesToHex(signature),
|
|
276
|
+
epoch: this._epoch,
|
|
277
|
+
publicKey: bytesToHex(this._current.publicKey),
|
|
278
|
+
algorithm: this.config.algorithm,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Sign an object (add _tribhujSig, _tribhujEpoch, _tribhujPubKey fields).
|
|
284
|
+
*/
|
|
285
|
+
signObject(obj) {
|
|
286
|
+
const payload = JSON.stringify(obj);
|
|
287
|
+
const sig = this.sign(payload);
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
...obj,
|
|
291
|
+
_tribhujSig: sig.signature,
|
|
292
|
+
_tribhujEpoch: sig.epoch,
|
|
293
|
+
_tribhujPubKey: sig.publicKey,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Verify a signature, accepting current OR previous key (grace period).
|
|
299
|
+
*
|
|
300
|
+
* The ternary verification: try current (+1), try previous (-1), fail (0).
|
|
301
|
+
* This is a TRIBHUJ consensus operation in miniature.
|
|
302
|
+
*
|
|
303
|
+
* @param {string|Uint8Array} message
|
|
304
|
+
* @param {string} signatureHex
|
|
305
|
+
* @param {string} publicKeyHex - The signer's claimed public key
|
|
306
|
+
* @returns {{ valid: boolean, keyState: string }} keyState: 'current'|'previous'|'invalid'
|
|
307
|
+
*/
|
|
308
|
+
verify(message, signatureHex, publicKeyHex) {
|
|
309
|
+
const messageBytes = typeof message === 'string'
|
|
310
|
+
? new TextEncoder().encode(message)
|
|
311
|
+
: message;
|
|
312
|
+
const signature = hexToBytes(signatureHex);
|
|
313
|
+
const publicKey = hexToBytes(publicKeyHex);
|
|
314
|
+
|
|
315
|
+
// Try current key (POSITIVE / present)
|
|
316
|
+
if (this._current && bytesToHex(this._current.publicKey) === publicKeyHex) {
|
|
317
|
+
try {
|
|
318
|
+
if (mlDsa65Verify(signature, messageBytes, publicKey)) {
|
|
319
|
+
return { valid: true, keyState: 'current' };
|
|
320
|
+
}
|
|
321
|
+
} catch (e) { /* fall through */ }
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Try previous key (NEGATIVE / past — grace period)
|
|
325
|
+
if (this._previous && bytesToHex(this._previous.publicKey) === publicKeyHex) {
|
|
326
|
+
try {
|
|
327
|
+
if (mlDsa65Verify(signature, messageBytes, publicKey)) {
|
|
328
|
+
return { valid: true, keyState: 'previous' };
|
|
329
|
+
}
|
|
330
|
+
} catch (e) { /* fall through */ }
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Unknown key — verify against the provided public key directly
|
|
334
|
+
// (for messages from peers whose ratchet state we don't track)
|
|
335
|
+
try {
|
|
336
|
+
if (mlDsa65Verify(signature, messageBytes, publicKey)) {
|
|
337
|
+
return { valid: true, keyState: 'external' };
|
|
338
|
+
}
|
|
339
|
+
} catch (e) { /* fall through */ }
|
|
340
|
+
|
|
341
|
+
return { valid: false, keyState: 'invalid' };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Verify a signed object.
|
|
346
|
+
*/
|
|
347
|
+
verifyObject(signedObj, publicKeyHex) {
|
|
348
|
+
const { _tribhujSig, _tribhujEpoch, _tribhujPubKey, ...rest } = signedObj;
|
|
349
|
+
if (!_tribhujSig) return { valid: false, keyState: 'unsigned' };
|
|
350
|
+
|
|
351
|
+
const key = publicKeyHex || _tribhujPubKey;
|
|
352
|
+
const payload = JSON.stringify(rest);
|
|
353
|
+
return this.verify(payload, _tribhujSig, key);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// ===========================================================================
|
|
357
|
+
// STATE / EXPORT
|
|
358
|
+
// ===========================================================================
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Get current ratchet state (public info only — safe to share over network).
|
|
362
|
+
*/
|
|
363
|
+
getPublicState() {
|
|
364
|
+
return {
|
|
365
|
+
algorithm: this.config.algorithm,
|
|
366
|
+
epoch: this._epoch,
|
|
367
|
+
chainLength: this._chainLength,
|
|
368
|
+
currentPublicKey: this._current ? bytesToHex(this._current.publicKey) : null,
|
|
369
|
+
previousPublicKey: this._previous ? bytesToHex(this._previous.publicKey) : null,
|
|
370
|
+
rotationInterval: this.config.rotationInterval,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Destroy all key material — "take away ALL the treasure".
|
|
376
|
+
*/
|
|
377
|
+
destroy() {
|
|
378
|
+
if (this._previous?.secretKey) this._previous.secretKey.fill(0);
|
|
379
|
+
if (this._current?.secretKey) this._current.secretKey.fill(0);
|
|
380
|
+
if (this._next?.secretKey) this._next.secretKey.fill(0);
|
|
381
|
+
|
|
382
|
+
this._previous = null;
|
|
383
|
+
this._current = null;
|
|
384
|
+
this._next = null;
|
|
385
|
+
this._initialized = false;
|
|
386
|
+
|
|
387
|
+
this.stopAutoRotation();
|
|
388
|
+
|
|
389
|
+
log.info('TRIBHUJ ratchet destroyed — all key material zeroed');
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// =============================================================================
|
|
394
|
+
// GATEWAY ATTESTATION — "Verify Once, Trust the Stamp"
|
|
395
|
+
// =============================================================================
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* A lightweight attestation that a gateway node has verified a message's
|
|
399
|
+
* ML-DSA-65 signature. Other nodes that trust this gateway can skip the
|
|
400
|
+
* expensive full verify and just check the attestation.
|
|
401
|
+
*
|
|
402
|
+
* This is the "non-rewarding" approach: the heavy crypto (ML-DSA-65 verify,
|
|
403
|
+
* ~2-5ms) happens once at the gateway. Subsequent nodes see only the
|
|
404
|
+
* attestation hash (~0.01ms to verify).
|
|
405
|
+
*
|
|
406
|
+
* Structure:
|
|
407
|
+
* attestation = SHA3-256(messageId ‖ signer ‖ gatewayNodeId ‖ timestamp)
|
|
408
|
+
* + signature from gateway's TRIBHUJ ratchet
|
|
409
|
+
*/
|
|
410
|
+
export class GatewayAttestation {
|
|
411
|
+
/**
|
|
412
|
+
* @param {string} gatewayNodeId - This gateway's node ID
|
|
413
|
+
* @param {TribhujRatchet} ratchet - Gateway's TRIBHUJ ratchet for signing attestations
|
|
414
|
+
* @param {Object} [options]
|
|
415
|
+
* @param {number} [options.attestationTTL=60000] - How long attestations are valid
|
|
416
|
+
*/
|
|
417
|
+
constructor(gatewayNodeId, ratchet, options = {}) {
|
|
418
|
+
this.gatewayNodeId = gatewayNodeId;
|
|
419
|
+
this.ratchet = ratchet;
|
|
420
|
+
this.attestationTTL = options.attestationTTL || 60000;
|
|
421
|
+
|
|
422
|
+
// Cache of attestations we've issued (for dedup)
|
|
423
|
+
this._issued = new Map(); // messageId -> attestation
|
|
424
|
+
this._maxIssued = 5000;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Create an attestation for a verified message.
|
|
429
|
+
* Call this AFTER you've done the full ML-DSA-65 verify.
|
|
430
|
+
*
|
|
431
|
+
* @param {string} messageId
|
|
432
|
+
* @param {string} signerNodeId - Who signed the original message
|
|
433
|
+
* @returns {Object} The attestation object to attach to the message
|
|
434
|
+
*/
|
|
435
|
+
attest(messageId, signerNodeId) {
|
|
436
|
+
const timestamp = Date.now();
|
|
437
|
+
|
|
438
|
+
// Build attestation hash
|
|
439
|
+
const input = `${messageId}:${signerNodeId}:${this.gatewayNodeId}:${timestamp}`;
|
|
440
|
+
const hashBytes = sha3_256(new TextEncoder().encode(input));
|
|
441
|
+
const attestHash = bytesToHex(hashBytes);
|
|
442
|
+
|
|
443
|
+
// Sign the attestation with our TRIBHUJ ratchet (fast — key already in memory)
|
|
444
|
+
const sig = this.ratchet.sign(attestHash);
|
|
445
|
+
|
|
446
|
+
const attestation = {
|
|
447
|
+
_gwAttest: {
|
|
448
|
+
hash: attestHash,
|
|
449
|
+
gateway: this.gatewayNodeId,
|
|
450
|
+
signer: signerNodeId,
|
|
451
|
+
messageId,
|
|
452
|
+
timestamp,
|
|
453
|
+
sig: sig.signature,
|
|
454
|
+
epoch: sig.epoch,
|
|
455
|
+
pubKey: sig.publicKey,
|
|
456
|
+
},
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
// Cache
|
|
460
|
+
this._issued.set(messageId, attestation);
|
|
461
|
+
if (this._issued.size > this._maxIssued) {
|
|
462
|
+
// Evict oldest
|
|
463
|
+
const first = this._issued.keys().next().value;
|
|
464
|
+
this._issued.delete(first);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return attestation._gwAttest;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Verify an attestation from a trusted gateway.
|
|
472
|
+
* Much cheaper than full ML-DSA-65 verify (~0.01ms vs ~2-5ms).
|
|
473
|
+
*
|
|
474
|
+
* @param {Object} attestation - The _gwAttest object
|
|
475
|
+
* @param {TribhujRatchet} [gatewayRatchet] - Gateway's ratchet (optional, uses our own if same gateway)
|
|
476
|
+
* @returns {{ valid: boolean, reason: string }}
|
|
477
|
+
*/
|
|
478
|
+
verifyAttestation(attestation, gatewayRatchet = null) {
|
|
479
|
+
if (!attestation?.hash || !attestation?.sig || !attestation?.gateway) {
|
|
480
|
+
return { valid: false, reason: 'malformed' };
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Check TTL
|
|
484
|
+
if (Date.now() - attestation.timestamp > this.attestationTTL) {
|
|
485
|
+
return { valid: false, reason: 'expired' };
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Reconstruct expected hash
|
|
489
|
+
const input = `${attestation.messageId}:${attestation.signer}:${attestation.gateway}:${attestation.timestamp}`;
|
|
490
|
+
const expectedHash = bytesToHex(sha3_256(new TextEncoder().encode(input)));
|
|
491
|
+
|
|
492
|
+
if (expectedHash !== attestation.hash) {
|
|
493
|
+
return { valid: false, reason: 'hash_mismatch' };
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// Verify the gateway's TRIBHUJ signature on the hash
|
|
497
|
+
const ratchet = gatewayRatchet || this.ratchet;
|
|
498
|
+
const result = ratchet.verify(attestation.hash, attestation.sig, attestation.pubKey);
|
|
499
|
+
|
|
500
|
+
return result.valid
|
|
501
|
+
? { valid: true, reason: `verified_via_${result.keyState}` }
|
|
502
|
+
: { valid: false, reason: 'bad_gateway_signature' };
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export default TribhujRatchet;
|
package/knowledge-base.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* YAKMESH Comprehensive Knowledge Base
|
|
2
|
+
* YAKMESH Comprehensive Knowledge Base v3.0.0
|
|
3
3
|
*
|
|
4
4
|
* This file contains ALL technical information about YAKMESH
|
|
5
5
|
* for use by YakBot (Discord) and YakAI (Web Assistant).
|
|
6
6
|
*
|
|
7
|
-
* Last Updated: 2026-02-
|
|
7
|
+
* Last Updated: 2026-02-12
|
|
8
8
|
*
|
|
9
9
|
* @module knowledge-base
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
export const YAKMESH_KNOWLEDGE_BASE = `
|
|
13
|
-
# YAKMESH
|
|
13
|
+
# YAKMESH v3.0.0 Complete Technical Reference
|
|
14
14
|
|
|
15
15
|
## Overview
|
|
16
16
|
YAKMESH (Yielding Atomic Kernel Modular Encryption Secured Hub) is a post-quantum secure P2P mesh network built for the 2026 threat landscape. It combines quantum-resistant cryptography with physics-based verification to create trustless distributed systems.
|
|
17
17
|
|
|
18
18
|
**Key Stats:**
|
|
19
|
-
- Version:
|
|
20
|
-
- Tests: 812 (Oracle 98, Protocol 56, Multi-Node 18, Security 390+, BYOND 36)
|
|
19
|
+
- Version: 3.0.0
|
|
20
|
+
- Tests: 812+ (Oracle 98, Protocol 56, Multi-Node 18, Security 390+, BYOND 36)
|
|
21
21
|
- License: MIT
|
|
22
22
|
- Node.js 18+ required
|
|
23
23
|
|
|
@@ -50,9 +50,13 @@ Epidemic-style message propagation.
|
|
|
50
50
|
|
|
51
51
|
### 4. ANNEX - Encrypted Channels
|
|
52
52
|
Autonomous Network Negotiated eXchange.
|
|
53
|
-
- ML-KEM-768 ephemeral key exchange
|
|
54
|
-
-
|
|
55
|
-
- Forward secrecy with key rotation
|
|
53
|
+
- ML-KEM-768 ephemeral key exchange (NIST FIPS 203)
|
|
54
|
+
- AES-256-GCM symmetric encryption
|
|
55
|
+
- Forward secrecy with TRIBHUJ key ratchet rotation
|
|
56
|
+
- Session expiry: 1hr timeout + 10K message limit, auto-rekey
|
|
57
|
+
- Replay protection: nonce dedup with 5-min window
|
|
58
|
+
- sharedSecret zeroed immediately after key derivation
|
|
59
|
+
- Transparent encryption on ALL peer-to-peer wire traffic
|
|
56
60
|
- Content-addressed storage integration
|
|
57
61
|
|
|
58
62
|
### 5. NAKPAK - Onion Routing
|
|
@@ -68,6 +72,30 @@ Secure Hidden Endpoint Resolution Path Architecture.
|
|
|
68
72
|
- RTT measurement for geo-proofing (performance.now())
|
|
69
73
|
- Automatic landmark discovery
|
|
70
74
|
- Protocol version 1.1 (geo-enabled)
|
|
75
|
+
|
|
76
|
+
### 7. TRIBHUJ (त्रिभुज) - Trinary Rotating Keypairs (NEW in v3.0)
|
|
77
|
+
Fibonacci-style ML-DSA-65 key ratchet using balanced ternary principles.
|
|
78
|
+
- Two genesis keypairs generated once ("double overhead"), then infinite derivation
|
|
79
|
+
- Key Kn = ML-DSA-65.keygen(SHA3-256(epoch || pub(n-2) || secret(n-1)))
|
|
80
|
+
- Triangle state: {previous(-1), current(0), next(+1)} = balanced ternary
|
|
81
|
+
- Forward secrecy: previous secret keys zeroed on rotation
|
|
82
|
+
- 5-minute auto-rotation, 1-minute grace period for in-flight messages
|
|
83
|
+
- Chain limit 1000 before forced re-genesis
|
|
84
|
+
- Also provides balanced ternary math: Trit(-1,0,+1), TritArray, consensus logic
|
|
85
|
+
|
|
86
|
+
### 8. Gateway Attestation (NEW in v3.0)
|
|
87
|
+
Verify-once gossip signature optimization.
|
|
88
|
+
- First verifier creates attestation: SHA3-256(messageId + signer + gatewayId + timestamp)
|
|
89
|
+
- Attestation signed with TRIBHUJ ratchet (~0.01ms vs ~2-5ms full ML-DSA-65 verify)
|
|
90
|
+
- Downstream peers check attestation instead of re-verifying original signature
|
|
91
|
+
- 60s TTL, automatically attached to gossip messages
|
|
92
|
+
|
|
93
|
+
### 9. SSE Real-Time Push (NEW in v3.0)
|
|
94
|
+
Server-Sent Events for instant gossip delivery.
|
|
95
|
+
- GET /rumors/subscribe — real-time gossip stream
|
|
96
|
+
- Replaces 10s HTTP polling (avg 5s latency → near-instant)
|
|
97
|
+
- Topic filtering, 15s heartbeat, auto-cleanup
|
|
98
|
+
- MeshBridge connects via SSE-first with HTTP polling fallback
|
|
71
99
|
- No central bootstrap required
|
|
72
100
|
|
|
73
101
|
### 7. STUPA - State Consensus
|
|
@@ -653,6 +681,7 @@ YAKMESH honors mountain peoples with Nepali/Tibetan naming:
|
|
|
653
681
|
---
|
|
654
682
|
|
|
655
683
|
## VERSION HISTORY
|
|
684
|
+
- v3.0.0: TRIBHUJ key ratchet, Gateway Attestation, SSE real-time push, ANNEX hardening, MeshBridge completion, comprehensive security audit (~90 findings addressed)
|
|
656
685
|
- v2.6.6: Philosophy page, Himalayan tribute, favicon fixes
|
|
657
686
|
- v2.6.5: Production Tailwind build, CDN removal
|
|
658
687
|
- v2.6.4: Win10 icon fix, sidebar toggle fix
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
:: ============================================================================
|
|
3
|
+
:: YAKMESH Launcher - Quick Start
|
|
4
|
+
:: Opens dashboard in browser and starts the node
|
|
5
|
+
:: ============================================================================
|
|
6
|
+
|
|
7
|
+
title YAKMESH Node
|
|
8
|
+
|
|
9
|
+
:: Find Node.js
|
|
10
|
+
where node >nul 2>&1
|
|
11
|
+
if %errorlevel% neq 0 (
|
|
12
|
+
echo [ERROR] Node.js not found in PATH
|
|
13
|
+
echo Please install Node.js from https://nodejs.org/
|
|
14
|
+
pause
|
|
15
|
+
exit /b 1
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
:: Get script directory
|
|
19
|
+
set SCRIPT_DIR=%~dp0
|
|
20
|
+
set NODE_DIR=%SCRIPT_DIR%..
|
|
21
|
+
|
|
22
|
+
:: Check if server exists
|
|
23
|
+
if not exist "%NODE_DIR%\server\index.js" (
|
|
24
|
+
echo [ERROR] server/index.js not found
|
|
25
|
+
echo Expected at: %NODE_DIR%\server\index.js
|
|
26
|
+
pause
|
|
27
|
+
exit /b 1
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
:: Read port from config or use default
|
|
31
|
+
set HTTP_PORT=3789
|
|
32
|
+
if defined YAKMESH_HTTP_PORT set HTTP_PORT=%YAKMESH_HTTP_PORT%
|
|
33
|
+
|
|
34
|
+
echo.
|
|
35
|
+
echo ========================================================================
|
|
36
|
+
echo.
|
|
37
|
+
echo YY YY AA KK KK MM MM EEEE SSSS HH HH
|
|
38
|
+
echo YY YY AAAA KK KK MMM MMM EE SS HH HH
|
|
39
|
+
echo YYY AA AA KKKK MM M MM EEE SSS HHHHHHH
|
|
40
|
+
echo YY AAAAAA KK KK MM MM EE SS HH HH
|
|
41
|
+
echo YY AA AA KK KK MM MM EEEE SSSS HH HH
|
|
42
|
+
echo.
|
|
43
|
+
echo Post-Quantum Secure P2P Mesh Network
|
|
44
|
+
echo.
|
|
45
|
+
echo ========================================================================
|
|
46
|
+
echo.
|
|
47
|
+
echo [*] Starting YAKMESH node...
|
|
48
|
+
echo [*] Dashboard: http://localhost:%HTTP_PORT%/dashboard
|
|
49
|
+
echo [*] Press Ctrl+C to stop
|
|
50
|
+
echo.
|
|
51
|
+
|
|
52
|
+
:: Open dashboard in browser after short delay
|
|
53
|
+
start "" cmd /c "ping -n 3 127.0.0.1 >nul && start http://localhost:%HTTP_PORT%/dashboard"
|
|
54
|
+
|
|
55
|
+
:: Change to node directory and start
|
|
56
|
+
cd /d "%NODE_DIR%"
|
|
57
|
+
node server/index.js
|
|
58
|
+
|
|
59
|
+
:: If we get here, node exited
|
|
60
|
+
echo.
|
|
61
|
+
echo [!] Node stopped.
|
|
62
|
+
pause
|