Official Python client for the SDKey license authentication protocol
Project description
sdkey
Official Python client for SDKey license authentication.
Implements the sealed session protocol: Ed25519-verified handshake, HKDF session keys, and AES-256-GCM validate envelopes, plus plaintext client auth (register / login / upgrade). See PROTOCOL.md.
Install
pip install sdkey
Requires Python 3.10+.
Quick start
Embed these values from the SDKey dashboard when you ship your app. app_version must exactly match the application version configured on the server (clientVersion); mismatch returns APP_OUTDATED.
from sdkey import SdkeyClient, SdkeyError
client = SdkeyClient(
api_base_url="https://api.sdkey.dev",
app_id="YOUR_APP_ID",
app_version="1.0.0",
app_public_key_b64="YOUR_APP_PUBLIC_KEY_BASE64",
)
try:
# hwid is optional (omit for web clients — server skips HWID checks)
result = client.validate("SDKY-XXXX-XXXX-XXXX-XXXX", "machine-hwid")
if result.success:
print("licensed", result.status, result.expires_at, result.subscription_tier)
print("message", result.message)
else:
print("denied", result.code, result.message)
except SdkeyError as err:
# Init / transport failures use `error` text from the server when present
print(err.code, err.message)
raise
validate calls init() automatically when no session exists. Sessions last ~15 minutes server-side; on SESSION_EXPIRED the client clears local state so the next call re-handshakes.
Client auth (plaintext JSON)
reg = client.register(
username="player1",
password="••••••••",
license_key="SDKY-XXXX-XXXX-XXXX-XXXX",
hwid="machine-hwid", # optional
)
if not reg.success:
print(reg.code, reg.error)
else:
print(reg.session_token, reg.user, reg.license)
login = client.login(username="player1", password="••••••••")
upgrade = client.upgrade(username="player1", license_key="SDKY-HIGHER-TIER-KEY")
upgrade takes username + license key only (no password). The new key’s subscriptionTier must be strictly greater than the user’s current tier.
Where message vs error appears
Per-app responseMessages may customize many strings. The SDK surfaces whatever the server returns.
| Surface | Success text field | Failure text field |
|---|---|---|
| Session init | (none) | error (raised as SdkeyError.message) |
| Sealed validate | message |
message |
| Client register / login / upgrade | (none) | error on ClientAuthResult |
Example JSON shapes
Init failure (plaintext):
{ "success": false, "error": "Client version outdated", "code": "APP_OUTDATED" }
Sealed validate success (message):
{
"success": true,
"code": "OK",
"message": "validated",
"status": "active",
"expiresAt": "2026-01-01T00:00:00.000Z",
"subscriptionTier": 0,
"sessionId": "...",
"timestamp": 1720000001,
"v": 1
}
Sealed validate failure (still message, not error):
{
"success": false,
"code": "HWID_MISMATCH",
"message": "Hardware ID mismatch",
"status": null,
"expiresAt": null,
"sessionId": "...",
"timestamp": 1720000001,
"v": 1
}
Client auth failure (error):
{
"success": false,
"error": "License tier must be higher than the current tier",
"code": "TIER_NOT_HIGHER"
}
API
SdkeyClient(options)
| Option | Type | Description |
|---|---|---|
api_base_url |
str |
API origin (no trailing slash) |
app_id |
str |
Application UUID |
app_version |
str |
Exact app version → sent as clientVersion |
app_public_key_b64 |
str |
Raw Ed25519 public key (32 bytes), base64 |
http_post |
callable | Optional HTTP POST override (tests / custom transport) |
Methods
init()— challenge handshake; verifies the signed hello; derives the AES session key; sendsclientVersionvalidate(license_key, hwid=None)— sealed validate; omitshwidJSON key when not provided; always decrypts then verifies the Ed25519 signature before trustingsuccessregister(...)/login(...)/upgrade(...)— plaintextPOST /api/v1/client/*get_session()/clear_session()— inspect or drop the local session
Errors
Protocol / transport failures raise SdkeyError with a code and message (server error text when the API provides one):
INIT_FAILED · APP_OUTDATED · HELLO_SIGNATURE_INVALID · VALIDATE_RESPONSE_INVALID · RESPONSE_SIGNATURE_INVALID · SESSION_MISMATCH · CLOCK_SKEW · NETWORK
License denials (banned, HWID mismatch, etc.) return a normal ValidateResult with success=False — they are not raised. Auth denials return ClientAuthResult(success=False, code=..., error=...).
This package does not include developer tooling / Bearer (sdk_live_…) management APIs.
Security notes
- Never ship app private keys in a client.
- Do not skip signature verification — that is the anti-spoof binding.
- This package is open source; the SDKey server remains a separate product.
Development
python -m pip install -e ".[dev]"
pytest
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sdkey-0.2.0.tar.gz.
File metadata
- Download URL: sdkey-0.2.0.tar.gz
- Upload date:
- Size: 14.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69a97c1eba5cfcc5c501e12d7eec6af2d501be3a84943896ff8cf23ae0039ec0
|
|
| MD5 |
17404e89ab7bdb45fa955f42ffa9a1ea
|
|
| BLAKE2b-256 |
0b36d6b38d160621d921c57f32f38e960eb1bdd6bb7a2c0bbfc7ef87f5230bf2
|
Provenance
The following attestation bundles were made for sdkey-0.2.0.tar.gz:
Publisher:
publish.yml on SDKeyDev/sdkey-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sdkey-0.2.0.tar.gz -
Subject digest:
69a97c1eba5cfcc5c501e12d7eec6af2d501be3a84943896ff8cf23ae0039ec0 - Sigstore transparency entry: 2195037862
- Sigstore integration time:
-
Permalink:
SDKeyDev/sdkey-python@d61508416e1d2825db5086a1bee6a1d3ad711d35 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/SDKeyDev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d61508416e1d2825db5086a1bee6a1d3ad711d35 -
Trigger Event:
release
-
Statement type:
File details
Details for the file sdkey-0.2.0-py3-none-any.whl.
File metadata
- Download URL: sdkey-0.2.0-py3-none-any.whl
- Upload date:
- Size: 12.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f645392c93ac4cdbc8452e7625ff84460fadd31d777f26c4296770657c7f601
|
|
| MD5 |
a67ca77f7bf5c7c7337412e4ef7ecdb1
|
|
| BLAKE2b-256 |
47ec123300cc7a661a03da0837f936500847e87da78b4069f22345482f61f1f2
|
Provenance
The following attestation bundles were made for sdkey-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on SDKeyDev/sdkey-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sdkey-0.2.0-py3-none-any.whl -
Subject digest:
4f645392c93ac4cdbc8452e7625ff84460fadd31d777f26c4296770657c7f601 - Sigstore transparency entry: 2195037864
- Sigstore integration time:
-
Permalink:
SDKeyDev/sdkey-python@d61508416e1d2825db5086a1bee6a1d3ad711d35 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/SDKeyDev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d61508416e1d2825db5086a1bee6a1d3ad711d35 -
Trigger Event:
release
-
Statement type: