0
# License Management
1
2
PyArmor provides comprehensive license management for controlling access to obfuscated scripts through hardware binding, time-based restrictions, and custom user data. The licensing system enables software vendors to protect their applications and control distribution with flexible restriction mechanisms.
3
4
## Capabilities
5
6
### License Generation
7
8
#### License Key Creation
9
10
Generate license files with custom restrictions and hardware binding for obfuscated scripts.
11
12
```python { .api }
13
def make_license_key(capsule, code: str, filename: str, **kwargs) -> None:
14
"""
15
Generate license key file with specified restrictions.
16
17
Args:
18
capsule: Protection capsule path or object
19
code (str): License registration code
20
filename (str): Output license file path
21
**kwargs: License options
22
- expired (str): Expiration date in YYYY-MM-DD format
23
- bind_disk (str): Bind to hard disk serial number
24
- bind_mac (str): Bind to MAC address
25
- bind_ipv4 (str): Bind to IPv4 address
26
- bind_domain (str): Bind to domain name
27
- bind_file (str): Bind to specific file checksum
28
- enable_period_mode (bool): Enable periodic validation
29
- period (int): Validation period in days
30
- data (str): Custom user data to embed
31
32
Raises:
33
LicenseError: If license generation fails
34
ValueError: If code format is invalid
35
BindingError: If hardware binding fails
36
"""
37
38
def generate_group_license(code: str, count: int, **kwargs) -> list:
39
"""
40
Generate multiple license files for group licensing.
41
42
Args:
43
code (str): Base license code
44
count (int): Number of licenses to generate
45
**kwargs: Group license options
46
- prefix (str): License file name prefix
47
- output (str): Output directory
48
- bind_template (str): Hardware binding template
49
50
Returns:
51
list: List of generated license file paths
52
"""
53
54
def make_trial_license(capsule, days: int, **kwargs) -> str:
55
"""
56
Generate time-limited trial license.
57
58
Args:
59
capsule: Protection capsule
60
days (int): Trial period in days
61
**kwargs: Trial options
62
- features (list): Enabled features for trial
63
- bind_data (str): Custom trial data
64
65
Returns:
66
str: Path to generated trial license
67
"""
68
```
69
70
### Registration Management
71
72
#### Registration Functions
73
74
Handle PyArmor registration codes and license activation for commercial usage.
75
76
```python { .api }
77
def get_registration_code() -> str:
78
"""
79
Get current PyArmor registration code.
80
81
Returns:
82
str: Current registration code or empty string if unregistered
83
"""
84
85
def query_keyinfo(key: str) -> dict:
86
"""
87
Query registration key information from server.
88
89
Args:
90
key (str): Registration key to query
91
92
Returns:
93
dict: Key information including features, expiration, device limits
94
- product (str): Product name
95
- version (str): License version
96
- lictype (str): License type (TRIAL, BASIC, PRO, etc.)
97
- features (list): Enabled features
98
- expired (str): Expiration date
99
- devices (int): Maximum device count
100
- platform (str): Platform restrictions
101
102
Raises:
103
NetworkError: If unable to connect to server
104
KeyError: If key is invalid or not found
105
"""
106
107
def activate_regcode(ucode: str) -> dict:
108
"""
109
Activate PyArmor registration code.
110
111
Args:
112
ucode (str): Registration code from purchase
113
114
Returns:
115
dict: Activation result with license information
116
117
Raises:
118
ActivationError: If activation fails
119
NetworkError: If server communication fails
120
"""
121
122
def register_keyfile(keyfile: str, upgrade: bool = None, legency: bool = False) -> None:
123
"""
124
Register PyArmor using license keyfile.
125
126
Args:
127
keyfile (str): Path to license keyfile (.zip or .txt)
128
upgrade (bool, optional): Upgrade existing license
129
legency (bool): Handle legacy license format
130
131
Raises:
132
RegistrationError: If registration fails
133
FileNotFoundError: If keyfile doesn't exist
134
FormatError: If keyfile format is invalid
135
"""
136
137
def upgrade_license(filename: str) -> dict:
138
"""
139
Upgrade existing license to newer version.
140
141
Args:
142
filename (str): License file to upgrade
143
144
Returns:
145
dict: Upgrade result information
146
"""
147
```
148
149
### Modern Registration System (v8+)
150
151
Enhanced registration management with web integration and group licensing.
152
153
```python { .api }
154
class Register:
155
"""
156
Modern license registration management.
157
"""
158
159
def __init__(self, ctx):
160
"""
161
Initialize register with context.
162
163
Args:
164
ctx (Context): PyArmor context instance
165
"""
166
167
def register_regfile(self, regfile: str) -> None:
168
"""
169
Register using registration file.
170
171
Args:
172
regfile (str): Registration file path
173
"""
174
175
def generate_group_device(self, device_id: int) -> None:
176
"""
177
Generate device file for group licensing.
178
179
Args:
180
device_id (int): Device ID (1-100)
181
"""
182
183
def check_group_license(self) -> dict:
184
"""
185
Check group license status and device allocation.
186
187
Returns:
188
dict: Group license information
189
"""
190
191
class WebRegister:
192
"""
193
Web-based registration with online validation.
194
"""
195
196
def check_request_interval(self) -> None:
197
"""
198
Check if sufficient time has passed since last request.
199
200
Raises:
201
RateLimitError: If too many requests made recently
202
"""
203
204
def register_group_device(self, regfile: str, device: int) -> None:
205
"""
206
Register device in group license online.
207
208
Args:
209
regfile (str): Group registration file
210
device (int): Device ID to register
211
"""
212
213
def request_ci_regfile(self, regfile: str) -> None:
214
"""
215
Request CI/CD pipeline registration file.
216
217
Args:
218
regfile (str): Base registration file
219
"""
220
221
def prepare(self, regfile: str, product: str, upgrade: bool = False) -> tuple:
222
"""
223
Prepare registration with validation.
224
225
Args:
226
regfile (str): Registration file path
227
product (str): Product name
228
upgrade (bool): Upgrade existing registration
229
230
Returns:
231
tuple: (registration_info, confirmation_message)
232
"""
233
234
def register(self, regfile: str, product: str, group: bool = False) -> None:
235
"""
236
Complete registration process.
237
238
Args:
239
regfile (str): Registration file
240
product (str): Product name
241
group (bool): Group license registration
242
"""
243
244
def upgrade_to_pro(self, regfile: str, product: str) -> None:
245
"""
246
Upgrade license to professional version.
247
248
Args:
249
regfile (str): Registration file
250
product (str): Product name
251
"""
252
```
253
254
### Hardware Binding
255
256
#### Device Information Functions
257
258
```python { .api }
259
def show_hd_info(name: str = None) -> str:
260
"""
261
Display hardware information for binding configuration.
262
263
Args:
264
name (str, optional): Specific hardware component name
265
- 'disk': Hard disk serial numbers
266
- 'mac': MAC addresses
267
- 'ipv4': IPv4 addresses
268
- 'domain': Domain name
269
- 'cpu': CPU information
270
271
Returns:
272
str: Formatted hardware information
273
274
Example output:
275
Hardware information:
276
Disk serial number: ABCD1234567890
277
MAC address: 00:11:22:33:44:55
278
IPv4 address: 192.168.1.100
279
Domain name: example.com
280
"""
281
282
def get_bind_key(hdtype: str, name: str = None) -> str:
283
"""
284
Get hardware binding key for specific device.
285
286
Args:
287
hdtype (str): Hardware type ('disk', 'mac', 'ipv4', 'domain')
288
name (str, optional): Specific device name
289
290
Returns:
291
str: Hardware binding key
292
"""
293
294
def validate_bind_key(key: str, hdtype: str) -> bool:
295
"""
296
Validate hardware binding key against current system.
297
298
Args:
299
key (str): Hardware binding key to validate
300
hdtype (str): Expected hardware type
301
302
Returns:
303
bool: True if key matches current hardware
304
"""
305
```
306
307
### License Validation
308
309
#### Runtime License Checking
310
311
```python { .api }
312
def check_license(license_file: str) -> dict:
313
"""
314
Validate license file and return restrictions.
315
316
Args:
317
license_file (str): Path to license file
318
319
Returns:
320
dict: License validation result
321
- valid (bool): License validity
322
- expired (str): Expiration date
323
- devices (list): Bound device information
324
- features (list): Enabled features
325
- data (str): Custom user data
326
327
Raises:
328
LicenseError: If license is invalid or corrupted
329
ExpiredError: If license has expired
330
BindingError: If hardware binding fails
331
"""
332
333
def enable_period_mode(license_file: str, period: int) -> None:
334
"""
335
Enable periodic license validation.
336
337
Args:
338
license_file (str): License file to modify
339
period (int): Validation period in days
340
"""
341
342
def validate_periodic_license() -> bool:
343
"""
344
Perform periodic license validation check.
345
346
Returns:
347
bool: True if validation passes
348
349
Raises:
350
ValidationError: If periodic validation fails
351
NetworkError: If unable to contact validation server
352
"""
353
```
354
355
## Usage Examples
356
357
### Basic License Generation
358
359
```python
360
from pyarmor import utils
361
362
# Generate capsule
363
capsule = utils.make_capsule()
364
365
# Create basic license
366
utils.make_license_key(
367
capsule,
368
"MYAPP-USER001",
369
"licenses/user001.lic"
370
)
371
372
# Create time-limited license
373
utils.make_license_key(
374
capsule,
375
"MYAPP-TRIAL",
376
"licenses/trial.lic",
377
expired="2024-12-31"
378
)
379
```
380
381
### Hardware Binding
382
383
```python
384
# Show available hardware information
385
print(utils.show_hd_info())
386
387
# Create MAC-bound license
388
utils.make_license_key(
389
capsule,
390
"MYAPP-MACHINE001",
391
"licenses/machine001.lic",
392
bind_mac="00:11:22:33:44:55"
393
)
394
395
# Create disk-bound license with expiration
396
utils.make_license_key(
397
capsule,
398
"MYAPP-WORKSTATION",
399
"licenses/workstation.lic",
400
bind_disk="ABCD1234567890",
401
expired="2025-06-30"
402
)
403
404
# Multiple binding constraints
405
utils.make_license_key(
406
capsule,
407
"MYAPP-SECURE",
408
"licenses/secure.lic",
409
bind_mac="00:11:22:33:44:55",
410
bind_ipv4="192.168.1.100",
411
bind_domain="company.com",
412
expired="2024-12-31"
413
)
414
```
415
416
### Group Licensing
417
418
```python
419
from pyarmor.register import generate_group_license
420
421
# Generate 10 licenses for group deployment
422
licenses = generate_group_license(
423
"MYAPP-GROUP001",
424
10,
425
prefix="dept_license_",
426
output="licenses/group/",
427
expired="2025-12-31"
428
)
429
430
for lic_path in licenses:
431
print(f"Generated: {lic_path}")
432
```
433
434
### Periodic Validation
435
436
```python
437
# Create license with periodic checking
438
utils.make_license_key(
439
capsule,
440
"MYAPP-SUBSCRIPTION",
441
"licenses/subscription.lic",
442
enable_period_mode=True,
443
period=30, # Check every 30 days
444
expired="2025-12-31"
445
)
446
447
# Enable periodic mode on existing license
448
utils.enable_period_mode("licenses/subscription.lic", 7) # Weekly checks
449
```
450
451
### Registration Management
452
453
```python
454
from pyarmor import register
455
456
# Check current registration
457
reg_code = register.get_registration_code()
458
if reg_code:
459
print(f"Registered with: {reg_code}")
460
else:
461
print("PyArmor is not registered")
462
463
# Query key information
464
try:
465
key_info = register.query_keyinfo("PYARMOR-KEY-XXXX")
466
print(f"Product: {key_info['product']}")
467
print(f"License Type: {key_info['lictype']}")
468
print(f"Features: {key_info['features']}")
469
print(f"Expires: {key_info['expired']}")
470
except Exception as e:
471
print(f"Key query failed: {e}")
472
473
# Register PyArmor
474
register.register_keyfile("pyarmor-regfile-xxxx.zip")
475
```
476
477
### Modern Registration (v8+)
478
479
```python
480
from pyarmor.cli.register import Register, WebRegister
481
from pyarmor.cli.context import Context
482
483
ctx = Context()
484
485
# Local registration
486
reg = Register(ctx)
487
reg.register_regfile("pyarmor-regfile-xxxx.zip")
488
489
# Web registration
490
web_reg = WebRegister(ctx)
491
web_reg.check_request_interval() # Rate limiting
492
493
# Register with product binding
494
info, msg = web_reg.prepare("pyarmor-regcode-xxxx.txt", "MyProduct")
495
print(msg)
496
web_reg.register("pyarmor-regcode-xxxx.txt", "MyProduct")
497
```
498
499
### License Validation in Applications
500
501
```python
502
from pyarmor.utils import check_license
503
504
try:
505
# Validate license at application startup
506
license_info = check_license("app.lic")
507
508
if license_info['valid']:
509
print("License valid")
510
print(f"Expires: {license_info['expired']}")
511
512
# Check custom data
513
if 'data' in license_info:
514
print(f"User data: {license_info['data']}")
515
516
else:
517
print("Invalid license")
518
exit(1)
519
520
except Exception as e:
521
print(f"License validation failed: {e}")
522
exit(1)
523
524
# Periodic validation
525
if not validate_periodic_license():
526
print("Periodic validation failed")
527
exit(1)
528
```
529
530
## Error Handling
531
532
```python
533
from pyarmor.utils import LicenseError, BindingError, ExpiredError
534
from pyarmor.register import RegistrationError, NetworkError
535
536
try:
537
# License operations
538
utils.make_license_key(capsule, "CODE", "license.lic",
539
bind_mac="invalid-mac")
540
541
except LicenseError as e:
542
print(f"License generation failed: {e}")
543
544
except BindingError as e:
545
print(f"Hardware binding failed: {e}")
546
547
try:
548
# Registration operations
549
register.register_keyfile("keyfile.zip")
550
551
except RegistrationError as e:
552
print(f"Registration failed: {e}")
553
554
except NetworkError as e:
555
print(f"Network error during registration: {e}")
556
557
try:
558
# License validation
559
license_info = check_license("app.lic")
560
561
except ExpiredError as e:
562
print(f"License expired: {e}")
563
564
except BindingError as e:
565
print(f"Hardware binding mismatch: {e}")
566
```