Implement offline license verification (T-502)

This commit is contained in:
ila
2026-07-20 01:29:40 +08:00
parent c51ff30c54
commit cd76f7f900
12 changed files with 887 additions and 239 deletions
+7
View File
@@ -0,0 +1,7 @@
# License v1 test corpus
`license-v1-vectors.json` contains only fake machine hashes/products, a test
public key, signed valid and invalid-shape documents, and the corresponding
valid canonical signing bytes. It contains no private key, production key, real
license ID, or real machine identifier. The static bytes are a
cross-implementation contract for License v1 signing.
+44
View File
@@ -0,0 +1,44 @@
{
"schema_version": 1,
"public_key_base64": "jl6xuV51N8SYjwr+7DReGnSHVXTG6PZYg/5aayoM2fA=",
"vectors": [
{
"name": "valid",
"document": "{\"issued_at\":\"2026-07-20T01:02:03Z\",\"license_id\":\"lic-test-20260720\",\"machine_hash\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"perpetual\":true,\"products\":[\"product-json-parser\",\"toolkit\"],\"rebind_policy\":\"self-service-1-per-90d\",\"schema_version\":1,\"signature\":\"JScvchl2W5O49yzNywlE5dhDI46Mb+VeIMdtud1pXj2T3IdzEbUimk3gRsw4ZKiPffTMaGJoPfuGSCR0pHT5Dw==\",\"update_policy\":\"updates-until-2027-12-31\"}",
"signed_payload_base64": "eyJpc3N1ZWRfYXQiOiIyMDI2LTA3LTIwVDAxOjAyOjAzWiIsImxpY2Vuc2VfaWQiOiJsaWMtdGVzdC0yMDI2MDcyMCIsIm1hY2hpbmVfaGFzaCI6IjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYiLCJwZXJwZXR1YWwiOnRydWUsInByb2R1Y3RzIjpbInByb2R1Y3QtanNvbi1wYXJzZXIiLCJ0b29sa2l0Il0sInJlYmluZF9wb2xpY3kiOiJzZWxmLXNlcnZpY2UtMS1wZXItOTBkIiwic2NoZW1hX3ZlcnNpb24iOjEsInVwZGF0ZV9wb2xpY3kiOiJ1cGRhdGVzLXVudGlsLTIwMjctMTItMzEifQ==",
"signature": "JScvchl2W5O49yzNywlE5dhDI46Mb+VeIMdtud1pXj2T3IdzEbUimk3gRsw4ZKiPffTMaGJoPfuGSCR0pHT5Dw==",
"expected_machine_hash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"expected_products": ["product-json-parser", "toolkit"]
},
{
"name": "unknown-field",
"document": "{\"extra\":true,\"issued_at\":\"2026-07-20T01:02:03Z\",\"license_id\":\"lic-test-20260720\",\"machine_hash\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"perpetual\":true,\"products\":[\"product-json-parser\",\"toolkit\"],\"rebind_policy\":\"self-service-1-per-90d\",\"schema_version\":1,\"signature\":\"QB4a4DvrGQeEI8tUti4gNTKvtdSb9SxlZjKdKCnv7VGq/CqqTWqHw7bb5SGguum+ueXymTmOkO24VdodTRmNDQ==\",\"update_policy\":\"updates-until-2027-12-31\"}",
"want_error": "invalid_license"
},
{
"name": "missing-perpetual",
"document": "{\"issued_at\":\"2026-07-20T01:02:03Z\",\"license_id\":\"lic-test-20260720\",\"machine_hash\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"products\":[\"product-json-parser\",\"toolkit\"],\"rebind_policy\":\"self-service-1-per-90d\",\"schema_version\":1,\"signature\":\"ByawlRJ6CWuELm7uYdFfzUWEgw5N2LuFNGIV1qzJejnOZ5C7yOqUBwl2JG0iw9umk5f/0blboWTlkg6x8DHDDA==\",\"update_policy\":\"updates-until-2027-12-31\"}",
"want_error": "invalid_license"
},
{
"name": "null-perpetual",
"document": "{\"issued_at\":\"2026-07-20T01:02:03Z\",\"license_id\":\"lic-test-20260720\",\"machine_hash\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"perpetual\":null,\"products\":[\"product-json-parser\",\"toolkit\"],\"rebind_policy\":\"self-service-1-per-90d\",\"schema_version\":1,\"signature\":\"HKVyEX5o/gzRpJk3TAqhp7sBf9+qjJvhfZk4zavWLrBzwY+ZgCW15XuMSh7ZwvXtnh23mFyssJvQgBPHOzIuCQ==\",\"update_policy\":\"updates-until-2027-12-31\"}",
"want_error": "invalid_license"
},
{
"name": "duplicate-product",
"document": "{\"issued_at\":\"2026-07-20T01:02:03Z\",\"license_id\":\"lic-test-20260720\",\"machine_hash\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"perpetual\":true,\"products\":[\"product-json-parser\",\"product-json-parser\"],\"rebind_policy\":\"self-service-1-per-90d\",\"schema_version\":1,\"signature\":\"UqtzJ6FnVkfCsrJanRzdUnVsFEgH7qRpoTlJgNhF4ZWu8L46so9hvUfskhc560AkADb1xvKi8Ih8cxrlApVbAg==\",\"update_policy\":\"updates-until-2027-12-31\"}",
"want_error": "invalid_license"
},
{
"name": "invalid-timestamp",
"document": "{\"issued_at\":\"2026-07-20T01:02:03+00:00\",\"license_id\":\"lic-test-20260720\",\"machine_hash\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"perpetual\":true,\"products\":[\"product-json-parser\",\"toolkit\"],\"rebind_policy\":\"self-service-1-per-90d\",\"schema_version\":1,\"signature\":\"ZthYd0W9WpFJJ+Fe7m43BkJ6rdwVn+ZbV0skBAFLvVPbDDCSzuYBA0Kpa581s41uE+zgtsdWqnk6X894hDPBAQ==\",\"update_policy\":\"updates-until-2027-12-31\"}",
"want_error": "invalid_license"
},
{
"name": "uppercase-machine-hash",
"document": "{\"issued_at\":\"2026-07-20T01:02:03Z\",\"license_id\":\"lic-test-20260720\",\"machine_hash\":\"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\",\"perpetual\":true,\"products\":[\"product-json-parser\",\"toolkit\"],\"rebind_policy\":\"self-service-1-per-90d\",\"schema_version\":1,\"signature\":\"h4en9HN21gcXuHQ4nEW00kwfHXcagkIqW+O8FWpR2H1WVzfHkm0Lj34YJySgGRVeslSR/3Yzy9ualeJtkA/kBA==\",\"update_policy\":\"updates-until-2027-12-31\"}",
"want_error": "invalid_license"
}
]
}