> ## Documentation Index
> Fetch the complete documentation index at: https://help.cryptolens.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Python 2 / IronPython: LicenseKey

> The parsed license object, including saving and loading signed responses.

Python 2 / IronPython implementation. [Reviewed source revision](https://github.com/Cryptolens/cryptolens-python/tree/8f38b5a37580f2aba1c9374f581cdc85e251950f).

```python theme={null}
from cryptolens_python2 import LicenseKey
```

You normally receive this object from `Key.activate`, `Key.get_key` or `LicenseKey.load_from_string`. Constructing or parsing a license object yourself does not establish that its signature is valid.

## Properties

| Property | Meaning |
| - | - |
| `product_id` | The numeric product ID. |
| `id` | The numeric license ID. |
| `key` | The license-key string. |
| `created` | Creation time as a Python datetime converted using the device's local timezone. |
| `expires` | Expiry time as a Python datetime converted using the device's local timezone. |
| `period` | The license period in days. |
| `f1` | Whether feature 1 is enabled. |
| `f2` | Whether feature 2 is enabled. |
| `f3` | Whether feature 3 is enabled. |
| `f4` | Whether feature 4 is enabled. |
| `f5` | Whether feature 5 is enabled. |
| `f6` | Whether feature 6 is enabled. |
| `f7` | Whether feature 7 is enabled. |
| `f8` | Whether feature 8 is enabled. |
| `notes` | The license notes. |
| `block` | Whether the returned license is blocked. |
| `global_id` | The globally unique license identifier. |
| `customer` | The API's customer data as a dictionary, or `None`. |
| `activated_machines` | A list of `ActivatedMachine` objects, or `None`. |
| `trial_activation` | Whether trial activation is configured. |
| `max_no_of_machines` | The machine limit; `0` disables machine registration. |
| `allowed_machines` | The allowed-machine value (whitelist) as received from the API. |
| `data_objects` | A list of API dictionaries, or `None`. Property names such as `Name` and `StringValue` retain their API casing. |
| `sign_date` | The signed timestamp as a Python datetime converted using the device's local timezone. |
| `raw_response` | The original `Response` envelope used when saving the signed response. |

<a id="cryptolens_python2.LicenseKey.from_response" />

## from\_response

Decode a response envelope into a license object.

```python theme={null}
LicenseKey.from_response(response)
```

### Parameters

| Parameter | Default | Meaning |
| - | - | - |
| `response` | Required | A `Response` object containing the signed-response envelope. |

### Result

Returns a `LicenseKey` object, including converted dates and activation objects.

Malformed, incomplete or unconvertible data can raise an exception. Do not call this parser as a substitute for verified activation or `load_from_string`.

### Checks

Decodes and parses the data; it does not verify the signature. Use `Key.activate`, `Key.get_key` or `load_from_string` when you need the SDK to verify it.

<a id="cryptolens_python2.LicenseKey.save_as_string" />

## save\_as\_string

Serialize the license's original signed response.

```python theme={null}
license_key.save_as_string()
```

### Result

Returns a JSON string that can be saved and later passed to `load_from_string`.

Requires a usable `raw_response`; an object constructed without it can raise an exception.

### Checks

Preserves the original signed response and signed timestamp. It does not create a new signature or restart the offline allowance.

### Example

After successful activation, `license_key` is the first item of the result. This example saves its original signed response.

```python theme={null}
with open("licensefile.skm", "w") as license_file:
    license_file.write(license_key.save_as_string())
```

<a id="cryptolens_python2.LicenseKey.load_from_string" />

## load\_from\_string

Load and verify a previously saved signed response.

```python theme={null}
LicenseKey.load_from_string(rsa_pub_key, string, signature_expiration_interval=-1)
```

### Parameters

| Parameter | Default | Meaning |
| - | - | - |
| `rsa_pub_key` | Required | Your account's complete RSA public key in XML form. |
| `string` | Required | The serialized string previously returned by `save_as_string()`. |
| `signature_expiration_interval` | `-1` | The maximum age in days. Positive values enable the age check; `0` and negative values disable it. |

### Result

Returns a `LicenseKey` object, or `None` when it cannot load and verify the data.

Returns `None` for malformed data, an invalid RSA key, a failed signature, a parsing failure, or a response older than a positive age limit.

### Checks

Verifies the license signature. A positive `signature_expiration_interval` also checks age from the signed timestamp using the device clock; the default `-1` disables that age check. It does not enforce license expiry, machine binding, product or feature requirements.

### Example

Replace the RSA public key placeholder with your account's key. Here, `3` is the maximum signed-response age in days.

```python theme={null}
with open("licensefile.skm", "r") as license_file:
    license_key = LicenseKey.load_from_string(
        "YOUR_RSA_PUBLIC_KEY", license_file.read(), 3)
if license_key is None:
    print("Could not load a verified response within the age limit.")
```

## FAQ

<AccordionGroup>
  <Accordion title="Does Saving the File Restart Its Offline Allowance?" id="does-saving-the-file-restart-its-offline-allowance">
    No. The age check uses the signed timestamp in the response. Copying or saving the file does not change that timestamp.
  </Accordion>

  <Accordion title="Does the Age Check Prevent Clock Rollback?" id="does-the-age-check-prevent-clock-rollback">
    No. The signature protects the timestamp from being edited, but the SDK compares it with the device clock. Changing that clock can affect the age check. See [offline verification](/examples/offline-verification) for the limitation and the other checks your application needs.
  </Accordion>
</AccordionGroup>

[Python SDK Reference](/libraries/python-api)
