Skip to content

Phase 05: Cryptography Layer

Implement the three cryptographic primitives that every other WPLM subsystem depends on: token signing, symmetric encryption, and device fingerprinting.

  • src/Crypto/Signer.php
  • src/Crypto/KeyVault.php
  • src/Crypto/Fingerprint.php

Signer produces and verifies Ed25519 signed tokens.

Token format:

base64url(json_payload) . "." . base64url(Ed25519_signature)

Where json_payload contains the license key hash, issued-at timestamp, expiry, and any claims the caller adds.

$token = $signer->sign([
'sub' => $license_key_hash,
'iat' => time(),
'exp' => $expires_at,
]);
$claims = $signer->verify($token); // returns array or null

Why Ed25519? Client software can embed only the 32-byte public key and verify tokens offline without contacting the licensing server. The private key never leaves the server.

Base64url helpersSigner::base64url_encode() and base64url_decode() use strtr() to map +/=-_ (RFC 4648 §5), making tokens URL-safe without padding issues.

Symmetric encryption for the license key value stored in the database.

Algorithm selectionsodium_crypto_aead_aes256gcm_is_available() is checked at runtime:

  • AES-256-GCM (hardware AES-NI): sodium_crypto_aead_aes256gcm_*
  • XChaCha20-Poly1305 (software fallback): sodium_crypto_aead_xchacha20poly1305_ietf_*

Both provide authenticated encryption (AEAD). The 24-byte nonce is prepended to the ciphertext; the whole blob is base64-encoded for safe text-column storage.

$encrypted = $vault->encrypt($plaintext_key);
$plaintext = $vault->decrypt($encrypted);

Key source — The AES key is loaded from wplm_aes_key option (generated by Seeder, stored unautoloaded).

Fingerprint converts raw device metadata into a stable, opaque identifier.

$hash = $fingerprint->hash($raw_device_string); // HMAC-SHA256 with wplm_hmac_secret
$hex = Fingerprint::sha256($string); // static plain SHA-256 helper

Why HMAC rather than plain SHA-256? The HMAC secret means an attacker who obtains fingerprint hashes from the database cannot reverse them into device identifiers or forge new ones without the secret.