devkanan 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: devkanan
3
+ Version: 0.2.2
4
+ Summary: Cliente Python para DevKanan — validación local + API online de licencias firmadas RSA
5
+ Author-email: Vilchis <vilchislalo98@gmail.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://devkanan.dev
8
+ Keywords: license,licensing,rsa,drm,devkanan,kanan
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.8
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: cryptography>=41.0.0
17
+ Requires-Dist: requests>=2.28.0
18
+ Dynamic: license-file
19
+
20
+ # devkanan
21
+
22
+ [![PyPI version](https://img.shields.io/pypi/v/devkanan.svg)](https://pypi.org/project/devkanan/)
23
+ [![Python](https://img.shields.io/pypi/pyversions/devkanan.svg)](https://pypi.org/project/devkanan/)
24
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
25
+
26
+ Lightweight Python client to activate and validate RSA-signed licenses issued by the **[DevKanan](https://devkanan.dev)** platform or an on-premise **DevKananServer**.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install devkanan
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Online activation
37
+
38
+ ```python
39
+ from devkanan import Key, Helpers
40
+
41
+ result, msg = Key.activate(
42
+ token=ACCESS_TOKEN,
43
+ rsa_pub_key=RSA_PUBLIC_KEY,
44
+ product_id=100000,
45
+ key="ABCD-EFGH-IJKL-MNOP",
46
+ machine_code=Helpers.GetMachineCode(v=2),
47
+ # floating_time_interval=300, # optional floating lease
48
+ server_url="https://devkanan.dev", # optional
49
+ )
50
+
51
+ if result is None:
52
+ print(f"Activation failed: {msg}")
53
+ exit(1)
54
+
55
+ if result.is_on_right_machine(Helpers.GetMachineCode(v=2)) and result.has_not_expired():
56
+ print("License valid — app can start")
57
+ ```
58
+
59
+ ### Offline validation (signed `.dat` file)
60
+
61
+ ```python
62
+ from devkanan import LicenseKey, Helpers
63
+
64
+ RSA_PUB_KEY = """-----BEGIN PUBLIC KEY-----
65
+ ... your tenant's RSA public key ...
66
+ -----END PUBLIC KEY-----"""
67
+
68
+ with open("license.dat", encoding="utf-8-sig") as f:
69
+ lk = LicenseKey.load_from_string(RSA_PUB_KEY, f.read(), max_age_days=1)
70
+
71
+ if lk is None:
72
+ print("Invalid license (corrupt signature, expired or blocked)")
73
+ exit(1)
74
+
75
+ if not lk.is_on_right_machine(Helpers.GetMachineCode(v=2)):
76
+ print("This machine is not authorized")
77
+ exit(1)
78
+
79
+ # Features
80
+ if lk.F1:
81
+ enable_pro_features()
82
+ ```
83
+
84
+ ### Usage credits
85
+
86
+ ```python
87
+ from devkanan import Credits
88
+
89
+ # Consume credits when a premium feature is used
90
+ ok, balance, msg = Credits.record(
91
+ token=ACCESS_TOKEN, product_id=100000, key=LICENSE_KEY,
92
+ amount=10, feature="export_pdf",
93
+ )
94
+
95
+ # Check current balance
96
+ enabled, balance, msg = Credits.balance(
97
+ token=ACCESS_TOKEN, product_id=100000, key=LICENSE_KEY,
98
+ )
99
+ ```
100
+
101
+ ## API
102
+
103
+ ### `Helpers.GetMachineCode(v=2)`
104
+
105
+ Generates a unique machine code based on hardware properties. `v=2` (default) uses BIOS UUID via PowerShell on Windows or `/etc/machine-id` on Linux. Produces the same hash as the Cryptolens SDK.
106
+
107
+ ### `LicenseKey.load_from_string(rsa_pub_key, content, max_age_days=0)`
108
+
109
+ Parses a `.dat`, verifies the RSA signature and freshness.
110
+
111
+ | Parameter | Type | Description |
112
+ |---|---|---|
113
+ | `rsa_pub_key` | str | XML (.NET) or PEM (standard). Auto-detected. |
114
+ | `content` | str | `.dat` file contents |
115
+ | `max_age_days` | int | Max days since `signDate` before re-validation is required. 0 = no limit. |
116
+
117
+ Returns a `LicenseKey` object or `None` if any check fails.
118
+
119
+ ### `LicenseKey` methods
120
+
121
+ - `is_on_right_machine(machine_code)` — verifies the machine is authorized
122
+ - `has_not_expired()` — verifies `expires > now`
123
+ - `has_feature(n)` — shortcut for `getattr(lk, f'f{n}')` (n = 1..8)
124
+
125
+ ### `LicenseKey` attributes
126
+
127
+ | Attribute | Type |
128
+ |---|---|
129
+ | `product_id`, `id`, `key`, `notes` | basic data |
130
+ | `created`, `expires`, `sign_date` | unix timestamps |
131
+ | `period`, `max_no_of_machines` | integers |
132
+ | `F1`..`F8`, `block`, `trial_activation` | flags |
133
+ | `activated_machines` | List[ActivatedMachine] |
134
+ | `data_objects` | List[DataObject] |
135
+ | `customer` | Customer or None |
136
+ | `offline_mode` | "FloatingLease" / "FloatingManual" / "Locked" |
137
+
138
+ ## Comparison with Cryptolens SDK
139
+
140
+ | | Cryptolens SDK | devkanan |
141
+ |---|---|---|
142
+ | Online activation | ✅ | ✅ |
143
+ | Offline `.dat` / `.skm` validation | ✅ | ✅ |
144
+ | `Helpers.GetMachineCode` | ✅ | ✅ (same hash) |
145
+ | `LicenseKey.load_from_string` | ✅ | ✅ |
146
+ | Size | ~2 MB with deps | ~10 KB |
147
+ | Dependencies | `pycryptodome`, `requests` | `cryptography`, `requests` |
148
+
149
+ ## Documentation
150
+
151
+ - [DevKanan docs](https://devkanan.dev/docs)
152
+ - [API reference](https://devkanan.dev/docs/en/api)
153
+ - [Offline mode guide](https://devkanan.dev/docs/en/offline)
154
+
155
+ ## License
156
+
157
+ [Apache 2.0](LICENSE). Partially based on Cryptolens Python SDK (also Apache 2.0).
@@ -0,0 +1,138 @@
1
+ # devkanan
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/devkanan.svg)](https://pypi.org/project/devkanan/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/devkanan.svg)](https://pypi.org/project/devkanan/)
5
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
6
+
7
+ Lightweight Python client to activate and validate RSA-signed licenses issued by the **[DevKanan](https://devkanan.dev)** platform or an on-premise **DevKananServer**.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install devkanan
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Online activation
18
+
19
+ ```python
20
+ from devkanan import Key, Helpers
21
+
22
+ result, msg = Key.activate(
23
+ token=ACCESS_TOKEN,
24
+ rsa_pub_key=RSA_PUBLIC_KEY,
25
+ product_id=100000,
26
+ key="ABCD-EFGH-IJKL-MNOP",
27
+ machine_code=Helpers.GetMachineCode(v=2),
28
+ # floating_time_interval=300, # optional floating lease
29
+ server_url="https://devkanan.dev", # optional
30
+ )
31
+
32
+ if result is None:
33
+ print(f"Activation failed: {msg}")
34
+ exit(1)
35
+
36
+ if result.is_on_right_machine(Helpers.GetMachineCode(v=2)) and result.has_not_expired():
37
+ print("License valid — app can start")
38
+ ```
39
+
40
+ ### Offline validation (signed `.dat` file)
41
+
42
+ ```python
43
+ from devkanan import LicenseKey, Helpers
44
+
45
+ RSA_PUB_KEY = """-----BEGIN PUBLIC KEY-----
46
+ ... your tenant's RSA public key ...
47
+ -----END PUBLIC KEY-----"""
48
+
49
+ with open("license.dat", encoding="utf-8-sig") as f:
50
+ lk = LicenseKey.load_from_string(RSA_PUB_KEY, f.read(), max_age_days=1)
51
+
52
+ if lk is None:
53
+ print("Invalid license (corrupt signature, expired or blocked)")
54
+ exit(1)
55
+
56
+ if not lk.is_on_right_machine(Helpers.GetMachineCode(v=2)):
57
+ print("This machine is not authorized")
58
+ exit(1)
59
+
60
+ # Features
61
+ if lk.F1:
62
+ enable_pro_features()
63
+ ```
64
+
65
+ ### Usage credits
66
+
67
+ ```python
68
+ from devkanan import Credits
69
+
70
+ # Consume credits when a premium feature is used
71
+ ok, balance, msg = Credits.record(
72
+ token=ACCESS_TOKEN, product_id=100000, key=LICENSE_KEY,
73
+ amount=10, feature="export_pdf",
74
+ )
75
+
76
+ # Check current balance
77
+ enabled, balance, msg = Credits.balance(
78
+ token=ACCESS_TOKEN, product_id=100000, key=LICENSE_KEY,
79
+ )
80
+ ```
81
+
82
+ ## API
83
+
84
+ ### `Helpers.GetMachineCode(v=2)`
85
+
86
+ Generates a unique machine code based on hardware properties. `v=2` (default) uses BIOS UUID via PowerShell on Windows or `/etc/machine-id` on Linux. Produces the same hash as the Cryptolens SDK.
87
+
88
+ ### `LicenseKey.load_from_string(rsa_pub_key, content, max_age_days=0)`
89
+
90
+ Parses a `.dat`, verifies the RSA signature and freshness.
91
+
92
+ | Parameter | Type | Description |
93
+ |---|---|---|
94
+ | `rsa_pub_key` | str | XML (.NET) or PEM (standard). Auto-detected. |
95
+ | `content` | str | `.dat` file contents |
96
+ | `max_age_days` | int | Max days since `signDate` before re-validation is required. 0 = no limit. |
97
+
98
+ Returns a `LicenseKey` object or `None` if any check fails.
99
+
100
+ ### `LicenseKey` methods
101
+
102
+ - `is_on_right_machine(machine_code)` — verifies the machine is authorized
103
+ - `has_not_expired()` — verifies `expires > now`
104
+ - `has_feature(n)` — shortcut for `getattr(lk, f'f{n}')` (n = 1..8)
105
+
106
+ ### `LicenseKey` attributes
107
+
108
+ | Attribute | Type |
109
+ |---|---|
110
+ | `product_id`, `id`, `key`, `notes` | basic data |
111
+ | `created`, `expires`, `sign_date` | unix timestamps |
112
+ | `period`, `max_no_of_machines` | integers |
113
+ | `F1`..`F8`, `block`, `trial_activation` | flags |
114
+ | `activated_machines` | List[ActivatedMachine] |
115
+ | `data_objects` | List[DataObject] |
116
+ | `customer` | Customer or None |
117
+ | `offline_mode` | "FloatingLease" / "FloatingManual" / "Locked" |
118
+
119
+ ## Comparison with Cryptolens SDK
120
+
121
+ | | Cryptolens SDK | devkanan |
122
+ |---|---|---|
123
+ | Online activation | ✅ | ✅ |
124
+ | Offline `.dat` / `.skm` validation | ✅ | ✅ |
125
+ | `Helpers.GetMachineCode` | ✅ | ✅ (same hash) |
126
+ | `LicenseKey.load_from_string` | ✅ | ✅ |
127
+ | Size | ~2 MB with deps | ~10 KB |
128
+ | Dependencies | `pycryptodome`, `requests` | `cryptography`, `requests` |
129
+
130
+ ## Documentation
131
+
132
+ - [DevKanan docs](https://devkanan.dev/docs)
133
+ - [API reference](https://devkanan.dev/docs/en/api)
134
+ - [Offline mode guide](https://devkanan.dev/docs/en/offline)
135
+
136
+ ## License
137
+
138
+ [Apache 2.0](LICENSE). Partially based on Cryptolens Python SDK (also Apache 2.0).
@@ -30,7 +30,7 @@ from .helpers import Helpers
30
30
  from .license_key import LicenseKey, ActivatedMachine, DataObject, Customer
31
31
  from .key import Key, Credits
32
32
 
33
- __version__ = "0.2.0"
33
+ __version__ = "0.2.2"
34
34
  __all__ = [
35
35
  "LicenseKey",
36
36
  "Helpers",
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: devkanan
3
+ Version: 0.2.2
4
+ Summary: Cliente Python para DevKanan — validación local + API online de licencias firmadas RSA
5
+ Author-email: Vilchis <vilchislalo98@gmail.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://devkanan.dev
8
+ Keywords: license,licensing,rsa,drm,devkanan,kanan
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.8
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: cryptography>=41.0.0
17
+ Requires-Dist: requests>=2.28.0
18
+ Dynamic: license-file
19
+
20
+ # devkanan
21
+
22
+ [![PyPI version](https://img.shields.io/pypi/v/devkanan.svg)](https://pypi.org/project/devkanan/)
23
+ [![Python](https://img.shields.io/pypi/pyversions/devkanan.svg)](https://pypi.org/project/devkanan/)
24
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
25
+
26
+ Lightweight Python client to activate and validate RSA-signed licenses issued by the **[DevKanan](https://devkanan.dev)** platform or an on-premise **DevKananServer**.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install devkanan
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Online activation
37
+
38
+ ```python
39
+ from devkanan import Key, Helpers
40
+
41
+ result, msg = Key.activate(
42
+ token=ACCESS_TOKEN,
43
+ rsa_pub_key=RSA_PUBLIC_KEY,
44
+ product_id=100000,
45
+ key="ABCD-EFGH-IJKL-MNOP",
46
+ machine_code=Helpers.GetMachineCode(v=2),
47
+ # floating_time_interval=300, # optional floating lease
48
+ server_url="https://devkanan.dev", # optional
49
+ )
50
+
51
+ if result is None:
52
+ print(f"Activation failed: {msg}")
53
+ exit(1)
54
+
55
+ if result.is_on_right_machine(Helpers.GetMachineCode(v=2)) and result.has_not_expired():
56
+ print("License valid — app can start")
57
+ ```
58
+
59
+ ### Offline validation (signed `.dat` file)
60
+
61
+ ```python
62
+ from devkanan import LicenseKey, Helpers
63
+
64
+ RSA_PUB_KEY = """-----BEGIN PUBLIC KEY-----
65
+ ... your tenant's RSA public key ...
66
+ -----END PUBLIC KEY-----"""
67
+
68
+ with open("license.dat", encoding="utf-8-sig") as f:
69
+ lk = LicenseKey.load_from_string(RSA_PUB_KEY, f.read(), max_age_days=1)
70
+
71
+ if lk is None:
72
+ print("Invalid license (corrupt signature, expired or blocked)")
73
+ exit(1)
74
+
75
+ if not lk.is_on_right_machine(Helpers.GetMachineCode(v=2)):
76
+ print("This machine is not authorized")
77
+ exit(1)
78
+
79
+ # Features
80
+ if lk.F1:
81
+ enable_pro_features()
82
+ ```
83
+
84
+ ### Usage credits
85
+
86
+ ```python
87
+ from devkanan import Credits
88
+
89
+ # Consume credits when a premium feature is used
90
+ ok, balance, msg = Credits.record(
91
+ token=ACCESS_TOKEN, product_id=100000, key=LICENSE_KEY,
92
+ amount=10, feature="export_pdf",
93
+ )
94
+
95
+ # Check current balance
96
+ enabled, balance, msg = Credits.balance(
97
+ token=ACCESS_TOKEN, product_id=100000, key=LICENSE_KEY,
98
+ )
99
+ ```
100
+
101
+ ## API
102
+
103
+ ### `Helpers.GetMachineCode(v=2)`
104
+
105
+ Generates a unique machine code based on hardware properties. `v=2` (default) uses BIOS UUID via PowerShell on Windows or `/etc/machine-id` on Linux. Produces the same hash as the Cryptolens SDK.
106
+
107
+ ### `LicenseKey.load_from_string(rsa_pub_key, content, max_age_days=0)`
108
+
109
+ Parses a `.dat`, verifies the RSA signature and freshness.
110
+
111
+ | Parameter | Type | Description |
112
+ |---|---|---|
113
+ | `rsa_pub_key` | str | XML (.NET) or PEM (standard). Auto-detected. |
114
+ | `content` | str | `.dat` file contents |
115
+ | `max_age_days` | int | Max days since `signDate` before re-validation is required. 0 = no limit. |
116
+
117
+ Returns a `LicenseKey` object or `None` if any check fails.
118
+
119
+ ### `LicenseKey` methods
120
+
121
+ - `is_on_right_machine(machine_code)` — verifies the machine is authorized
122
+ - `has_not_expired()` — verifies `expires > now`
123
+ - `has_feature(n)` — shortcut for `getattr(lk, f'f{n}')` (n = 1..8)
124
+
125
+ ### `LicenseKey` attributes
126
+
127
+ | Attribute | Type |
128
+ |---|---|
129
+ | `product_id`, `id`, `key`, `notes` | basic data |
130
+ | `created`, `expires`, `sign_date` | unix timestamps |
131
+ | `period`, `max_no_of_machines` | integers |
132
+ | `F1`..`F8`, `block`, `trial_activation` | flags |
133
+ | `activated_machines` | List[ActivatedMachine] |
134
+ | `data_objects` | List[DataObject] |
135
+ | `customer` | Customer or None |
136
+ | `offline_mode` | "FloatingLease" / "FloatingManual" / "Locked" |
137
+
138
+ ## Comparison with Cryptolens SDK
139
+
140
+ | | Cryptolens SDK | devkanan |
141
+ |---|---|---|
142
+ | Online activation | ✅ | ✅ |
143
+ | Offline `.dat` / `.skm` validation | ✅ | ✅ |
144
+ | `Helpers.GetMachineCode` | ✅ | ✅ (same hash) |
145
+ | `LicenseKey.load_from_string` | ✅ | ✅ |
146
+ | Size | ~2 MB with deps | ~10 KB |
147
+ | Dependencies | `pycryptodome`, `requests` | `cryptography`, `requests` |
148
+
149
+ ## Documentation
150
+
151
+ - [DevKanan docs](https://devkanan.dev/docs)
152
+ - [API reference](https://devkanan.dev/docs/en/api)
153
+ - [Offline mode guide](https://devkanan.dev/docs/en/offline)
154
+
155
+ ## License
156
+
157
+ [Apache 2.0](LICENSE). Partially based on Cryptolens Python SDK (also Apache 2.0).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "devkanan"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Cliente Python para DevKanan — validación local + API online de licencias firmadas RSA"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
devkanan-0.2.0/PKG-INFO DELETED
@@ -1,120 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: devkanan
3
- Version: 0.2.0
4
- Summary: Cliente Python para DevKanan — validación local + API online de licencias firmadas RSA
5
- Author-email: Vilchis <vilchislalo98@gmail.com>
6
- License: Apache-2.0
7
- Project-URL: Homepage, https://devkanan.dev
8
- Keywords: license,licensing,rsa,drm,devkanan,kanan
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: License :: OSI Approved :: Apache Software License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.8
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE
16
- Requires-Dist: cryptography>=41.0.0
17
- Requires-Dist: requests>=2.28.0
18
- Dynamic: license-file
19
-
20
- # qustomlicensing
21
-
22
- Cliente Python ligero para validar archivos de licencia `.dat` firmados con RSA, emitidos por **LicensingServer** SaaS o QustomLicenseServer.
23
-
24
- API estilo Cryptolens — fácil migración si vienes de su SDK.
25
-
26
- ## Instalación
27
-
28
- ```bash
29
- pip install qustomlicensing
30
- ```
31
-
32
- O para desarrollo:
33
- ```bash
34
- pip install -e .
35
- ```
36
-
37
- ## Uso básico
38
-
39
- ```python
40
- from qustomlicensing import LicenseKey, Helpers
41
-
42
- # Clave pública RSA del tenant (XML o PEM)
43
- RSA_PUB_KEY = """-----BEGIN PUBLIC KEY-----
44
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
45
- -----END PUBLIC KEY-----"""
46
-
47
- # Obtener machine code de esta PC
48
- machine_code = Helpers.GetMachineCode(v=2)
49
-
50
- # Leer y validar .dat
51
- with open("license.dat", "r", encoding="utf-8-sig") as f:
52
- license_key = LicenseKey.load_from_string(RSA_PUB_KEY, f.read(), max_age_days=1)
53
-
54
- if license_key is None:
55
- print("Licencia invalida o firma corrupta")
56
- exit(1)
57
-
58
- # Verificar esta máquina
59
- if not license_key.is_on_right_machine(machine_code):
60
- print("Esta maquina no esta autorizada")
61
- exit(1)
62
-
63
- # Verificar features
64
- if license_key.F1:
65
- print("Feature Pro activado")
66
-
67
- print(f"Licencia valida hasta {license_key.expires}")
68
- ```
69
-
70
- ## API
71
-
72
- ### `Helpers.GetMachineCode(v=2)`
73
- Genera un machine code único basado en propiedades del hardware. `v=2` es el algoritmo actual (SHA-256 sobre identificadores).
74
-
75
- ### `LicenseKey.load_from_string(rsa_pub_key, content, max_age_days=0)`
76
- Parsea un `.dat` JSON, verifica firma RSA y freshness.
77
-
78
- | Parámetro | Tipo | Descripción |
79
- |---|---|---|
80
- | `rsa_pub_key` | str | XML (.NET) o PEM. Auto-detecta. |
81
- | `content` | str | Contenido del archivo `.dat` |
82
- | `max_age_days` | int | Máx. días desde `signDate`. 0 = ilimitado o usa el del `.dat`. |
83
-
84
- Devuelve un objeto `LicenseKey` o `None` si la validación falla.
85
-
86
- ### Atributos de `LicenseKey`
87
- | Atributo | Tipo |
88
- |---|---|
89
- | `product_id`, `id`, `key`, `notes` | datos básicos |
90
- | `created`, `expires`, `sign_date` | datetimes UTC |
91
- | `period`, `max_no_of_machines`, `max_offline_days` | enteros |
92
- | `F1`..`F8`, `block`, `trial_activation` | flags |
93
- | `activated_machines` | List[ActivatedMachine] |
94
- | `data_objects` | List[DataObject] |
95
- | `customer` | Customer o None |
96
- | `offline_mode` | str (FloatingLease/FloatingManual/Locked) |
97
-
98
- ### `license_key.is_on_right_machine(machine_code)`
99
- Verifica que el machine code esté en `activatedMachines`.
100
-
101
- ### `license_key.has_not_expired()`
102
- Verifica que `expires > now`.
103
-
104
- ### `license_key.has_feature(n)`
105
- Atajo para `getattr(license_key, f'F{n}')`.
106
-
107
- ## Comparación con SDK Cryptolens
108
-
109
- | | Cryptolens SDK | qustomlicensing |
110
- |---|---|---|
111
- | Activate online | ✅ | ❌ (usa requests directamente) |
112
- | Validar .skm/.dat offline | ✅ | ✅ |
113
- | `Helpers.GetMachineCode` | ✅ | ✅ (compatible) |
114
- | `LicenseKey.load_from_string` | ✅ | ✅ (compatible) |
115
- | Tamaño | ~2 MB con deps | ~50 KB |
116
- | Dependencias | `pycryptodome`, `requests` | solo `cryptography` |
117
-
118
- ## Licencia
119
-
120
- Apache-2.0. Basado en código del SDK de Cryptolens (también Apache-2.0).
devkanan-0.2.0/README.md DELETED
@@ -1,101 +0,0 @@
1
- # qustomlicensing
2
-
3
- Cliente Python ligero para validar archivos de licencia `.dat` firmados con RSA, emitidos por **LicensingServer** SaaS o QustomLicenseServer.
4
-
5
- API estilo Cryptolens — fácil migración si vienes de su SDK.
6
-
7
- ## Instalación
8
-
9
- ```bash
10
- pip install qustomlicensing
11
- ```
12
-
13
- O para desarrollo:
14
- ```bash
15
- pip install -e .
16
- ```
17
-
18
- ## Uso básico
19
-
20
- ```python
21
- from qustomlicensing import LicenseKey, Helpers
22
-
23
- # Clave pública RSA del tenant (XML o PEM)
24
- RSA_PUB_KEY = """-----BEGIN PUBLIC KEY-----
25
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
26
- -----END PUBLIC KEY-----"""
27
-
28
- # Obtener machine code de esta PC
29
- machine_code = Helpers.GetMachineCode(v=2)
30
-
31
- # Leer y validar .dat
32
- with open("license.dat", "r", encoding="utf-8-sig") as f:
33
- license_key = LicenseKey.load_from_string(RSA_PUB_KEY, f.read(), max_age_days=1)
34
-
35
- if license_key is None:
36
- print("Licencia invalida o firma corrupta")
37
- exit(1)
38
-
39
- # Verificar esta máquina
40
- if not license_key.is_on_right_machine(machine_code):
41
- print("Esta maquina no esta autorizada")
42
- exit(1)
43
-
44
- # Verificar features
45
- if license_key.F1:
46
- print("Feature Pro activado")
47
-
48
- print(f"Licencia valida hasta {license_key.expires}")
49
- ```
50
-
51
- ## API
52
-
53
- ### `Helpers.GetMachineCode(v=2)`
54
- Genera un machine code único basado en propiedades del hardware. `v=2` es el algoritmo actual (SHA-256 sobre identificadores).
55
-
56
- ### `LicenseKey.load_from_string(rsa_pub_key, content, max_age_days=0)`
57
- Parsea un `.dat` JSON, verifica firma RSA y freshness.
58
-
59
- | Parámetro | Tipo | Descripción |
60
- |---|---|---|
61
- | `rsa_pub_key` | str | XML (.NET) o PEM. Auto-detecta. |
62
- | `content` | str | Contenido del archivo `.dat` |
63
- | `max_age_days` | int | Máx. días desde `signDate`. 0 = ilimitado o usa el del `.dat`. |
64
-
65
- Devuelve un objeto `LicenseKey` o `None` si la validación falla.
66
-
67
- ### Atributos de `LicenseKey`
68
- | Atributo | Tipo |
69
- |---|---|
70
- | `product_id`, `id`, `key`, `notes` | datos básicos |
71
- | `created`, `expires`, `sign_date` | datetimes UTC |
72
- | `period`, `max_no_of_machines`, `max_offline_days` | enteros |
73
- | `F1`..`F8`, `block`, `trial_activation` | flags |
74
- | `activated_machines` | List[ActivatedMachine] |
75
- | `data_objects` | List[DataObject] |
76
- | `customer` | Customer o None |
77
- | `offline_mode` | str (FloatingLease/FloatingManual/Locked) |
78
-
79
- ### `license_key.is_on_right_machine(machine_code)`
80
- Verifica que el machine code esté en `activatedMachines`.
81
-
82
- ### `license_key.has_not_expired()`
83
- Verifica que `expires > now`.
84
-
85
- ### `license_key.has_feature(n)`
86
- Atajo para `getattr(license_key, f'F{n}')`.
87
-
88
- ## Comparación con SDK Cryptolens
89
-
90
- | | Cryptolens SDK | qustomlicensing |
91
- |---|---|---|
92
- | Activate online | ✅ | ❌ (usa requests directamente) |
93
- | Validar .skm/.dat offline | ✅ | ✅ |
94
- | `Helpers.GetMachineCode` | ✅ | ✅ (compatible) |
95
- | `LicenseKey.load_from_string` | ✅ | ✅ (compatible) |
96
- | Tamaño | ~2 MB con deps | ~50 KB |
97
- | Dependencias | `pycryptodome`, `requests` | solo `cryptography` |
98
-
99
- ## Licencia
100
-
101
- Apache-2.0. Basado en código del SDK de Cryptolens (también Apache-2.0).
@@ -1,120 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: devkanan
3
- Version: 0.2.0
4
- Summary: Cliente Python para DevKanan — validación local + API online de licencias firmadas RSA
5
- Author-email: Vilchis <vilchislalo98@gmail.com>
6
- License: Apache-2.0
7
- Project-URL: Homepage, https://devkanan.dev
8
- Keywords: license,licensing,rsa,drm,devkanan,kanan
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: License :: OSI Approved :: Apache Software License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.8
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE
16
- Requires-Dist: cryptography>=41.0.0
17
- Requires-Dist: requests>=2.28.0
18
- Dynamic: license-file
19
-
20
- # qustomlicensing
21
-
22
- Cliente Python ligero para validar archivos de licencia `.dat` firmados con RSA, emitidos por **LicensingServer** SaaS o QustomLicenseServer.
23
-
24
- API estilo Cryptolens — fácil migración si vienes de su SDK.
25
-
26
- ## Instalación
27
-
28
- ```bash
29
- pip install qustomlicensing
30
- ```
31
-
32
- O para desarrollo:
33
- ```bash
34
- pip install -e .
35
- ```
36
-
37
- ## Uso básico
38
-
39
- ```python
40
- from qustomlicensing import LicenseKey, Helpers
41
-
42
- # Clave pública RSA del tenant (XML o PEM)
43
- RSA_PUB_KEY = """-----BEGIN PUBLIC KEY-----
44
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
45
- -----END PUBLIC KEY-----"""
46
-
47
- # Obtener machine code de esta PC
48
- machine_code = Helpers.GetMachineCode(v=2)
49
-
50
- # Leer y validar .dat
51
- with open("license.dat", "r", encoding="utf-8-sig") as f:
52
- license_key = LicenseKey.load_from_string(RSA_PUB_KEY, f.read(), max_age_days=1)
53
-
54
- if license_key is None:
55
- print("Licencia invalida o firma corrupta")
56
- exit(1)
57
-
58
- # Verificar esta máquina
59
- if not license_key.is_on_right_machine(machine_code):
60
- print("Esta maquina no esta autorizada")
61
- exit(1)
62
-
63
- # Verificar features
64
- if license_key.F1:
65
- print("Feature Pro activado")
66
-
67
- print(f"Licencia valida hasta {license_key.expires}")
68
- ```
69
-
70
- ## API
71
-
72
- ### `Helpers.GetMachineCode(v=2)`
73
- Genera un machine code único basado en propiedades del hardware. `v=2` es el algoritmo actual (SHA-256 sobre identificadores).
74
-
75
- ### `LicenseKey.load_from_string(rsa_pub_key, content, max_age_days=0)`
76
- Parsea un `.dat` JSON, verifica firma RSA y freshness.
77
-
78
- | Parámetro | Tipo | Descripción |
79
- |---|---|---|
80
- | `rsa_pub_key` | str | XML (.NET) o PEM. Auto-detecta. |
81
- | `content` | str | Contenido del archivo `.dat` |
82
- | `max_age_days` | int | Máx. días desde `signDate`. 0 = ilimitado o usa el del `.dat`. |
83
-
84
- Devuelve un objeto `LicenseKey` o `None` si la validación falla.
85
-
86
- ### Atributos de `LicenseKey`
87
- | Atributo | Tipo |
88
- |---|---|
89
- | `product_id`, `id`, `key`, `notes` | datos básicos |
90
- | `created`, `expires`, `sign_date` | datetimes UTC |
91
- | `period`, `max_no_of_machines`, `max_offline_days` | enteros |
92
- | `F1`..`F8`, `block`, `trial_activation` | flags |
93
- | `activated_machines` | List[ActivatedMachine] |
94
- | `data_objects` | List[DataObject] |
95
- | `customer` | Customer o None |
96
- | `offline_mode` | str (FloatingLease/FloatingManual/Locked) |
97
-
98
- ### `license_key.is_on_right_machine(machine_code)`
99
- Verifica que el machine code esté en `activatedMachines`.
100
-
101
- ### `license_key.has_not_expired()`
102
- Verifica que `expires > now`.
103
-
104
- ### `license_key.has_feature(n)`
105
- Atajo para `getattr(license_key, f'F{n}')`.
106
-
107
- ## Comparación con SDK Cryptolens
108
-
109
- | | Cryptolens SDK | qustomlicensing |
110
- |---|---|---|
111
- | Activate online | ✅ | ❌ (usa requests directamente) |
112
- | Validar .skm/.dat offline | ✅ | ✅ |
113
- | `Helpers.GetMachineCode` | ✅ | ✅ (compatible) |
114
- | `LicenseKey.load_from_string` | ✅ | ✅ (compatible) |
115
- | Tamaño | ~2 MB con deps | ~50 KB |
116
- | Dependencias | `pycryptodome`, `requests` | solo `cryptography` |
117
-
118
- ## Licencia
119
-
120
- Apache-2.0. Basado en código del SDK de Cryptolens (también Apache-2.0).
File without changes
File without changes
File without changes
File without changes