OnewaySWP is a Python library for building one-way license verification systems without requiring a server.
Licenses are generated on the admin side, distributed to clients, and verified entirely offline.
The framework internally handles license generation, cryptographic signing, protected local state, and verification. Client applications only require a public key to validate licenses.
No internet connection. No license server. No backend infrastructure.
OnewaySWP is designed for developers who want a practical licensing solution that stays portable, self-contained, and independent.
| Feature | Description | |
|---|---|---|
| ◉ | Offline Verification | No internet connection or license server required |
| ◉ | Auto-Detection | Automatically detects the current OS and architecture |
| ◉ | Cross-Platform | Supports Windows, Linux, macOS, and Android |
| ◉ | Multi-Mode | Supports Date, Credit, and Duration license types |
| ◉ | Session-Based Duration | Duration licenses measured during active sessions |
| ◉ | Credit System | Credit-based licenses with automatic decrement |
| ◉ | Cryptographic Protection | License integrity and tamper detection |
| ◉ | Protected Local Storage | Local license state protected with internal protection mechanisms |
| ◉ | Clock Rollback Protection | Detects system clock manipulation |
| ◉ | Multi-License Support | Multiple independent license states per application |
| ◉ | Session Context Manager | Automatic start/stop for duration licenses |
| ◉ | State Export & Import | Move license state between environments |
| ◉ | Retry on File Lock | Automatic retry when state file is locked |
Install directly from PyPI:
pip install onewayswp| Command | Purpose |
|---|---|
pip |
Python package installer |
install |
Installs a package |
onewayswp |
OnewaySWP package |
Create an admin instance and generate the key pair.
from onewayswp import Admin
# Create admin instance
admin = Admin()
# Load existing key pair.
# If it does not exist yet, it will be generated automatically.
admin.load_keys(auto_generate=True)
# Display keys
print("Secret:", admin.secret_key)
print("Public:", admin.public_key)Recommended: Always use load_keys(auto_generate=True) on the admin side.
Manual key generation via generate_keys() should only be used when you intentionally want to replace the existing key pair. Replacing the key pair will invalidate all previously issued licenses.
Important: The secret key is used to sign licenses and must remain private. The public key is distributed to client applications for verification.
Load the existing keys and create a license.
from onewayswp import Admin
admin = Admin()
# Load existing keys
admin.load_keys(auto_generate=False)
# Create a license
result = admin.create_license(
type="date",
expires="2027-12-31",
additional_data={
"client_name": "username123"
}
)
print(result["token"])The client application only needs the public key.
from onewayswp import Client
# Create client instance
client = Client("data/license.swpb")
# Load public key
client.open_key("~/.owswp/public.key")
# Check whether a license is already active
if not client.is_active():
token = input("Enter key: ")
# Validate license
result = client.validate_key(token)
if not result["status"]:
print(result["message"])
exit(1)
# Verify protection state
protection = client.protection_verify()
if protection["status"]:
print("Application running...")
else:
print(protection["message"])┌─────────────────────┐
│ ADMIN │
├─────────────────────┤
│ Load Key Pair │
│ ↓ │
│ Create License │
│ ↓ │
│ Distribute Token │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ CLIENT │
├─────────────────────┤
│ Public Key │
│ ↓ │
│ Validate Token │
│ ↓ │
│ Verify Local State │
└─────────────────────┘
OnewaySWP provides three license modes.
A license that expires on a specific date.
result = admin.create_license(
type="date",
expires="2027-12-31"
)| Parameter | Description |
|---|---|
type |
"date" |
expires |
Expiration date in YYYY-MM-DD format |
Returns information such as:
tokentypeexpiredexpires_at
A license containing a credit balance that decreases when used.
result = admin.create_license(
type="credit",
credits=100
)| Parameter | Description |
|---|---|
type |
"credit" |
credits |
Initial credit amount |
Returns information such as:
tokentypecredit_value
A license valid for a fixed amount of active usage time.
result = admin.create_license(
type="duration",
hours=2
)| Parameter | Description |
|---|---|
type |
"duration" |
hours |
Duration in hours |
duration_seconds |
Alternative duration in seconds |
Returns information such as:
tokentypeduration_hours
| Method | Parameters | Returns | Description |
|---|---|---|---|
__init__ |
key_dir: str = None |
Admin |
Create admin instance |
keys_exist |
key_dir: str = None |
bool |
Check if key files exist |
generate_keys |
auto_save: bool = True, file_path: str = None |
tuple |
Generate key pair |
save_keys |
target_dir: str = None |
None |
Save keys to disk |
load_keys |
key_dir: str = None, validate: bool = True, auto_generate: bool = False |
tuple |
Load keys |
set_keys |
secret_key: str, public_key: str, validate: bool = True |
None |
Set keys manually |
validate_keys |
none |
bool |
Verify key pair |
create_license |
type, expires, credits, duration_seconds, hours, additional_data |
dict |
Create license token |
regenerate_keys |
key_dir: str = None |
tuple |
Generate new key pair |
platform |
none |
dict |
Get OS and architecture |
version |
none |
str |
Get library version |
| Method | Parameters | Returns | Description |
|---|---|---|---|
__init__ |
data_path: str = None, extra_paths: List[str] = None |
Client |
Create client instance |
open_key |
path: str |
None |
Load public key |
set_public_key |
key: str |
None |
Set public key |
is_active |
none |
bool |
Check active license |
validate_key |
token: str |
dict |
Validate license |
inspect_key |
token: str |
dict |
Inspect token without activation |
protection_verify |
none |
dict |
Verify local protection state |
use_credit |
amount: int = 1 |
dict |
Decrement credits |
session |
none |
context |
Duration session context |
export_state |
none |
dict |
Export license state |
import_state |
data: dict or str |
dict |
Import license state |
status |
none |
dict |
Get last status |
state_path |
none |
str |
Get state file path |
reset |
none |
None |
Delete local state |
version |
none |
str |
Get library version |
The info object provides library information and supports both attribute-style and dictionary-style access.
| Method | Description |
|---|---|
__getattr__ |
Access field as attribute |
__getitem__ |
Access field by key |
__contains__ |
Check whether field exists |
__iter__ |
Iterate over field names |
keys() |
Get field names |
values() |
Get field values |
items() |
Get field/value pairs |
get() |
Get field with default |
to_dict() |
Convert to dictionary |
Validation and operation methods use a consistent dictionary-based response format.
{
"status": True,
"code": "SUCCESS",
"message": "License valid and activated",
"type": "credit",
"credit_value": 100,
"remaining_credits": 100,
"created_at": "2026-10-03 12:00:00",
"last_time": "2026-10-03 12:05:00",
"additional_data": {
"hardware_id": "1234567890"
}
}{
"status": False,
"code": "EXPIRED",
"message": "Token expired"
}Failure responses contain:
status
code
message
| Field | Type | Description |
|---|---|---|
status |
bool |
True when operation succeeds |
code |
str |
Status or error code |
message |
str |
Human-readable message |
type |
str |
date, credit, or duration |
| Field | Type | Description |
|---|---|---|
expired |
str |
Expiration date |
expires_at |
int |
Unix expiration timestamp |
remaining_days |
int |
Remaining days |
| Field | Type | Description |
|---|---|---|
credit_value |
int |
Initial credit |
remaining_credits |
int |
Remaining credit |
used |
int |
Credit used in last operation |
| Field | Type | Description |
|---|---|---|
duration_hours |
float |
Total duration |
duration_seconds |
int |
Total duration in seconds |
remaining_hours |
float |
Remaining duration |
remaining_seconds |
int |
Remaining seconds |
elapsed_seconds |
int |
Elapsed session time |
started_at |
str |
Session start |
stopped_at |
str |
Session stop |
| Field | Type | Description |
|---|---|---|
created_at |
str |
License creation timestamp |
last_time |
str |
Last verification timestamp |
| Code | Description |
|---|---|
SUCCESS |
Operation completed successfully |
INVALID_SIGNATURE |
Token signature is invalid |
INVALID_MAGIC |
File format is invalid |
INVALID_KEY_FORMAT |
Key format is invalid |
UNSUPPORTED_VERSION |
File version is not supported |
KEY_MISMATCH |
Key pair does not match |
SECURITY_ERROR |
Security violation detected |
EXPIRED |
Token has expired |
CLOCK_ROLLBACK_DETECTED |
System clock rollback detected |
CORRUPTED_FILE |
File is corrupted |
INSUFFICIENT_CREDITS |
Credit balance is insufficient |
FILE_LOCKED |
File is locked by another process |
IO_ERROR |
Input/output error |
CRYPTO_ERROR |
Cryptographic error |
SERIALIZATION_ERROR |
Serialization error |
FFI_ERROR |
Foreign function interface error |
NO_STATE_FILE |
State file does not exist |
from onewayswp import Admin
admin = Admin(key_dir="./keys")
secret, public = admin.generate_keys(
auto_save=True
)
print("Secret Key:", secret)
print("Public Key:", public)from onewayswp import Admin
admin = Admin()
secret, public = admin.load_keys(
validate=True,
auto_generate=False
)
print("Keys loaded successfully")from onewayswp import Admin
admin = Admin()
secret, public = admin.load_keys(
auto_generate=True
)
print("Keys ready")
print("Public:", public)from onewayswp import Admin
admin = Admin()
admin.load_keys()
result = admin.create_license(
type="date",
expires="2027-12-31",
additional_data={
"client_name": "user12345",
"plan": "pro"
}
)
token = result["token"]
print("Token:", token)
print("Expires:", result["expired"])
print("Expires at:", result["expires_at"])from onewayswp import Admin
admin = Admin()
admin.load_keys()
result = admin.create_license(
type="credit",
credits=100,
additional_data={
"client_name": "user12345"
}
)
print("Token:", result["token"])
print("Credits:", result["credit_value"])from onewayswp import Admin
admin = Admin()
admin.load_keys()
result = admin.create_license(
type="duration",
hours=2,
additional_data={
"client_name": "user12345"
}
)
print("Token:", result["token"])
print("Duration:", result["duration_hours"], "hours")Alternative using seconds:
result = admin.create_license(
type="duration",
duration_seconds=3600
)
print(
"Duration:",
result["duration_hours"],
"hours"
)from onewayswp import Admin
admin = Admin()
admin.set_keys(
secret_key="OWSWP-sec-...",
public_key="OWSWP-pub-...",
validate=True
)
print("Keys set")from onewayswp import Admin
admin = Admin()
admin.load_keys()
new_secret, new_public = admin.regenerate_keys()
print("New secret:", new_secret)
print("New public:", new_public)Regenerating the key pair will cause previously issued tokens to become invalid.
from onewayswp import Admin
admin = Admin()
info = admin.platform()
print("OS:", info["os"])
print("Arch:", info["arch"])from onewayswp import Client
client = Client(
"data/license.swpb"
)
client.set_public_key(
"OWSWP-pub-..."
)
if client.is_active():
print("License already active")
else:
token = input("Enter key: ")
result = client.validate_key(token)
if result["status"]:
print("License activated")
print("Type:", result["type"])
else:
print("Failed:", result["message"])from onewayswp import Client
client = Client(
"data/license.swpb"
)
client.open_key(
"~/.owswp/public.key"
)
result = client.validate_key(
"OWSWP-..."
)
if not result["status"]:
print("Invalid license")
exit(1)
result = client.use_credit(5)
if result["status"]:
print("Used 5 credits")
print(
"Remaining:",
result["remaining_credits"]
)
else:
print("Failed:", result["message"])Duration licenses can measure usage during an active session.
from onewayswp import Client
import time
client = Client(
"data/license.swpb"
)
client.open_key(
"~/.owswp/public.key"
)
result = client.validate_key(
"OWSWP-..."
)
if not result["status"]:
print("Invalid license")
exit(1)
with client.session():
print("Application running...")
time.sleep(10)
protection = client.protection_verify()
print(
"Remaining:",
protection["remaining_hours"],
"hours"
)from onewayswp import Client
client = Client(
"data/license.swpb"
)
client.set_public_key(
"OWSWP-pub-..."
)
result = client.inspect_key(
"OWSWP-..."
)
if result["status"]:
print("Type:", result["type"])
print("Is expired:", result["is_expired"])
if result["type"] == "date":
print(
"Expires:",
result["expired"]
)
print(
"Remaining days:",
result["remaining_days"]
)
elif result["type"] == "credit":
print(
"Credits:",
result["credit_value"]
)
elif result["type"] == "duration":
print(
"Duration hours:",
result["duration_hours"]
)Export state:
from onewayswp import Client
client1 = Client(
"data/license1.swpb"
)
client1.open_key(
"~/.owswp/public.key"
)
exported = client1.export_state()
print(
"Exported data:",
exported["data"][:50],
"..."
)
print(
"Public key:",
exported["public_key"]
)Import state:
client2 = Client(
"data/license2.swpb"
)
client2.set_public_key(
exported["public_key"]
)
result = client2.import_state(
exported
)
if result["status"]:
print(
"State imported successfully"
)from onewayswp import Client
client = Client(
"data/license.swpb"
)
client.set_public_key(
"OWSWP-pub-..."
)
client.reset()
print("State reset")After resetting, the next validation will require a new token.
from onewayswp import info
print(info)
print("Author:", info.author)
print("Version:", info.oneway_version)
print("GitHub:", info.swp_github)Dictionary-style access:
print("Author:", info["author"])Convert to dictionary:
data = info.to_dict()
for key, value in data.items():
print(f"{key}: {value}")from onewayswp import (
Client,
OnewaySWPError,
InvalidTokenError,
ExpiredError,
SecurityError,
)
client = Client(
"data/license.swbp"
)
client.set_public_key(
"OWSWP-pub-..."
)
try:
result = client.validate_key(
"OWSWP-..."
)
if not result["status"]:
code = result["code"]
message = result["message"]
print(
f"Error [{code}]: {message}"
)
except InvalidTokenError as e:
print(
f"Invalid token: {e}"
)
except ExpiredError as e:
print(
f"Token expired: {e}"
)
except SecurityError as e:
print(
f"Security error: {e}"
)
except OnewaySWPError as e:
print(
f"Error: {e}"
)OnewaySWP is designed to help developers create one-way license verification systems for applications that cannot rely on a server.
It is a licensing framework, not a replacement for application-level security.
The library applies internal cryptographic protection to help preserve license integrity, protect local license state, and detect unauthorized modification.
However, the overall security of an application still depends on how the framework is integrated by the developer.
Any bypass, modification, or direct interaction with the application code is outside the scope of this library.
The secret key is used to sign licenses.
Never distribute it with client applications.
If the secret key is exposed, another party may be able to generate valid licenses.
Store the secret key and public key safely.
Losing the key pair may prevent future licenses from being verified against previously issued tokens.
Client applications only require the public key to validate licenses.
The secret key should remain on the administrative side.
Treat the .swpb state file as protected application data.
Manual modification may invalidate the license state.
OnewaySWP is a tool.
The way it is integrated into an application determines how effectively it contributes to the application's licensing protection.
OnewaySWP is designed for cross-platform usage:
Windows
Linux
macOS
Android
Platform and architecture information can be detected automatically:
from onewayswp import Admin
admin = Admin()
info = admin.platform()
print(info["os"])
print(info["arch"])| Project | OnewaySWP |
| Description | Offline One-Way License Framework |
| Version | 0.1.0 |
| Author | Juan Hulu |
| Organization | SilentWolfProject |
| License | MIT |
-
Author — TikTok https://tiktok.com/@juanhulu.xyz
-
SWP — TikTok https://tiktok.com/@silentwolfproject
-
Author — Instagram https://www.instagram.com/juanhulu.xyz
-
SWP — Instagram https://www.instagram.com/silentwolfproject
-
GitHub Pages https://silentwolfproject.github.io
