> For the complete documentation index, see [llms.txt](https://docs.licensespring.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.licensespring.com/sdks/tutorials/advanced-usage/security-and-cryptographic-providers.md).

# Security and Cryptographic Providers

LicenseSpring prioritizes software security and empowers vendors to bolster their software security.

While offering a default cryptographic service provider, we enable software vendors to adapt it according to their needs.

This guide outlines changing cryptographic providers, reasons for the change, and a comprehensive security best practices tutorial.

### Prerequisites

* Completed the [**Getting Started**](broken://pages/7049c234acf9cb81aabf96249c3b5178911a4986) Tutorial, specifically:
  * Initialized `LicenseManager` (or `LicenseHandler`) with your configuration using the appropriate settings.
  * Created a `LicenseID` using either `LicenseID::fromKey` or `LicenseID::fromUser` function, depending on the activation method you prefer.
  * Implemented basic license management, including license activations, deactivations, and both online and local license checks.

### Cryptographic Providers

A cryptographic provider, often referred to as a cryptographic library or module, is a software component that offers a collection of cryptographic algorithms and functions to secure data through encryption, decryption, digital signatures, hashing, and more.

#### Default Cryptographic Provider

LicenseSpring SDKs use a license file stored locally on the user's device for the purpose of validating their license status. This file serves as a repository for crucial license-related information as well as user data.

To maintain the security of this data, every time a license file is generated, it undergoes encryption through our proprietary cryptographic provider.

Subsequently, during the program's execution, the cryptographic provider facilitates the decryption of the license file, rendering the enclosed data usable within the program.

For information on when default encryption and decryption occurs, see [**Custom License Storage**](/sdks/tutorials/advanced-usage/custom-license-storage.md).

Both the C++ and .NET SDKs use a modern authenticated-encryption provider by default:

{% hint style="warning" %}
Since v8.0.0, both the C++ and the .NET SDK use a more secure `GcmCryptoProvider` and `CryptoProviderV2` respectively (both AES-256-GCM) as the default cryptographic provider.
{% endhint %}

#### Changing Cryptographic Provider

Our C++ and .NET SDKs offer diverse options for enhancing security by customizing the default cryptographic provider. You have the flexibility to modify the default cryptographic provider by implementing the designated interface found in both the C++ and .NET SDKs. However, for a more straightforward approach, you can maintain the default cryptographic provider and instead alter the salt and key used.

In simpler terms, a key functions similarly to a password, enabling data encryption and decryption. On the other hand, a salt is appended to your data to increase the complexity of decryption. This adjustment lets you distinguish your encryption method from the default approach in a straightforward manner.

{% hint style="warning" %}
We highly recommend setting a unique salt for all new products that are using LicenseSpring. This way, encryption will be different for each product.
{% endhint %}

While we entrust the implementation of the interface to developers, as it depends on their encryption preferences, we will demonstrate here how to establish the salt and key for the default cryptographic provider. It's advisable to configure the cryptographic provider early in your application, alongside the other license settings, to ensure that it's in place before activation. This proactive approach ensures the encryption of your local license file using the designated cryptographic provider.

The following shows how to specifically set the key and salt for various SDKs:

{% tabs %}
{% tab title="C++" %}

```cpp
ExtendedOptions options;
options.getCryptoProvider()->setKey("password");
options.getCryptoProvider()->setSalt("SALT");

auto configuration = Configuration::Create(
        EncryptStr("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"),
        EncryptStr("XXXXXXXXX-XXXXX-XXXXXXXXXXXXX_XXXXXX_XXXXXX"),
        EncryptStr("XXXXXX"),
        "NAME", "VERSION", options );
        
auto licenseManager = LicenseManager::create(pConfiguration);
```

{% endtab %}

{% tab title="C#" %}
Since SDK v8.0.0 the .NET SDK encrypts the local license file with AES-256-GCM (authenticated encryption) using the LSLF file format. Keys are derived with PBKDF2-HMAC-SHA256. This is the default, you don't have to configure anything to get it.

Existing license files written by older SDK versions are detected and migrated to the new LSLF format automatically the first time they are read — no action required.

You can still customize the encryption by setting the cryptographic key and salt on the default provider:

```csharp
var options = new LicenseSpring.ExtendedOptions();

var configuration = new LicenseSpring.Configuration(
            apiKey: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
            sharedKey: "XXXXXXXXX-XXXXX-XXXXXXXXXXXXX_XXXXXX_XXXXXX", 
            productCode: "XXXXXX", 
            appName: "NAME",
            appVersion: "VERSION",
            extendedOptions: options );
            
// PBKDF2 password input. Defaults to your Shared key if not set.
configuration.CryptoProvider.Key = "KEY";

// OPTIONAL. Must be a Base64-encoded 16-byte value. 
// The value here is just a sample, make sure to generate your own value!
configuration.CryptoProvider.Salt = "aN149wGIDHieafxsgptuuA==";

var licenseManager = LicenseManager.GetInstance();

licenseManager.Initialize( configuration );
```

The Salt property changed. With the current default provider (CryptoProviderV2), Salt must be a Base64-encoded, exactly 16-byte value. Any other string (e.g. a plain word) is ignored and a fresh random salt is generated and stored in the file header instead. If you don't set Salt, the SDK generates a secure random salt per file automatically — this is the recommended approach for new products. We highly recommend not reusing salts across products.

Backward compatibility

* Existing license files keep working. License files written by older SDK versions are detected automatically and migrated to the new LSLF format the first time they are read — no action required.
* Using the legacy provider. If you specifically need the previous AES-CBC behavior, you can assign the legacy provider explicitly. It implements the same ICryptoProvider interface, and its Salt accepts any free-form string:

{% code overflow="wrap" %}

```csharp
configuration.CryptoProvider = 
        new LicenseSpring.CryptoProvider( key: "KEY", salt: "SALT" );
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}

````swift
/// LicenseCryptor is protocol declared in SDK to implement custom license encryption routines.
///
/// ```
/// @objc
/// public protocol LicenseCryptor {
///     func encrypt(_ data: Data) -> Data?
///     func decrypt(_ data: Data) -> Data?
/// }
/// ```

struct MyCryptor: LicenseCryptor {
    func decrypt(_ data: Data) -> Data? {
        ...
        return decrypted
    }
    
    func encrypt(_ data: Data) -> Data? {
        ...
        return encrypted
    }
}
configuration.licenseCryptor = MyCryptor()
````

{% endtab %}

{% tab title="Python" %}

```python
## SETUP (ONLY ONCE)
from licensespring.licensefile.default_crypto import DefaultCryptoProvider
from licensespring.licensefile.config import Configuration
from licensespring.licensefile.license_manager import LicenseManager

password = "YOUR_PASSWORD"
salt = "YOUR_SALT"

crypto = DefaultCryptoProvider()

key = crypto.derive_key(password=key_password,salt=key_salt)
iv = crypto.generate_random_iv()

conf = Configuration(product="your_product_key",api_key="your_api_key",
                   shared_key="your_shared_key",file_key=key,file_iv=iv,
                   is_guard_file_enabled=True)
                   
manager = LicenseManager(conf)
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
	storage := &data_handler.DefaultFileStorage{}
	crypto := crypto_provider.DefaultCryptoProvider{}
	if useOAuth {
		crypto.SetKey(config_file.CryptoProviderKey)
	} else {
		crypto.SetKey(config_file.SharedKey)
	}
	storage.SetCryptoProvider(&crypto)

	c := license_handler.LicenseHandlerConfig{
		ApiKey:      config_file.ApiKey,
		SharedKey:   config_file.SharedKey,
		ProductCode: productCode,
		AuthData:    auth.FromKey(productAuth.LicenseKey),
		OAuth:       useOAuth,
		Verbose:     logger.VERBOSE,
		Storage:     storage,
	}

	lh, err := license_handler.NewLicenseHandler(c)
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Note: After this code snippet, the rest of your program that uses `licenseManager`, including activation and file reading, will use this cryptographic provider for encryption/decryption.
{% endhint %}

In the C++ SDK, there is a setter for `CryptoProvider`:

```cpp
options.overrideCryptoProvider(cryptoProvider);
```

{% hint style="info" %}
Note: If the crypto provider is not set, then the default crypto provider will be used.
{% endhint %}

#### Why Change Cryptographic Provider?

Introducing a customized encryption and decryption algorithm is relevant if your product already employs a specific encryption algorithm that you wish to maintain uniform across your software, including licensing components.

Moreover, developers have the liberty to adopt this approach if they hold reservations about utilizing an external encryption algorithm and instead prefer to develop and integrate their own encryption methodology.

This level of autonomy empowers developers to align encryption practices with their individual security considerations and preferences.

### Other Security Features

#### Encrypting Strings

In C++, the potential exists to extract strings from an application after it has been compiled.

This can potentially expose sensitive information, such as API keys, shared keys, management keys, product codes, and various other strings of value. This vulnerability underscores the importance of safeguarding these strings.

Fortunately, the C++ SDK offers a solution: the `EncryptStr()` method encrypts these strings during compile-time and decrypts them during run-time.

Embracing this method is highly advisable for constant strings that necessitate shielding from user access.

By employing this approach, you can significantly enhance the security of your application's sensitive information, ensuring that these strings remain well-protected throughout the application's lifecycle.

```cpp
auto configuration = Configuration::Create(
        EncryptStr("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"),
        EncryptStr("XXXXXXXXX-XXXXX-XXXXXXXXXXXXX_XXXXXX_XXXXXX"), 
        EncryptStr("XXXXXX" ),
        "NAME", "VERSION", options);
```

#### Logging

While logging serves as a valuable tool for debugging purposes, it holds utmost significance to disable logging in your release build. Failing to do so could potentially expose users to any information that has been logged. The nature of this information can encompass a wide array of data.

For a comprehensive understanding of the type of information that could be at risk, we recommend referring to our [**Logging Tutorial**](broken://pages/f47b33e5d0e119ff9848958cb4d96ac2bf7229da).

By deactivating logging in your release build, you take a crucial step toward safeguarding user privacy and preventing unintended exposure of sensitive data. This practice contributes to the overall security and integrity of your software product.

#### License Security

Implementing license checks, whether conducted offline or online, during both application opening and closing is highly advisable.

These checks play a pivotal role in verifying the ongoing validity of a license and ensuring its integrity remains intact.

Such measures are especially effective in thwarting potential tampering attempts, such as altering the date to extend license validity artificially or transferring an activated license file to an unauthorized device lacking the corresponding license.

#### Air-Gapped Licensing

In zero-trust networks, where security is a top priority and trust assumptions are minimized, adopting [**Air-Gapped Licensing**](broken://pages/b3b0fa878d0bf76ab0b419e272fe5e34f69e7642) can offer substantial advantages.

Air-gapped licensing involves keeping the licensing process entirely isolated from external networks and internet connectivity. This approach enhances security by reducing the potential attack surface and preventing unauthorized access to licensing components.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.licensespring.com/sdks/tutorials/advanced-usage/security-and-cryptographic-providers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
