Download Game! Currently 74 players and visitors. Last logged in:CelbornKandaharIberiamsspGunk

Blitzer's Blog >> 72185

Back to blogs index
Posted: 07 Sep 2026 14:15 [ permalink ]
To make cryptography work seamlessly across Node.js, Browsers, and embedded
engines like `mquickjs` without slowing down your game loop, we must navigate
a major architectural hurdle: **Asynchronous APIs**.

Modern browsers use `window.crypto.subtle`, but its methods return Promises.
If you try to verify a network packet asynchronously in a fast-paced game
loop, your CRDT state will instantly fall out of sync while waiting for the
Promise to resolve. Furthermore, lightweight engines like `mquickjs` do not
have native WebCrypto built-in.

The universal, high-performance solution is to use **Ed25519** (via a
pure-JavaScript implementation) rather than standard ECDSA.

Ed25519 is exceptionally fast, highly secure, and most importantly, it can be
executed synchronously. The industry standard library for this is
`tweetnacl-js`. It has zero dependencies, is heavily audited, and runs
flawlessly in Node, Browsers, and QuickJS.

Here is how you implement this cryptographic layer across your mesh.

### 1. The Cross-Platform Adapter

First, install the library (`npm install tweetnacl @noble/hashes` or include
the minified script in your browser/mquickjs environment).

We will create a lightweight `CryptoAdapter` that serializes the payload,
signs it, and verifies it synchronously.

```javascript
/ CryptoAdapter.js
const nacl = require('tweetnacl');
const { utf8ToBytes } = require('./utils'); // Simple string-to-Uint8Array
converter

class CryptoAdapter {
    constructor(publicKey, privateKey = null) {
        // Keys must be Uint8Arrays
        this.publicKey = publicKey; 
        this.privateKey = privateKey;
    }

    /** Called ONLY by the GM Daemon */
    signEvent(event) {
        if (!this.privateKey) throw new Error("Missing Private Key");
        
        // Convert the deterministically ordered payload to bytes
        const messageBytes = utf8ToBytes(JSON.stringify(event.payload));
        
        // Generate a detached signature (just the signature bytes)
        const signatureBytes = nacl.sign.detached(messageBytes,
this.privateKey);
        
        // Attach it to the network event as a base64 or hex string
        event.signature = Buffer.from(signatureBytes).toString('base64');
        return event;
    }

    /** Called synchronously by all clients in the game loop */
    verifyEvent(event) {
        if (!event.signature) return false;

        const messageBytes = utf8ToBytes(JSON.stringify(event.payload));
        const signatureBytes = Buffer.from(event.signature, 'base64');

        // Returns true if valid, false if tampered/fake
        return nacl.sign.detached.verify(messageBytes, signatureBytes,
this.publicKey);
    }
}

```

### 2. The GM Daemon Implementation

On your secure Node.js server, the GM Daemon holds both the private and public
keys. When resolving a high-stakes auction, it signs the state change before
broadcasting.

```javascript
/ GM_Daemon.js
const gmKeys = nacl.sign.keyPair(); // Save this privately in production!
const cryptoAuth = new CryptoAdapter(gmKeys.publicKey, gmKeys.secretKey);

function resolveAuction(winnerId, item, price) {
    const rawEvent = {
        type: 'VFS_WRITE',
        path: '/mud/rooms/auction_house/item_sold.json',
        payload: { winner: winnerId, item: item, gold_deducted: price }
    };

    // The GM securely signs the packet
    const signedEvent = cryptoAuth.signEvent(rawEvent);
    
    // Broadcast to the dmz_relay
    meshCRDT.socket.send(JSON.stringify(signedEvent));
}

```

### 3. The Client-Side Filter

In the Browser or `mquickjs` client, you hardcode the GM's Public Key. You
intercept high-stakes packets right before they hit the CRDT state and perform
a synchronous validation.

```javascript
/ Client_Engine.js
const gmPublicKey = new Uint8Array([...]); // Hardcoded known GM key
const cryptoVerify = new CryptoAdapter(gmPublicKey);

meshCRDT.on('message', (event) => {
    // Check if this path requires GM authority
    if (event.path.includes('/auction_house/')) {
        
        const isValid = cryptoVerify.verifyEvent(event);
        
        if (!isValid) {
            console.warn("[SECURITY] Rejected forged authoritative packet.");
            return; // Drop the packet entirely
        }
    }

    // Packet is verified! Apply to local state.
    applyToGameState(event);
});

```

By keeping the signature detached and verifying synchronously with Ed25519,
your MUD remains cheat-proof without dropping a single frame of rendering.