$ feature / signed-validation
Validation responses your app can trust.
A naive licensing flow is "ask the server, trust the answer." That's brittle. The user controls the network, the DNS, the proxy, and any patching tools they want to run. Anything the server returns can be intercepted, edited, and replayed. AuthForge signs every positive validation response with Ed25519, and your SDK verifies it locally with a public key embedded at build time. A network attacker can't forge a positive answer without our private key, which never leaves our infrastructure.
Why Ed25519
Ed25519 (RFC 8032) is a modern, audited, deterministic elliptic-curve signature scheme. Compared to RSA-PSS or ECDSA, it ships with three practical wins for licensing:
- Small payloads. Public keys are 32 bytes, signatures are 64 bytes. The license response stays under 1 KB even with metadata.
- Fast verification. A single verify on a modern machine is under a millisecond, which matters when you call it on every app launch.
- Side-channel resistant. Deterministic signing means there's no nonce-reuse footgun like the ones that have killed bad ECDSA implementations.
The flow
- Your SDK generates a per-request 128-bit nonce.
- SDK
POST /auth/validatewith{ license_key, hwid, nonce }. - AuthForge runs all checks (key valid, HWID slot available, no rate limit hit, no allow/deny block, sufficient credits).
- If everything passes, AuthForge serializes the result + the request nonce into a payload and signs it with the app's private key.
- Response:
{ valid: true, payload, signature, nonce }. - SDK runs
ed25519_verify(public_key, payload, signature)locally, assertsresponse.nonce == request.nonce, then unwraps the payload.
The public key lives in your dashboard under App settings → Security → Ed25519 public key, and you embed it as a constant in your build. Each app has its own keypair so a leak (in the unlikely event we ever rotated) would be scoped.
Verification, by SDK
The official SDKs handle verification automatically: you call
validate_license() and either get a result or an exception.
But the underlying verification primitive is small and you can drop down
to it if you want to write your own SDK or you're integrating from a
language we don't have a first-party SDK for.
Python
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
from cryptography.exceptions import InvalidSignature
def verify(public_key_bytes: bytes, payload: bytes, signature: bytes) -> bool:
try:
Ed25519PublicKey.from_public_bytes(public_key_bytes).verify(signature, payload)
return True
except InvalidSignature:
return False Node.js
import { verify, createPublicKey } from "node:crypto";
function verifyEd25519(publicKeyDer: Buffer, payload: Buffer, signature: Buffer): boolean {
const key = createPublicKey({ key: publicKeyDer, format: "der", type: "spki" });
return verify(null, payload, key, signature);
} Go
import "crypto/ed25519"
func Verify(publicKey ed25519.PublicKey, payload, signature []byte) bool {
return ed25519.Verify(publicKey, payload, signature)
} Rust
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
fn verify(public_key: &[u8; 32], payload: &[u8], signature: &[u8; 64]) -> bool {
let key = VerifyingKey::from_bytes(public_key).unwrap();
let sig = Signature::from_bytes(signature);
key.verify(payload, &sig).is_ok()
} C#
using NSec.Cryptography;
bool Verify(byte[] publicKeyBytes, byte[] payload, byte[] signature)
{
var algorithm = SignatureAlgorithm.Ed25519;
var key = PublicKey.Import(algorithm, publicKeyBytes, KeyBlobFormat.RawPublicKey);
return algorithm.Verify(key, payload, signature);
} C++
// Using libsodium
#include <sodium.h>
bool Verify(const unsigned char public_key[32],
const unsigned char* payload, size_t payload_len,
const unsigned char signature[64]) {
return crypto_sign_verify_detached(signature, payload, payload_len, public_key) == 0;
} Putting it together
Signed validation is one piece of the broader AuthForge security model . Combine it with hardware locking , rate limiting, and the self-ban flow, and you have layered defenses that don't rely on any single check holding up under attack.