How is the serial number of a certificate formed?

The following is an explanation of how the serial numbers of issued certificates are formed and how the behavior of the certification authorities can be customized.

The behavior for generating serial numbers for issued certificates is controlled by the following registry key:

HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\{name-of-certification authority}\HighSerial

The following command can be used to view the current configuration:

certutil -getreg CA\HighSerial

Configuration options

The following configuration options are available:

  • HighSerial set to REG_DWORD = 0
  • HighSerial set to REG_DWORD between 1 and 0x7f (127)
  • HighSerial set to REG_DWORD = 0xffffffff
  • HighSerial set to a hexadecimal value as REG_SZ

Background information

To understand how each option works, we will first briefly explain the three functions used.

GetTickCount

Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days.
The return value is the number of milliseconds that have elapsed since the system was started.

The function returns the time since the start of the operating system in milliseconds, up to a maximum value of 49.7 days.

UShort

Holds unsigned 16-bit (2-byte) integers ranging in value from 0 through 65,535.

The UShort data type can take the values 0 to 65535.

CryptGenRandom

The CryptGenRandom function fills a buffer with cryptographically random bytes.

The CryptGenRandom function returns random numbers.

HighSerial REG_DWORD = 0

This is the default setting for all certification authorities up to Windows Server 2008 R2. The generated serial numbers will be 10 bytes long and are composed as follows:

DWORD GetTickCount() + 
UShort (key index of the certification authority certificate) +
DWORD RequestId

Since there is no true random component involved, these serial numbers are predictable, which facilitates an attack on an insecure signature algorithm (e.g. MD5 and SHA-1) (and in the case of the Flame also successfully carried out). For this reason, certification authorities behave differently as of Windows Server 2012.

EXAMPLE

610dde5a0000000003

After the certificate authority certificate has been renewed with a new key, you can see that the corresponding bit has changed:

6154e9cb000100000007

HighSerial set to REG_DWORD between 1 and 0x7f (127)

This is the default setting for all certification authorities from Windows Server 2012 onwards (but not if they are set via In-place upgrade from a previous operating system has been updated to this version level). The generated serial numbers will be 19 bytes long and are composed as follows:

BYTE the configured registry value + 
DWORD RequestId +
8 bytes CryptGenRandom data +
UShort (key index of the certification authority certificate) +
DWORD RequestId

The random data is renewed for each certificate issued, so the generated serial numbers are unpredictable.

The serial numbers also have a prefix, which is used, for example, for the Auditing OCSP requests can be evaluated.

Example

HighSerial is set to REG_DWORD = 3b (59). As you can see, the serial number starts with this value.

3b000000031e83d411d8bcef0f000000000003

HighSerial set to REG_DWORD = 0xffffffff

When the certification authority attempts to generate the first serial number, an 8 byte random number is generated using the CryptGenRandom function and stored in the HighSerial value. The generated serial numbers will be 14 bytes long and are composed as follows:

8 bytes the previously generated CryptGenRandom data from HighSerial +
UShort (key index of the certification authority certificate) +
DWORD RequestId

Since the 8 bytes of random data are generated only the first time a certificate is issued, these serial numbers are predictable. The option should therefore not be used.

Example

16a28b7e63099507000000000004

The random value generated by CryptGenRandom is entered in the HighSerial value as REG_SZ (string):

Highserial set to a hexadecimal value as REG_SZ

A 1 to 13 bytes long hexadecimal value of the type REG_SZ can be entered in the HighSerial value. The generated serial numbers will - depending on the length of the configured set value - be between 7 and 19 bytes long and are composed as follows:

1 to 13 bytes of the data entered in HighSerial +
UShort (key index of the certification authority certificate) +
DWORD RequestId

This option also does not contain a function to generate random values and therefore results in predictable serial numbers. It should therefore not be used.

Default values

Operating systemDefault value
Windows Server 2003
Windows Server 2008
Windows Server 2008 R2
REG_DWORD = 0
Windows Server 2012
Windows Server 2012 R2
Windows Server 2016
Windows Server 2019
REG_DWORD randomly generated between 1 and 0x7f (127)

Conclusion

From a security point of view, the configuration with the highest random percentage should always be selected. This corresponds to the option of setting the HighSerial value as REG_DWORD to a value between 1 and 0x7f (127), as has been the standard since Windows Server 2012.

For systems that are operated by means of In-Place Upgrade have migrated to Windows Server 2012 or newer, it may be useful to set the HighSerial value to the new standard.

For systems that have been migrated to a server with a new operating system, a decision should be actively made as to whether to stay with the Registration import takes over the value from the old system or leaves it at the new setting.

However, it is also possible to upgrade certificate authorities running on Windows Server 2008 and Windows Server 2008 R2 to the new Windows Server 2012 default value already.

Related links:

External sources

en_USEnglish