Files
keysat-root/tests/crosscheck/README.md
T
Keysat 843ff0e5d7 Initial backup of root workspace files
Glue files not covered by subproject repos: top-level docs, logo,
keysat-design-system, and crosscheck tests. Subproject folders are
gitignored (each has its own Gitea remote).
2026-06-12 17:51:40 -05:00

71 lines
3.2 KiB
Markdown

# Format cross-check
Verifies that the three implementations of the `LIC1-...-...` key format
(licensing-service in Rust, licensing-client-rust SDK, licensing-client-ts SDK)
all agree, byte for byte, on **both** the legacy v1 payload layout and the
current v2 layout.
## Approach
1. `reference_signer.py` builds three license keys from scratch using the exact
byte layouts documented in `licensing-service/src/crypto/mod.rs`. It uses
Python's `cryptography` for Ed25519 signing — an independent implementation
from the Rust one, so agreement here is strong evidence the format is
correct, not just that the Rust side agrees with itself.
The three keys exercise every branch of the parser:
- **`v1`** — legacy fixed-74 payload, fingerprint-bound. New keys aren't
issued in v1 anymore, but SDKs must still accept them indefinitely so
old keys in the wild keep working.
- **`v2`** — trial key, fingerprint-bound, with explicit expiry and two
entitlements. Stresses the variable-length tail parser.
- **`v2_perpetual_unbound`** — the "happy path" for a normal paid purchase:
v2, no expiry, no fingerprint binding, no entitlements.
2. `run_ts.mjs` imports the built TypeScript SDK (`dist/index.js`) and runs
each of the three fixtures through: field-by-field parse, signature
verification, fingerprint binding (positive + negative), entitlement
lookup, `isExpiredAt` boundaries, and tamper detection. Also spot-checks
`hashFingerprint` against Python's `hashlib.sha256` and public-key loading.
## Rust SDK coverage
The Rust SDK uses the same crates as the service (`data_encoding::BASE32_NOPAD`,
`ed25519_dalek`) with identical byte offsets (`licensing-client-rust/src/key.rs`
mirrors `licensing-service/src/crypto/mod.rs`), so round-trip compatibility is
guaranteed by construction. If you change the layout, update the service's
`from_bytes`, the Rust SDK's `from_bytes`, and `reference_signer.py` together.
The Rust SDK's own unit tests (`cargo test -p licensing-client`) round-trip
every flag + version combination.
## Running
```bash
# Build the TS SDK first.
cd licensing-client-ts
npm install
npm run build
cd ../tests/crosscheck
python3 reference_signer.py > vector.json
node --experimental-vm-modules run_ts.mjs
```
## Current test vectors
Both vectors share a deterministic signing key seeded with `bytes(range(32))`,
so the license strings in `vector.json` are stable across regenerations (a
regression in encoding will produce a git diff).
| fixture | version | expires_at | entitlements | flags |
|------------------------|---------|-------------|------------------|-----------------------------------------|
| `v1` | 1 | (n/a) | (n/a) | `FINGERPRINT_BOUND` |
| `v2` | 2 | 1900000000 | `["pro","multi-device"]` | `FINGERPRINT_BOUND \| TRIAL` |
| `v2_perpetual_unbound` | 2 | 0 | `[]` | `0` |
Product UUID: `6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0`, fingerprint raw string
`"test-machine-fingerprint"` (SHA-256
`d34461ff63170de633b5aa2512ce2e15ac120b1c325acdada67c02e594ba3b3d`).