Choose a complete language example, verify every public test vector, then implement the separate license access checks.
What you will learn
- Select a verifier for your runtime.
- Build full source with pinned dependencies.
- Distinguish standalone verification from official SDK behavior.
Prerequisites
- Read signed responses.
- Have a trusted public key and the original UTF-8 envelope.
- Install the runtime described on the selected language page.
Choose your language
| Language | Runtime / dependencies | Complete example |
|---|---|---|
| Python | Python 3.9+; cryptography 46.0.3 | Python source and commands |
| PHP | PHP 8.2+ with ext-sodium; no Composer dependency | PHP source and commands |
| JavaScript | Node.js 22+; built-in crypto; no npm dependency | JavaScript source and commands |
| TypeScript | Node.js 22+; TypeScript 7.0.2; @types/node 22.19.7 | TypeScript source and commands |
| C# | .NET 7+; BouncyCastle.Cryptography 2.7.0 | C# source and commands |
| Java | JDK 17+; Gson 2.14.0; Bouncy Castle 1.86 | Java source and commands |
| Kotlin | Kotlin compiler 2.4.21; JDK 17+; Gson 2.14.0; Bouncy Castle 1.86 | Kotlin source and commands |
| Swift | Swift 6+; macOS 13+; built-in CryptoKit | Swift source and commands |
| Go | Go 1.22+; standard library only | Go source and commands |
| Rust | Rust 1.81+; exact dependencies in Cargo.toml and included Cargo.lock | Rust source and commands |
| Ruby | Ruby 2.6+; libsodium 1.0.20; standard Ruby Fiddle/JSON | Ruby source and commands |
| Dart | Dart 3.7+; cryptography 2.9.0 | Dart source and commands |
| C | C11 compiler; yyjson 0.13.0; libsodium 1.0.20 | C source and commands |
| C++ | C++17 compiler; yyjson 0.13.0; libsodium 1.0.20 | C++ source and commands |
Download and run
- Download the complete source archive.
- Extract it and open a terminal in its security directory.
- Build the selected language using its full instructions.
- Run the positive, tampered and expired commands.
- Run selftest.py with that language's command to verify all 23 cases.
Expected result: PASS23. Every language was executed on macOS against the same23 cases,322 checks in total. These tests cover authenticity and malformed-input refusal, not native Windows/Linux packaging or a complete license policy.
What the samples preserve
Numeric tokens remain in their original server form, including 19.0, large integers and PHP exponent notation. Object names sort by UTF-8 bytes; Unicode strings are not normalized. Duplicate keys, invalid Unicode, trailing content, unsupported algorithms, bad key IDs, malformed signatures and excessive depth fail closed.
The trusted key is a separate input. Do not extract a public key from an envelope and treat it as trusted. The programs return signature_valid only; a cryptographically valid expired vector is still not usable.
Current SDK limitations
These independent examples do not change the official SDKs. The current JavaScript SDK can lose integral-float markers. C# can fail after escaped-Unicode cache serialization. Python can reject valid signatures containing Unicode separators or PHP exponent spellings. Numeric feature helpers in all SDKs require an explicit valid-result guard. Test your exact payloads and cache round trips before a release; do not disable signature verification to work around a discrepancy.
The four official SDKs still provide activation, binding and offline-policy behavior that these small verifiers intentionally do not implement. A custom client needs the complete signed-response checks and offline policy, not just this cryptographic function.
Expected result
Every selected verifier returns the documented result for all 23 vectors. Actual license permission remains a separate decision.
Common mistakes
- Unlocking on signature_valid alone.
- Shipping the synthetic vector key as a production key.
- Calling a standalone verifier an official SDK or silently replacing SDK internals.
Security notes
Keep dependencies pinned and review updates. Do not pass raw customer envelopes or tokens to public debugging services. The sample archive contains only public synthetic values.
Troubleshooting
| Symptom | Cause | Action |
|---|---|---|
| Shared runner fails | Runtime, source or canonical bytes differ | Read the failing vector name; rebuild exact source |
| Signature works but SDK fails | Different SDK canonical/cache implementation | Reproduce with the public cases and contact support |
| Wrong-language build instructions | Dependencies differ by runtime | Open the matching language page |
Next steps
Read signed responses and the threat model, then validate your own integration in Sandbox.