JHILKE झिल्के
Just Hidden In-band Legitimate Key Exchange
Deterministic bootstrap key derivation and continuous friend-or-foe peer verification for the Yakmesh mesh.
v3.0The Sound of Crickets
In Nepali, झिल्के (jhilke) describes the chirping of crickets in the Himalayan night — a chorus only those who belong can hear. Outsiders perceive noise; insiders hear signals.
Like the D-Day cricket clickers, where Allied paratroopers used a simple click-clack pattern to identify friend from foe in darkness. Like the Navajo codetalkers whose language was unbreakable because it was meaningful only to those who grew up with it.
JHILKE hides its peer verification signals inside ordinary mesh entropy traffic. To an observer, it's noise. To nodes sharing the same codebase and build — it's a conversation.
Why Fireflies?
Fireflies (Lampyridae) are nature's original steganographers. Each species flashes a unique pattern — a species-specific dialect that only potential mates of the same species can decode. To every other creature in the meadow, it's just random light. Sound familiar?
JHILKE nodes do exactly what fireflies do: they embed signals in the noise of the night. The "dialect" is derived from the shared codebase hash + per-build nonce. Same code, same build = same species = you understand the flash pattern. Different code or different build = different species = it's just entropy.
Real fireflies are disappearing worldwide due to light pollution, habitat loss, and pesticides. At least 2,000 species exist, with some already critically endangered. If you see fireflies near your home, consider yourself lucky — and keep the lights low for them.
Overview
JHILKE provides two critical functions for the Yakmesh mesh:
Deterministic Bootstrap
Both nodes independently derive the same initial symmetric key
from SHA3(codeHash + buildNonce) via HKDF. Traffic is encrypted from message #1 —
ANNEX has a key before any wire traffic flows.
Friend-or-Foe Verification
Continuous 8-byte peer integrity chirps every 30 seconds, hidden in
mesh_entropy messages. Only nodes with the same codebase AND build nonce can produce
or verify chirps. JHILKE emits events; KARMA handles consequences.
ACT State Machine
AGUWA Coordinated Transition using TRIBHUJ trits: PREPARE (+1) → READY (0) → SWITCH (−1). Execution waits for AGUWA epoch boundary with order parameter r ≥ 0.2 before any transition fires.
SST Modulation
Every chirp's HKDF context includes a Fibonacci 24-cycle
digital root (fibonacciRoot(tick % 24)), adding rotational variety that
prevents pattern analysis across tick boundaries.
Initialization
JHILKE is initialized from mesh/network.js with four parameters:
import { JhilkeCoordinator } from './mesh/jhilke.js';
const jhilke = new JhilkeCoordinator({
codeHash: oracle.selfHash, // Validation Oracle code hash (hex string)
nodeId: identity.nodeId, // This node's identity
mesh: meshInstance, // MeshNetwork (provides sendTo + peers Map)
buildNonce: manifest.nonce, // Per-build secret from manifest.json
});
jhilke.start(); // Begin 30-second chirp loop
buildNonce comes from manifest.json,
generated at build time. It makes both the bootstrap key and the chirp dialect
per-build secrets — an attacker with only the source code cannot derive them.
They need the manifest from a specific build.
Deterministic Bootstrap
When two nodes connect, they both independently compute the same initial 256-bit symmetric key. No KEM exchange needed — traffic is encrypted from the very first message:
deriveBootstrapKey(peerId) {
// Step 1: Input Key Material — per-build secret
const ikm = sha3_256.create()
.update(hexToBytes(this.codeHash))
.update(utf8ToBytes(this.buildNonce || ''))
.digest();
// Step 2: Sort node IDs for order-independence
const [first, second] = [this.nodeId, peerId].sort();
// Step 3: HKDF derivation
const salt = `YAKMESH-JHILKE-BOOTSTRAP-2026:${first}:${second}`;
const info = 'yakmesh-jhilke-bootstrap-key-v1';
const key = hkdf(sha3_256, ikm, salt, info, 32);
return Buffer.from(key); // 32-byte (256-bit) symmetric key
}
Bootstrap Key Properties
- Order-independent: Node IDs are sorted before hashing — A→B and B→A produce the same key.
- Per-build secret: IKM =
SHA3(codeHash + buildNonce)— not derivable from source code alone. - Deterministic: Same code hash + same build nonce + same node pair = identical key on both sides.
- JHILKE's only key: This is the one key JHILKE derives. What ANNEX does with it after (KEM upgrade, rekey) is ANNEX's business — JHILKE doesn't know or care.
What JHILKE Provides
JHILKE touches exactly three things in the connection lifecycle. Everything else is ANNEX's job:
-
1
Bootstrap Key (on connect) — JHILKE derives a deterministic 256-bit key from
SHA3(codeHash + buildNonce)and hands it to ANNEX. This is the only key JHILKE ever produces. What ANNEX does with it — encrypt, KEM upgrade, whatever — is not JHILKE's concern. -
2
Continuous Chirps (every 30s) — Friend-or-foe verification via
mesh_entropymessages. JHILKE emitschirp:verifiedorchirp:failedevents. It does not act on failures — KARMA handles consequences. -
3
ACT Coordination (on demand) — When a coordinated transition is needed, JHILKE's ACT state machine coordinates timing across peers. Execution fires at an AGUWA epoch boundary with r ≥ 0.2. What happens at execution is up to the caller — JHILKE just emits
act:execute.
Cricket Chirps — Friend-or-Foe
Every 30 seconds (matching the gossip HELLO cadence), each node sends a friend-or-foe
chirp to every connected peer. Chirps are hidden inside normal mesh_entropy
messages:
// What an observer sees on the wire:
{
type: 'mesh_entropy',
entropy: 'a7f3b2c1...', // 32 bytes genuine PRAHARI sponge entropy
jhilke: '8e4d1f2a...', // 8-byte friend-or-foe chirp
pad: 'c3d2e1f0...', // 16–64 bytes PRAHARI random padding
t: 1741564800000 // AGUWA-synchronized timestamp
}
// To an observer: routine entropy exchange. Nothing unusual.
// To nodes sharing the dialect: continuous peer verification.
Dialect Derivation
The "dialect" is the shared secret that makes chirp encoding/verification possible.
It's derived from the same SHA3(codeHash + buildNonce) IKM as the bootstrap
key, but with different salt and info strings — producing a completely independent seed:
_deriveDialectSeed() {
const ikm = sha3_256.create()
.update(hexToBytes(this.codeHash))
.update(utf8ToBytes(this.buildNonce || ''))
.digest();
return hkdf(sha3_256, ikm,
'jhilke-cricket-salt-2026', // Salt (different from bootstrap)
'yakmesh-jhilke-dialect-v1', // Info (different from bootstrap)
32); // 256-bit dialect seed
}
Chirp Generation
Each chirp is an 8-byte HKDF output encoding both node IDs, the current AGUWA tick, and the SST Fibonacci 24-cycle position for rotational variety:
_generateChirp(peerId, tick) {
const [first, second] = [this.nodeId, peerId].sort();
// SST modulation — Fibonacci digital root at this tick position
const fibPos = tick % 24;
const fibRoot = fibonacciRoot(fibPos);
const context = `${first}:${second}:${tick}:${fibPos}:${fibRoot}`;
return hkdf(sha3_256, this.dialectSeed, context,
'jhilke-signal-v1', 8); // 8-byte chirp
}
Chirp Verification
Verification uses dynamic tick tolerance computed from three sources. This accounts for GPS precision differences AND actual system clock drift:
_verifyChirp(peerId, signalBytes, currentTick) {
// Source 1: MANI trust-level tolerance (peer's time source precision)
const maniToleranceMs = aguwa.getToleranceForPeer(peerId);
// Source 2: Clock drift — our correctionMs + peer margin + propagation
const driftToleranceMs = Math.abs(aguwa._correctionMs) + 2000;
// Use the larger of MANI precision vs actual drift
const toleranceMs = Math.max(maniToleranceMs, driftToleranceMs);
const dynamicTicks = Math.ceil(toleranceMs / 1000);
const tolerance = Math.max(1, dynamicTicks); // ±1 tick floor
for (let offset = -tolerance; offset <= tolerance; offset++) {
const testTick = currentTick + offset;
if (testTick < 0) continue;
const expected = this._generateChirp(peerId, testTick);
if (bytesToHex(expected) === bytesToHex(signalBytes)) {
return { valid: true, tick: testTick, offset };
}
}
return { valid: false };
}
correctionMs-based drift term accounts for the actual clock offset
that the oscillator is still correcting. The ±1 static floor provides a minimum safety margin.
Wire Format
Chirps are transmitted via _sendChirp(), which constructs a complete
mesh_entropy message with genuine entropy, the hidden chirp, and variable
camouflage padding:
_sendChirp(peerId) {
const chirp = this._generateChirp(peerId, this._sharedTick());
// Variable padding from PRAHARI sponge (16–64 bytes)
const paddingSize = 16 + (seedStore.squeeze(4, 'JHILKE-PADDING-SIZE')
.readUInt32BE(0) % 48);
const padding = seedStore.squeeze(paddingSize, 'JHILKE-PADDING');
this.mesh.sendTo(peerId, {
type: 'mesh_entropy',
entropy: bytesToHex(seedStore.squeeze(32, 'JHILKE-ENTROPY')),
jhilke: bytesToHex(chirp),
pad: bytesToHex(padding),
t: aguwa.now(),
});
}
| Field | Size | Source | Purpose |
|---|---|---|---|
| entropy | 32 bytes | PRAHARI sponge | Genuine entropy contribution to mesh pool |
| jhilke | 8 bytes | HKDF(dialect + context) | Friend-or-foe verification chirp |
| pad | 16–64 bytes | PRAHARI sponge | Variable camouflage (prevents size fingerprinting) |
| t | number | AGUWA | GPS-synchronized timestamp |
ACT — AGUWA Coordinated Transition
When a coordinated transition is needed, JHILKE runs the ACT state machine. ACT uses TRIBHUJ trits and is driven on the same 30-second chirp cadence. All transitions are driven by internal state only — never external signals.
| State | Trit | Meaning | Duration |
|---|---|---|---|
| PREPARE | +1 (POSITIVE) | Node has consented. Waiting for actPrepareMinTicks. |
≥ 3 ticks (≥ 90s) |
| READY | 0 (NEUTRAL) | Minimum prepare elapsed. Waiting for all peers to reach READY. | Until all peers READY |
| SWITCH | −1 (NEGATIVE) | All peers ready. Counting down to epoch boundary execution. | ≥ 2 ticks (≥ 60s), then r ≥ 0.2 |
| EXECUTING | terminal | Epoch boundary reached. act:execute event emitted. |
Instant (cleanup follows) |
ACT State Flow (30-second cadence)
Node A Node B
────── ──────
idle idle
│ │
├── beginACT(targetEpoch) ──────── ┤
│ │
PREPARE (+1) PREPARE (+1)
│ (broadcast via gossip) │
│ ≥ 3 ticks (≥ 90 seconds) │
│ │
READY (0) READY (0)
│ ◀── peer state check ──▶ │
│ │
│ (all peers in READY) │
│ │
SWITCH (−1) SWITCH (−1)
│ ≥ 2 ticks, AGUWA r ≥ 0.2 │
│ wait for epoch boundary │
│ │
EXECUTING ── act:execute ──────▶ EXECUTING
│ │
idle (transition complete) idle
getCurrentEpoch() >= targetEpoch — the target epoch boundary has arrived.
If either condition fails, execution is deferred to the next 30-second tick.
Dependencies
AGUWA
aguwa.tick() provides the GPS-synchronized wall-clock
second used for chirp encoding. aguwa.orderParameter() gates ACT execution.
aguwa.getToleranceForPeer() provides MANI precision for dynamic verification tolerance.
PRAHARI
seedStore.squeeze() provides genuine sponge entropy
for the entropy field (32 bytes), variable padding (16–64 bytes),
and padding size selection. All entropy is real, not filler.
SST
fibonacciRoot(tick % 24) from oracle/sst.js
provides the 24-cycle digital root that modulates chirp context, preventing pattern repetition
across tick boundaries.
KARMA
JHILKE emits chirp:verified and chirp:failed
events but takes no punitive action. KARMA evaluates
consecutiveFailures and manages peer reputation consequences.
Configuration Constants
All constants live in JHILKE_CONFIG (exported for testing):
| Constant | Value | Purpose |
|---|---|---|
| bootstrapSalt | 'YAKMESH-JHILKE-BOOTSTRAP-2026' |
HKDF salt prefix for bootstrap key derivation |
| bootstrapInfo | 'yakmesh-jhilke-bootstrap-key-v1' |
HKDF info for bootstrap key derivation |
| dialectSalt | 'jhilke-cricket-salt-2026' |
HKDF salt for dialect seed derivation |
| dialectInfo | 'yakmesh-jhilke-dialect-v1' |
HKDF info for dialect seed derivation |
| signalInfo | 'jhilke-signal-v1' |
HKDF info for individual chirp generation |
| signalSize | 8 bytes | HKDF output length per chirp |
| paddingMin / paddingMax | 16 / 64 bytes | Variable camouflage padding range |
| chirpInterval | 30,000 ms | Chirp transmission cadence (matches gossip HELLO) |
| tickTolerance | ±1 tick | Static floor for chirp verification tolerance |
| actPrepareMinTicks | 3 (≥ 90s) | Minimum ticks in PREPARE before advancing to READY |
| actSwitchDelayTicks | 2 (≥ 60s) | Minimum ticks in SWITCH before executing |
API Reference
jhilke.deriveBootstrapKey(peerId) → Buffer
Derives a deterministic 32-byte bootstrap encryption key for a peer.
Both nodes compute the same key independently from SHA3(codeHash + buildNonce).
| peerId | string | The remote peer's node ID |
jhilke.start() /
jhilke.stop()
start() begins the 30-second chirp loop, sending
friend-or-foe verification chirps to all connected peers. stop() halts the loop,
cleans up ACT timers, and clears all peer state.
jhilke.handleIncoming(fromPeerId, message)
Processes an incoming mesh_entropy message.
If the message contains a jhilke field, it verifies the chirp and emits
chirp:verified or chirp:failed. Messages without chirps are ignored.
| fromPeerId | string | Sender's node ID |
| message | object | The mesh_entropy message object |
jhilke.beginACT(targetEpoch, epochBufferN = 2)
Initiates the ACT state machine for a coordinated transition. Enters PREPARE phase with a 30-second tick cadence. Ignored if ACT is already in progress.
| targetEpoch | number | The AGUWA epoch at which to execute |
| epochBufferN | number | Dynamic epoch buffer from propagation model (default: 2) |
jhilke.handleACTState(peerId, data)
Receives a peer's ACT state announcement (broadcast via gossip).
Ignored if this node is not participating in ACT or if targetEpoch doesn't match.
Triggers _checkAllReady() when in READY state.
| peerId | string | Sender's node ID |
| data | object | { state: 'PREPARE'|'READY'|'SWITCH', targetEpoch } |
jhilke.getACTState() → Object | null
Returns current ACT state machine status for diagnostics.
Returns null if no ACT is in progress.
{
state: 'READY', // Current phase
targetEpoch: 42, // Target epoch
prepareTicks: 3, // Ticks spent in PREPARE
switchTicks: 0, // Ticks spent in SWITCH
peerStates: { // Tracked peer states
'abc123...': 'READY',
'def456...': 'PREPARE'
}
}
jhilke.getStats() → Object
Returns operational statistics.
{
bootstrapKeysDerived: 3,
chirpsSent: 142,
chirpsReceived: 138,
chirpsVerified: 135,
chirpsFailed: 3,
peerCount: 2
}
jhilke.cleanupPeer(peerId)
Removes all tracked state for a disconnected peer. Called by the mesh when a peer connection is lost.
Event Emissions
JhilkeCoordinator extends EventEmitter. It emits soft intelligence
signals — it does NOT take punitive action. KARMA handles consequences:
| Event | Trigger | Payload |
|---|---|---|
| chirp:verified | Incoming chirp validates (friend) | { peerId, tick, offset } |
| chirp:failed | Incoming chirp fails verification (foe?) | { peerId, consecutiveFailures } |
| act:state | ACT state transition or broadcast tick | { state, targetEpoch } |
| act:execute | Epoch boundary reached + r ≥ 0.2 | { targetEpoch } |
Security Properties
- • Zero plaintext first message — The bootstrap key (derived from code hash + build nonce) gives ANNEX a symmetric key before any traffic flows. The very first message on the wire is encrypted.
-
•
Build isolation — The
buildNoncefrommanifest.jsonmakes both the bootstrap key and the chirp dialect per-build secrets. Source code alone is insufficient to derive either one. - • Codebase-bound dialect — Only nodes with identical code hash + identical build nonce (verified by the Validation Oracle) can produce or verify chirps. Fork the code → different dialect.
- • Internal-state-driven transitions — ACT state transitions are driven purely by internal state and timers; never by external signals. This prevents remote reset attacks.
-
•
Traffic analysis resistance — Chirps blend into normal
mesh_entropytraffic at the same 30-second gossip cadence. PRAHARI-sourced variable padding (16–64 bytes) prevents size fingerprinting. - • AGUWA epoch synchronization — ACT executes only at GPS-synchronized epoch boundaries with order parameter r ≥ 0.2. No node acts unilaterally.
Relationship to ANNEX
JHILKE and ANNEX are deliberately separate modules with clean separation of concerns:
| Responsibility | ANNEX | JHILKE |
|---|---|---|
| Symmetric encryption | AES-256-GCM encrypt/decrypt | — |
| Initial key derivation | Uses key from JHILKE | HKDF(SHA3(codeHash + buildNonce)) |
| KEM exchange | ML-KEM-768 encap/decap | — |
| Transition coordination | — | ACT state machine (AGUWA-gated) |
| Peer verification | — | Friend-or-foe chirps (30s) |
| Message signing | ML-DSA-65 sign/verify | — |
What JHILKE Is NOT
- ✕ Not a key exchange protocol. It's deterministic bootstrap + coordination. ANNEX handles actual ML-KEM-768 key exchange.
- ✕ Not a trust model. KARMA evaluates chirp failures and manages peer reputation. JHILKE just emits events.
- ✕ Not an encryption cipher. ANNEX handles AES-256-GCM encryption. JHILKE coordinates transition timing and verifies peer identity — KARMA handles trust.
-
✕
Not a failover handler. Lost or failed chirps increment
consecutiveFailures— KARMA decides the consequences.
JHILKE is the cricket chorus conductor — it orchestrates when and how all nodes synchronize to the same cryptographic state, continuously verifies that peers belong to the same swarm, and provides ANNEX with the foundation for encrypted communication from the very first message.