Phase 05: Cryptography Layer
Implement the three cryptographic primitives that every other WPLM subsystem depends on: token signing, symmetric encryption, and device fingerprinting.
Files Written
Section titled “Files Written”src/Crypto/Signer.phpsrc/Crypto/KeyVault.phpsrc/Crypto/Fingerprint.php
Signer
Section titled “Signer”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 nullWhy 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 helpers — Signer::base64url_encode() and base64url_decode() use strtr() to map +/= → -_ (RFC 4648 §5), making tokens URL-safe without padding issues.
KeyVault
Section titled “KeyVault”Symmetric encryption for the license key value stored in the database.
Algorithm selection — sodium_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
Section titled “Fingerprint”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 helperWhy 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.