Product key
lastmod 2025-12-15created 2020-11-2633 edits
A product key, or software key, is a specific software-based key for a computer program. It certifies that the copy of the program is genuine. Activation is often done offline by entering the key, but for software such as Windows 8.1, online activation is required to prevent multiple users from using the same key. Not all software has a product key; some distributors use other methods for copy protection, and in some cases, such as free and open-source software, copy protection is not used.
Computer games use product keys to verify that the game has not been copied without authorization. Similarly, playing an online game with two identical product keys at the same time is not allowed.
Categories
- licensepp
- Licensecc - Software licensing, copy protection in C++. It has few dependencies and it's cross-platform.
- Crypto++
- Serial code
- mini-key-server
- Key management (KMS; Key management service; Key management system; Key management server)
Product key
- Cryptolens - Commercial; useful for reviewing the various features you need.
Notes on how to generate and manage product keys.
Guide to choosing a serial key
The most important factor is whether it is unique for every node.
Kubernetes uses the following method.
Verify that the MAC address and product_uuid are unique for every node.
- You can get the MAC address of the network interfaces using the command
ip linkorifconfig -a - The
product_uuidcan be checked with the following command:sudo cat /sys/class/dmi/id/product_uuid
Some virtual machines may have identical values, but hardware devices will very likely have unique addresses. Kubernetes uses these values to uniquely identify the nodes in the cluster. If these values are not unique to each node, the installation process may fail.
See the following.
- Stackoverflow - DMIDecode product_uuid and product_serial.what is the difference?
- KLDP - A question about Linux and Unix UUIDs..
- Stackoverflow - Getting a unique id from a unix-like system
- [Recommended] On IDs
- machine-id - freedesktop.org
- machine-id (AllThatLinux!) - Can be renewed with systemd-machine-id-setup or dbus-uuidgen.
So which one to choose?
Written with reference to the On IDs page, experience, and other sites.
When programming software that cooperates with software running on behalf of other users, other sessions, or other computers, you often need to work with unique identifiers. These can be bound to various hardware and software objects as well as to lifetimes. Often, when people look for such an ID to use, they pick the wrong one because the semantics and lifetime of the ID are not clear. Below is a list of the somewhat hard-to-understand IDs accessible on Linux and how you should or should not use them.
Hardware IDs
-
/sys/class/dmi/id/product_uuid - The main board product UUID, as set by the board manufacturer and encoded in the BIOS DMI information. It may be used to identify a mainboard and only the mainboard. It changes when the user replaces the main board. Also, often enough BIOS manufacturers write bogus serials into it. In addition, it is x86-specific. Access for unprivileged users is forbidden. Hence it is of little general use.
-
CPUID/EAX=3 CPU serial number - A CPU UUID, as set by the CPU manufacturer and encoded on the CPU chip. It may be used to identify a CPU and only a CPU. It changes when the user replaces the CPU. Also, most modern CPUs don't implement this feature anymore, and older computers tend to disable this option by default, controllable via a BIOS Setup option. In addition, it is x86-specific. Hence this too is of little general use.
-
/sys/class/net/*/address - One or more network MAC addresses, as set by the network adapter manufacturer and encoded on some network card EEPROM. It changes when the user replaces the network card. Since network cards are optional and there may be more than one the availability if this ID is not guaranteed and you might have more than one to choose from. On virtual machines the MAC addresses tend to be random. This too is hence of little general use.
-
/sys/bus/usb/devices/*/serial - Serial numbers of various USB devices, as encoded in the USB device EEPROM. Most devices don't have a serial number set, and if they have it is often bogus. If the user replaces his USB hardware or plugs it into another machine these IDs may change or appear in other machines. This hence too is of little use.
There are various other hardware IDs available, many of which you may discover via the ID_SERIAL udev property of various devices, such hard disks and similar. They all have in common that they are bound to specific (replacable) hardware, not universally available, often filled with bogus data and random in virtualized environments. Or in other words: don't use them, don't rely on them for identification, unless you really know what you are doing and in general they do not guarantee what you might hope they guarantee.
Software IDs
-
/proc/sys/kernel/random/boot_id - A random ID that is regenerated on each boot. As such it can be used to identify the local machine's current boot. It's universally available on any recent Linux kernel. It's a good and safe choice if you need to identify a specific boot on a specific booted kernel.
-
gethostname(),/proc/sys/kernel/hostname - A non-random ID configured by the administrator to identify a machine in the network. Often this is not set at all or is set to some default value such as localhost and not even unique in the local network. In addition it might change during runtime, for example because it changes based on updated DHCP information. As such it is almost entirely useless for anything but presentation to the user. It has very weak semantics and relies on correct configuration by the administrator. Don't use this to identify machines in a distributed environment. It won't work unless centrally administered, which makes it useless in a globalized, mobile world. It has no place in automatically generated filenames that shall be bound to specific hosts. Just don't use it, please. It's really not what many people think it is. gethostname() is standardized in POSIX and hence portable to other Unixes.
- IP Addresses returned by SIOCGIFCONF or the respective Netlink APIs
- These tend to be dynamically assigned and often enough only valid on local networks or even only the local links (i.e. 192.168.x.x style addresses, or even 169.254.x.x/IPv4LL). Unfortunately they hence have little use outside of networking.
-
gethostid() - Returns a supposedly unique 32-bit identifier for the current machine. The semantics of this is not clear. On most machines this simply returns a value based on a local IPv4 address. On others it is administrator controlled via the /etc/hostid file. Since the semantics of this ID are not clear and most often is just a value based on the IP address it is almost always the wrong choice to use. On top of that 32bit are not particularly a lot. On the other hand this is standardized in POSIX and hence portable to other Unixes. It's probably best to ignore this value and if people don't want to ignore it they should probably symlink /etc/hostid to /var/lib/dbus/machine-id or something similar.
-
/var/lib/dbus/machine-id - An ID identifying a specific Linux/Unix installation. It does not change if hardware is replaced. It is not unreliable in virtualized environments. This value has clear semantics and is considered part of the D-Bus API. It is supposedly globally unique and portable to all systems that have D-Bus. On Linux, it is universally available, given that almost all non-embedded and even a fair share of the embedded machines ship D-Bus now. This is the recommended way to identify a machine, possibly with a fallback to the host name to cover systems that still lack D-Bus. If your application links against libdbus, you may access this ID with dbus_get_local_machine_id(), if not you can read it directly from the file system.
-
/proc/self/sessionid - An ID identifying a specific Linux login session. This ID is maintained by the kernel and part of the auditing logic. It is uniquely assigned to each login session during a specific system boot, shared by each process of a session, even across su/sudo and cannot be changed by userspace. Unfortunately some distributions have so far failed to set things up properly for this to work (Hey, you, Ubuntu!), and this ID is always (uint32_t) -1 for them. But there's hope they get this fixed eventually. Nonetheless it is a good choice for a unique session identifier on the local machine and for the current boot. To make this ID globally unique it is best combined with /proc/sys/kernel/random/boot_id.
-
getuid() - An ID identifying a specific Unix/Linux user. This ID is usually automatically assigned when a user is created. It is not unique across machines and may be reassigned to a different user if the original user was deleted. As such it should be used only locally and with the limited validity in time in mind. To make this ID globally unique it is not sufficient to combine it with /var/lib/dbus/machine-id, because the same ID might be used for a different user that is created later with the same UID. Nonetheless this combination is often good enough. It is available on all POSIX systems.
-
ID_FS_UUID - an ID that identifies a specific file system in the udev tree. It is not always clear how these serials are generated but this tends to be available on almost all modern disk file systems. It is not available for NFS mounts or virtual file systems. Nonetheless this is often a good way to identify a file system, and in the case of the root directory even an installation. However due to the weakly defined generation semantics the D-Bus machine ID is generally preferrable.
-
/etc/machine-id - In some cases it is symlinked to
/var/lib/dbus/machine-idby default. - Can be renewed with systemd-machine-id-setup or dbus-uuidgen.
-
/etc/fstab,getfsent(),getfsfile(),/dev/disk/by-uuid, blkid - Disk UUID
Generating IDs
Linux offers a kernel interface to generate UUIDs on demand, by reading from /proc/sys/kernel/random/uuid. This is a very simple interface to generate UUIDs. That said, the logic behind UUIDs is unnecessarily complex and often it is a better choice to simply read 16 bytes or so from /dev/urandom.
English text and references on serial key time limits (expiration dates)
- The System Time Has Been Changed on Your Computer or on the License Manager PC
- License errors due to system date & time | Download & Install | Autodesk Knowledge Network - Autodesk products allow time changes within 2 days.
English:
TestComplete licensing modules detect changes made to the system time in order to prevent attempts to extend time-limited licenses. Therefore, it is important to ensure that the computer time and date are set correctly prior to installing TestComplete.
Korean:
TestComplete 라이센스 모듈은 시간 제한 라이센스를 연장하려는 시도를 방지하기 위해 시스템 시간 변경 사항을 감지합니다. 따라서 TestComplete를 설치하기 전에 컴퓨터 시간과 날짜가 올바르게 설정되었는지 확인하는 것이 중요합니다.
Example of restricting time changes
- Create a trial_tracker entry in encrypted form in the Windows registry and in a file.
- Assign the app installation timestamp (yyyy-mm-dd-hh-mm-ss) to trial_tracker. Every time the app starts, check that the current system timestamp is greater than trial_tracker and less than the expected expiration date.
- If so, update trial_tracker to the current system timestamp and continue.
- If not, trial_tracker has been tampered with or the trial period has expired. Ask the user to buy the full version or quit.
- Note: users can get around this by deleting the Windows registry entry and the encrypted file (if they can find them). In that case, you can add extra checks. For example, create a secondary Windows registry entry that checks for the existence of the primary registry entry and the encrypted file.
- Along with this, you can apply an additional remote check depending on the Internet connection (optional).
Some methods
PostgreSQL
Check the time-tracking hint with the last stats reset time.
TimescaleDB
The metadata lets you check two pieces of information from installation time: the UUID and the install time.
And you can check time updates with the following command.
select last_start, last_finish, next_start, last_successful_finish, total_runs from _timescaledb_internal.bgw_job_stat;
Method used in c2core
The following steps run in the runtime program. (has public key)
- Check and create the directory where the Keystore is stored.
/usr/local/c2core/var/a - Save and open the Keystore file.
- Prepare the SessionID. (If it is not in the Keystore, create a new one.)
- Create the SessionInfo.
{SessionID, MachineID, ProductUUID} - Obtain the current time.
- Get the current time using NTP.
- If it can't connect, use the local time.
- If the environment variable (
C2CORE_AUTH_CERT_INPUT) exists, check whether the file at that path exists. - If the environment variable check fails, check the default path.
/usr/local/c2core/answer.cert - If a file is provided, save the EncodedCertificateInfo to the Keystore.
- If no file is provided, create a RequestInfo and exit. In this case, use the error code
E_REJECTED.
- The SessionInfo must be exactly identical.
- The current time must not exceed the Deadline.
- If the environment variable (
C2CORE_AUTH_CERT_INPUT) exists, check whether the file at that path exists. - If the environment variable check fails, check the default path.
/usr/local/c2core/answer.cert - If the authentication information is correct, save the EncodedCertificateInfo to the Keystore.
- Otherwise, create a RequestInfo and exit. In this case, use the error code
E_REJECTED.
- Obtain the UpdateInfo from the Keystore.
- Decode the UpdateInfo using the
AES256{key,iv}information in the CertificateInfo. - The current time must not be earlier than the last login time. (24-hour tolerance)
- Encode the UpdateInfo using the
AES256{key,iv}information in the CertificateInfo. - Save the encrypted UpdateInfo to the Keystore.
The following runs in the certificate file generator. (has private key)
- Read the request file and decode it with the Private Key.
- Create the authentication information: {authentication key, expiration time, service limit scope}.
- Create the certificate file together with the information from the request file.
Fake routine
Force it to run for a few minutes.
- Read ethernet mac-address: MAC
- Encode (Static private key in original source): RSAPrivate{MAC}
- Save keystore file:
${STORAGE_ROOT}/key/default.key - ... deploy ...
- Decode (Static public key in binary): MAC
- Test ethernet mac-address
PC ID INFORMATION:
- Docker container:
/sys/class/dmi/id/product_uuid - Local PC:
/etc/machine-id
Method used in recc
Run Answer and create an authentication request file with the public-key. Add the items in the following list to the request file information.
- Requesting user's email
- Requesting user's pw (SHA256)
- TimescaleDB UUID
- Generated random UUID
- Local time
Authentication methods on the authentication GUI screen:
- Request to the authentication server. (Internet connection available)
- Upload a License file (no Internet connection)
How to check authentication expiration:
- Check the last run date of TimescaleDB's bgw (Background Worker).
Serial key storage
See Credential Store for details.
See also
- Biometric passport
- Cryptographic hash function
- Intel Upgrade Service
- Keygen
- License manager
- Product activation
- Serial number
- Software license server
- Volume license key
- UUID
- Credential Store
- Authentication