# Hardware ID generation

A hardware ID is a unique device identifier used to bind a license to that device, which helps to avoid transferring licenses to other devices.

This tutorial will help you learn more about hardware ID algorithms provided by LicenseSpring SDKs and choose the optimal hardware ID algorithm for your application.

### Prerequisites

{% stepper %}
{% step %}

### Initialize LicenseManager

Initialized `LicenseManager` (or `LicenseHandler`) with your configuration using the appropriate settings.
{% endstep %}

{% step %}

### Activate a license

Activated a license of any type.
{% endstep %}

{% step %}

### Implement checks

Implemented routine local and online checks within the application.
{% endstep %}
{% endstepper %}

### SDK-independent hardware ID generator library

We provide a SDK-independent hardware ID generator library as a dynamically-loadable shared library. This is a part of our on-going process to standardize licensing across all our SDKs. The library is integrated into:

* C++ SDK since v7.42.0,
* C# SDK since v7.34.0,
* Java SDK since v2.25.1,
* Go SDK since the v2 rewrite,
* Python SDK since v2.0.0,
* JavaScript SDK since initial release.

Swift and Android SDK use custom hardware ID generation algorithms as they are mostly tied to platforms with straightforward hardware ID generation.

Each SDK packages the shared library to be easily deployable either manually or through popular repositories and package managers. The library is released for multiple operating systems and architectures:

* For **Windows**, we provide binaries built for x64, x86 and ARM64 architectures, built with a VS2022 MSVC toolchain. We also provide a version built GCC 8.1 from Qt's distribution of MinGW.
* For **macOS**, we provide binaries built for the x86\_64 architecture (min. required version 10.12) and arm64 architecture (min. required version 11.0).
* For **Linux**, we provide binaries built for i686, x86\_64, armv7l (i.e. armhf), ppc64le, s390x and riscv architectures, linked against either glibc 2.27 or musl libc.
* For **iOS**, we provide an XCFramework, which includes slices for `iphoneos` (arm64) and `iphonesimulator` (arm64 & x86\_64). The slices are shipped as static libraries, which means the framework must be statically linked into the consumer library or application.

#### Algorithms list

The library exports an enum of available algorithms. Algorithm names in each SDK that FFIs into the library can easily be mapped to an algorithm in the following list:

```cpp
enum class HardwareIdAlgorithm {
    /**
     * @brief Default hardware ID calculation algorithm.
     *
     * @details Computes a default hardware identifier.
     * On Windows, computes HardwareIdAlgorithm::WindowsComputerSystemProductId.
     * On macOS, the algorithm uses `gethostuuid` to compute a unique machine
     * identifier.
     * On Linux, computes HardwareIdAlgorithm::LinuxMachineId.
     */
    Default,

    /**
     * @brief Alternative hardware ID algorithm for Windows.
     *
     * @details Computes a hardware fingerprint based on CPU, disk, and
     * motherboard.
     */
    WindowsHardwareFingerprintId,

    /**
     * @brief Default hardware ID algorithm for Windows.
     *
     * @details Gets the UUID of the Windows machine using the Computer System
     * Product UUID. See [Microsoft
     * Docs](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-computersystemproduct).
     */
    WindowsComputerSystemProductId,

    /**
     * @brief Alternative hardware ID algorithm for Windows.
     *
     * @details Retrieves `SOFTWARE\Microsoft\Cryptography\MachineGUID` from
     * the Windows registry.
     */
    WindowsCryptographyId,

    /**
     * @brief Default hardware ID algorithm for Linux.
     *
     * @details Reads `/etc/machine-id` and `/var/lib/dbus/machine-id` in that
     * order. If these files don't exist, a new UUID is written to the
     * filesystem.
     */
    LinuxMachineId,

    /**
     * @brief Cloud platforms instance hardware ID algorithm.
     *
     * @details Retrieves the instance ID for cloud platforms, including Azure,
     * AWS, and GCP.
     */
    CloudPlatformsId
};
```

