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).
This commit is contained in:
Keysat
2026-06-12 17:51:40 -05:00
commit 843ff0e5d7
55 changed files with 6887 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
# 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`).
+207
View File
@@ -0,0 +1,207 @@
"""Produce LIC1-...-... keys the service would accept — used to verify the
SDK parsers round-trip correctly.
Emits two fixtures now: v1 (legacy fixed-74 payload) and v2 (variable-length
payload with expires_at + entitlements). SDKs must accept both.
Byte layout (matches licensing-service/src/crypto/mod.rs exactly):
v1 (74 bytes, fixed):
[0] version = 1
[1] flags
[2..18] product_id (UUID BE, 16 bytes)
[18..34] license_id (UUID BE, 16 bytes)
[34..42] issued_at (u64 BE, unix seconds)
[42..74] fingerprint_hash (SHA-256, zero if unbound)
v2 (83 bytes + variable entitlements):
[0] version = 2
[1] flags
[2..18] product_id
[18..34] license_id
[34..42] issued_at (u64 BE)
[42..50] expires_at (u64 BE, 0 = perpetual)
[50..82] fingerprint_hash (SHA-256, zero if unbound)
[82] num_entitlements (u8)
[83..] for each: [u8 len][len bytes of UTF-8 slug]
Signature: 64 bytes over the raw payload bytes.
Encoding: LIC1-<base32(payload)>-<base32(signature)>
RFC 4648 base32, uppercase, no padding.
"""
import base64
import hashlib
import json
import sys
import uuid
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.serialization import (
Encoding, PrivateFormat, PublicFormat, NoEncryption,
)
KEY_VERSION_V1 = 1
KEY_VERSION_V2 = 2
FLAG_FINGERPRINT_BOUND = 0b0000_0001
FLAG_TRIAL = 0b0000_0010
def b32nopad(b: bytes) -> str:
return base64.b32encode(b).decode("ascii").rstrip("=")
def make_payload_v1(
flags: int,
product_id: bytes, license_id: bytes,
issued_at: int, fp_hash: bytes,
) -> bytes:
assert len(product_id) == 16
assert len(license_id) == 16
assert len(fp_hash) == 32
payload = (
bytes([KEY_VERSION_V1, flags])
+ product_id
+ license_id
+ issued_at.to_bytes(8, "big")
+ fp_hash
)
assert len(payload) == 74, f"v1 payload is {len(payload)} bytes, expected 74"
return payload
def make_payload_v2(
flags: int,
product_id: bytes, license_id: bytes,
issued_at: int, expires_at: int,
fp_hash: bytes, entitlements: list[str],
) -> bytes:
assert len(product_id) == 16
assert len(license_id) == 16
assert len(fp_hash) == 32
assert 0 <= len(entitlements) <= 255
tail = bytearray()
for slug in entitlements:
encoded = slug.encode("utf-8")
assert len(encoded) <= 255, f"entitlement '{slug}' too long"
tail.append(len(encoded))
tail.extend(encoded)
head = (
bytes([KEY_VERSION_V2, flags])
+ product_id
+ license_id
+ issued_at.to_bytes(8, "big")
+ expires_at.to_bytes(8, "big")
+ fp_hash
+ bytes([len(entitlements)])
)
assert len(head) == 83
return head + bytes(tail)
def sign_and_encode(sk: Ed25519PrivateKey, payload: bytes) -> str:
sig = sk.sign(payload)
assert len(sig) == 64
return f"LIC1-{b32nopad(payload)}-{b32nopad(sig)}"
def main():
# Deterministic test vector — fixed seeds so the output is stable.
sk = Ed25519PrivateKey.from_private_bytes(bytes(range(32)))
pk = sk.public_key()
pub_pem = pk.public_bytes(
Encoding.PEM, PublicFormat.SubjectPublicKeyInfo
).decode()
product_id = uuid.UUID("6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0").bytes
license_id_v1 = uuid.UUID("11111111-2222-3333-4444-555555555555").bytes
license_id_v2 = uuid.UUID("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee").bytes
issued_at = 1_700_000_000
expires_at_v2 = 1_900_000_000 # ~2030
fingerprint_raw = "test-machine-fingerprint"
fp_hash = hashlib.sha256(fingerprint_raw.encode()).digest()
entitlements_v2 = ["pro", "multi-device"]
# v1: legacy fingerprint-bound key.
v1_payload = make_payload_v1(
FLAG_FINGERPRINT_BOUND,
product_id, license_id_v1, issued_at, fp_hash,
)
v1_key = sign_and_encode(sk, v1_payload)
# v2: trial + fingerprint-bound, with entitlements and expiry.
v2_flags = FLAG_FINGERPRINT_BOUND | FLAG_TRIAL
v2_payload = make_payload_v2(
v2_flags,
product_id, license_id_v2, issued_at, expires_at_v2,
fp_hash, entitlements_v2,
)
v2_key = sign_and_encode(sk, v2_payload)
# v2 perpetual, unbound, no entitlements — the "happy path" for a normal
# permanent license purchase.
v2_plain_payload = make_payload_v2(
0,
product_id, license_id_v2, issued_at, 0,
bytes(32), [],
)
v2_plain_key = sign_and_encode(sk, v2_plain_payload)
out = {
"publicKeyPem": pub_pem,
"v1": {
"licenseKey": v1_key,
"expected": {
"version": 1,
"productUuid": "6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0",
"licenseUuid": "11111111-2222-3333-4444-555555555555",
"issuedAt": issued_at,
"expiresAt": 0,
"flags": FLAG_FINGERPRINT_BOUND,
"isFingerprintBound": True,
"isTrial": False,
"entitlements": [],
"fingerprintRaw": fingerprint_raw,
"fingerprintHashHex": fp_hash.hex(),
},
},
"v2": {
"licenseKey": v2_key,
"expected": {
"version": 2,
"productUuid": "6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0",
"licenseUuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"issuedAt": issued_at,
"expiresAt": expires_at_v2,
"flags": v2_flags,
"isFingerprintBound": True,
"isTrial": True,
"entitlements": entitlements_v2,
"fingerprintRaw": fingerprint_raw,
"fingerprintHashHex": fp_hash.hex(),
},
},
"v2_perpetual_unbound": {
"licenseKey": v2_plain_key,
"expected": {
"version": 2,
"productUuid": "6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0",
"licenseUuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"issuedAt": issued_at,
"expiresAt": 0,
"flags": 0,
"isFingerprintBound": False,
"isTrial": False,
"entitlements": [],
"fingerprintRaw": None,
"fingerprintHashHex": "00" * 32,
},
},
}
json.dump(out, sys.stdout, indent=2)
print()
if __name__ == "__main__":
main()
+138
View File
@@ -0,0 +1,138 @@
import { readFileSync } from 'node:fs'
import {
Verifier,
PublicKey,
hashFingerprint,
parseLicenseKey,
isExpiredAt,
hasEntitlement,
} from '/sessions/hopeful-determined-edison/ts-sdk-build/dist/index.js'
const vector = JSON.parse(readFileSync(new URL('./vector.json', import.meta.url), 'utf8'))
let failures = 0
function check(name, cond, extra = '') {
if (cond) {
console.log(` OK ${name}`)
} else {
console.log(` FAIL ${name}${extra ? ': ' + extra : ''}`)
failures++
}
}
const toHex = (b) =>
Array.from(b).map((x) => x.toString(16).padStart(2, '0')).join('')
const verifier = new Verifier(PublicKey.fromPem(vector.publicKeyPem))
function runCase(label, caseData) {
console.log(`\n== ${label}: parseLicenseKey + verify ==`)
const expected = caseData.expected
const parsed = parseLicenseKey(caseData.licenseKey)
check(`${label}.version`, parsed.payload.version === expected.version,
`got ${parsed.payload.version}`)
check(`${label}.productUuid`, parsed.payload.productUuid === expected.productUuid,
`got ${parsed.payload.productUuid}`)
check(`${label}.licenseUuid`, parsed.payload.licenseUuid === expected.licenseUuid,
`got ${parsed.payload.licenseUuid}`)
check(`${label}.issuedAt`, parsed.payload.issuedAt === expected.issuedAt)
check(`${label}.expiresAt`, parsed.payload.expiresAt === expected.expiresAt,
`got ${parsed.payload.expiresAt}`)
check(`${label}.flags`, parsed.payload.flags === expected.flags,
`got ${parsed.payload.flags}`)
check(`${label}.isFingerprintBound`,
parsed.payload.isFingerprintBound === expected.isFingerprintBound)
check(`${label}.isTrial`, parsed.payload.isTrial === expected.isTrial)
check(
`${label}.entitlements`,
JSON.stringify(parsed.payload.entitlements) === JSON.stringify(expected.entitlements),
`got ${JSON.stringify(parsed.payload.entitlements)}`,
)
check(
`${label}.fingerprintHash`,
toHex(parsed.payload.fingerprintHash) === expected.fingerprintHashHex,
)
// Signed bytes length depends on version + entitlements. We just assert
// that it round-trips the signature check.
check(`${label}.signature size`, parsed.signature.length === 64)
try {
const v = verifier.verify(caseData.licenseKey)
check(`${label}.verify()`, true)
check(`${label}.verify productId`, v.productId === expected.productUuid)
check(`${label}.verify licenseId`, v.licenseId === expected.licenseUuid)
} catch (e) {
check(`${label}.verify()`, false, String(e))
}
if (expected.isFingerprintBound) {
try {
verifier.verifyWithFingerprint(caseData.licenseKey, expected.fingerprintRaw)
check(`${label}.verifyWithFingerprint correct`, true)
} catch (e) {
check(`${label}.verifyWithFingerprint correct`, false, String(e))
}
let rejectedWrong = false
try {
verifier.verifyWithFingerprint(caseData.licenseKey, 'wrong-fingerprint')
} catch (e) {
rejectedWrong = String(e).toLowerCase().includes('fingerprint')
}
check(`${label}.verifyWithFingerprint wrong`, rejectedWrong)
}
// Entitlement helper.
for (const slug of expected.entitlements) {
check(`${label}.hasEntitlement('${slug}')`, hasEntitlement(parsed.payload, slug))
}
check(`${label}.hasEntitlement('nonexistent')`,
!hasEntitlement(parsed.payload, 'definitely-not-a-real-slug'))
// Expiry helper.
if (expected.expiresAt > 0) {
check(`${label}.isExpiredAt(before)`, !isExpiredAt(parsed.payload, expected.expiresAt - 1))
check(`${label}.isExpiredAt(at)`, isExpiredAt(parsed.payload, expected.expiresAt))
check(`${label}.isExpiredAt(after)`, isExpiredAt(parsed.payload, expected.expiresAt + 1))
} else {
check(`${label}.perpetual never expires`,
!isExpiredAt(parsed.payload, 2_000_000_000))
}
// Tamper check — flip the last base32 character of the signature.
const orig = caseData.licenseKey
const lastChar = orig.slice(-1)
const flipped = lastChar === 'A' ? 'B' : 'A'
const tampered = orig.slice(0, -1) + flipped
let tamperRejected = false
try {
verifier.verify(tampered)
} catch {
tamperRejected = true
}
check(`${label}.tampered key rejected`, tamperRejected)
}
runCase('v1', vector.v1)
runCase('v2', vector.v2)
runCase('v2_perpetual_unbound', vector.v2_perpetual_unbound)
console.log('\n== hashFingerprint === Python SHA-256 ==')
check(
'sha256 matches',
toHex(hashFingerprint(vector.v1.expected.fingerprintRaw))
=== vector.v1.expected.fingerprintHashHex,
)
console.log('\n== pubkey loaded has correct length ==')
check(
'public key raw is 32 bytes',
PublicKey.fromPem(vector.publicKeyPem).raw.length === 32,
)
if (failures > 0) {
console.log(`\nFAIL: ${failures} check(s) failed`)
process.exit(1)
}
console.log('\nALL CHECKS PASSED')
+54
View File
@@ -0,0 +1,54 @@
{
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAA6EHv/POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg=\n-----END PUBLIC KEY-----\n",
"v1": {
"licenseKey": "LIC1-AEAW6RVE6YGS6SRIW2VD5D57N4UPAEIRCEISEIRTGNCEIVKVKVKVKVIAAAAAAZKT6EANGRDB75RRODPGGO22UJISZYXBLLASBMODEWWNVWTHYAXFSS5DWPI-FV56FI7ZTB5GIFQHIPQ35QVVE5AO5FQGVQS45UJ5F632MLXS7VHMHYVLZWGE64FJOEXD2PVIFNE5XGRMTNOUOVEKDTW736743W25MAY",
"expected": {
"version": 1,
"productUuid": "6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0",
"licenseUuid": "11111111-2222-3333-4444-555555555555",
"issuedAt": 1700000000,
"expiresAt": 0,
"flags": 1,
"isFingerprintBound": true,
"isTrial": false,
"entitlements": [],
"fingerprintRaw": "test-machine-fingerprint",
"fingerprintHashHex": "d34461ff63170de633b5aa2512ce2e15ac120b1c325acdada67c02e594ba3b3d"
}
},
"v2": {
"licenseKey": "LIC1-AIBW6RVE6YGS6SRIW2VD5D57N4UPBKVKVKVLXO6MZTO533XO53XO53QAAAAAAZKT6EAAAAAAABYT7MYA2NCGD73DC4G6MM5VVISRFTROCWWBECY4GJNM3LNGPQBOLFF2HM6QEA3QOJXQY3LVNR2GSLLEMV3GSY3F-QPSJIDYL6Y5TFCKXQ2SN43EDJIZIRJZCEROM2I4MJHODT6KO4KDPW6AJ3HMYJERYPD34CF2Z46PXPYFKSRZS7BDZKVKWE57UBJSTEBI",
"expected": {
"version": 2,
"productUuid": "6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0",
"licenseUuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"issuedAt": 1700000000,
"expiresAt": 1900000000,
"flags": 3,
"isFingerprintBound": true,
"isTrial": true,
"entitlements": [
"pro",
"multi-device"
],
"fingerprintRaw": "test-machine-fingerprint",
"fingerprintHashHex": "d34461ff63170de633b5aa2512ce2e15ac120b1c325acdada67c02e594ba3b3d"
}
},
"v2_perpetual_unbound": {
"licenseKey": "LIC1-AIAG6RVE6YGS6SRIW2VD5D57N4UPBKVKVKVLXO6MZTO533XO53XO53QAAAAAAZKT6EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-E4IT25ES5NBBQAXVAMZPLBDB5P2ILZL4RGKYUWEWLME5ZVGM7HGBG5CP3XHWBQ5FCYPEC6YGKBHCTQ7M7RZP7OR7NAYAMNAJAWW4QDQ",
"expected": {
"version": 2,
"productUuid": "6f46a4f6-0d2f-4a28-b6aa-3e8fbf6f28f0",
"licenseUuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"issuedAt": 1700000000,
"expiresAt": 0,
"flags": 0,
"isFingerprintBound": false,
"isTrial": false,
"entitlements": [],
"fingerprintRaw": null,
"fingerprintHashHex": "0000000000000000000000000000000000000000000000000000000000000000"
}
}
}