Home / Docs / Licensing

Licensing

Create flexible, secure licenses for your customers. Control where, when, and how your encrypted applications can run.

How Licenses Work

A PurePHPEncryptor license is a signed file (with .ppe extension) that contains:

The license file is required to run encrypted applications. During runtime, the encrypted code validates the license before decryption. If any constraint fails (wrong server, expired, etc.), the application refuses to run.

Hardware Binding

Lock licenses to specific servers to prevent unauthorized copying and redistribution.

Hostname Binding

The most common binding method. Locks the license to a specific hostname:

bash
ppe license:generate \
    --licensee="Acme Corp" \
    --hostname=app.acme.com \
    --output=acme.ppe

The license will only work on a server where gethostname() returns app.acme.com.

IP Address Binding

Lock to a specific IP address:

bash
ppe license:generate \
    --licensee="Acme Corp" \
    --ip=203.0.113.50 \
    --output=acme.ppe

Dynamic IPs: IP binding is best for servers with static IPs. For cloud environments with dynamic IPs, use hostname binding instead.

MAC Address Binding

Lock to a specific network interface:

bash
ppe license:generate \
    --licensee="Acme Corp" \
    --mac=00:1A:2B:3C:4D:5E \
    --output=acme.ppe

Multiple Constraints

Combine constraints for stronger protection. All constraints must match:

bash
ppe license:generate \
    --licensee="Acme Corp" \
    --hostname=app.acme.com \
    --ip=203.0.113.50 \
    --output=acme.ppe

Time Limits

Control the validity period of licenses for subscriptions, trials, or annual renewals.

Expiration Date

Set an absolute or relative expiration:

bash
# Relative expiration (from now)
ppe license:generate \
    --licensee="Trial User" \
    --expires=+14d \
    --output=trial.ppe

# Absolute expiration
ppe license:generate \
    --licensee="Annual License" \
    --expires=2026-01-15 \
    --output=annual.ppe

Supported relative formats:

Format Example Meaning
+Nd +30d 30 days from now
+Nw +2w 2 weeks from now
+Nm +6m 6 months from now
+Ny +1y 1 year from now

Not-Before Date

Prevent licenses from being used before a specific date (useful for pre-generating licenses):

bash
ppe license:generate \
    --licensee="Future Customer" \
    --not-before=2025-03-01 \
    --expires=2026-03-01 \
    --output=future.ppe

Online Validation

For maximum control, enable online license validation. The encrypted application will contact your server to verify the license before running.

Enable Online Validation

bash
ppe license:generate \
    --licensee="Enterprise Customer" \
    --hostname=app.enterprise.com \
    --validate-url=https://licenses.yourcompany.com/validate \
    --output=enterprise.ppe

Validation Endpoint

Your validation endpoint receives a POST request with the license ID and hardware fingerprint:

json
{
    "license_id": "ent-12345",
    "fingerprint": "sha256:abc123...",
    "hostname": "app.enterprise.com",
    "ip": "203.0.113.50",
    "timestamp": "2025-01-15T10:30:00Z"
}

Your server should respond with:

json
// Valid license
{ "valid": true }

// Revoked or invalid license
{ "valid": false, "reason": "License revoked" }

Offline Grace Period

To prevent outages if your validation server is temporarily unreachable, set a grace period:

bash
ppe license:generate \
    --licensee="Enterprise Customer" \
    --validate-url=https://licenses.yourcompany.com/validate \
    --validate-grace=24h \
    --output=enterprise.ppe

With a 24-hour grace period, the application will continue to run for up to 24 hours if it can't reach your validation server.

Custom Metadata

Embed custom data in licenses for version limits, feature flags, or any other purpose:

bash
ppe license:generate \
    --licensee="Pro Customer" \
    --meta="plan:professional" \
    --meta="max_users:50" \
    --meta="features:api,reports,exports" \
    --output=pro.ppe

Access metadata in your application:

php
<?php
$license = ppe_license();

if ($license->meta('plan') === 'professional') {
    // Enable pro features
}

$maxUsers = (int) $license->meta('max_users', 10);
$features = explode(',', $license->meta('features', ''));

License Management Tips

Best Practices:

  • Always use hardware binding for production licenses
  • Use hostname binding for cloud servers with dynamic IPs
  • Set reasonable expiration dates to encourage renewals
  • Keep a database of issued licenses for tracking and revocation
  • Use online validation for high-value enterprise customers