The full package can be downloaded on the [**hardware ID generator download page**](https://sdk.licensespring.com/#hardware_id_generator/).

#### Configuration

When you have chosen the algorithm, set it to the **ExtendedOptions**.

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

```cpp
LicenseSpring::ExtendedOptions options;

// DeviceIDAlgorithm::HardwareIdGeneratorDefault is the default 
// value for the new hardware ID generator library
options.setDeviceIdAlgorithm(HardwareIdGeneratorDefault);
```

{% endtab %}

{% tab title="C#" %}

```csharp
var options = new ExtendedOptions();
options.DeviceIdAlgorithm = DeviceIDAlgorithm.AutoId;
```

{% endtab %}

{% tab title="Swift" %}

```swift
configuration.hardwareID = generateMyOwnCustomID()
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseSpringConfiguration config = LicenseSpringConfiguration.builder()
  .identityProvider(HardwareIdStrategy.AUTO_HARDWARE_ID)
  .build();
```

{% endtab %}

{% tab title="Python" %}

```python
from licensespring.licensefile.config import Configuration
from licensespring.hardware import HardwareIdProviderSource

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,hardware_id_provider=HardwareIdProviderSource
```

{% endtab %}
{% endtabs %}

SDKs also allow overriding the hardware ID. For instance, you can use the MAC address as the hardware ID:

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

```cpp
LicenseSpring::ExtendedOptions options;
options.setHardwareID(options.getNetworkInfo().mac());
```

{% endtab %}

{% tab title="C#" %}

```csharp
var configuration = new LicenseSpring.Configuration();
var options = new LicenseSpring.ExtendedOptions();
options.HardwareID = configuration.MACAddress;
configuration.ExtendedOptions = options;
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
lm_config := license_manager.LicenseManagerBasicConfiguration{
				OAuth:             false,
				ApiKey:            "your-api-key",
				SharedKey:         "your-shared-key",
				ProductCode:       "your-product-code",
				AuthData:          auth.FromKey("LICENSE-KEY"),
			}

lm, _ := license_manager.NewLicenseManager(
    lm_config,
    license_manager.WithHardwareId("your-HW-ID"),
)
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseSpringConfiguration config = LicenseSpringConfiguration.builder()
  .identityProvider(customIdentityProvider)
  .build();
```

{% endtab %}

{% tab title="Python" %}

```python
class CustomHardwareIdProvider(HardwareIdProvider):
    def get_id(self):
        return "your_custom_hwid"

conf = Configuration(product="your_product_key",api_key="your_api_key",
                   shared_key="your_shared_key",file_key=key,file_iv=iv,
                   hardware_id_provider=CustomHardwareIdProvider)
```

{% endtab %}
{% endtabs %}

#### Relink License

The license relinking method can be useful when the hardware ID algorithm has been changed. Despite the license belonging to the current device, the local check will throw **DeviceNotLicensedException** since different algorithms produce different hardware IDs. In this case you can relink the license to the new hardware ID.

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

```cpp
try
{
  license->localCheck();
}
catch(const DeviceNotLicensedException& ex)
{
  std::cout << "Trying to upgrade to newer hardware ID algorithm..." << std::endl;
  license = m_licenseManager->relinkLicense(HardwareIdGeneratorWindowsComputerSystemProductId);
  std::cout << "License successfully linked to new hardware ID." << std::endl;
  return;
}

// the C++ SDK also provides unlinkFromDevice and isLicenseBelongsToThisDevice methods
// unlinkFromDevice check if the license is tied to the current device, and deactivates it
// isLicenseBelongsToThisDevice checks if the license belongs to hardware ID computed by
// the passed DeviceIDAlgorithm
```

{% endtab %}

{% tab title="C#" %}

```csharp
try
{
  license.LocalCheck();
}
catch( DeviceNotLicensedException ex )
{
  Console.WriteLine( "Trying to upgrade to a newer device id algorithm..." );
  license = manager.RelinkLicense( DeviceIDAlgorithm.Gen3 );
  Console.WriteLine( "License successfully linked to new device id.\n" );
  return;
}
```

{% endtab %}
{% endtabs %}

This method checks if the old hardware ID of the license matches any of the IDs generated by different algorithms. When it finds the correct algorithm, it deactivates the license with the old ID and activates it again using the new algorithm. This method throws the same exceptions as a regular license activation.

### Recovering WMI

WMI repository issues can occur on Windows 10 and Windows 11. It's useful to know how to fix them since most of the hardware ID algorithms use WMI.

To check if the WMI repository is consistent, open Command Prompt with administrator privileges and run `winmgmt /verifyrepository`.

If you don't get a message stating `WMI repository is consistent`, proceed with the next steps.

In the same Command Prompt window, run the three following commands:

* <pre class="language-powershell" data-line-numbers><code class="lang-powershell">cd C:\Windows\system32\wbem
  mofcomp.exe CIMWin32.mof
  regsvr32 cimwin32.dll
  </code></pre>

You can also try to recover WMI by running the `winmgmt /resetrepository` in Command Prompt with admin privileges. See [**this StackOverflow thread**](https://stackoverflow.com/a/71535626) for more information and [this Microsoft community discussion](https://techcommunity.microsoft.com/t5/ask-the-performance-team/wmi-repository-corruption-or-not/ba-p/375484) for risks related to running the command.


---

# Agent Instructions: 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:

```
GET https://docs.licensespring.com/sdks/tutorials/best-practices/hardware-id-generation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
