You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从SHA1哈希可靠生成OpenSSL认可的非负证书序列号?

Fixing Negative Serial Numbers in OpenSSL with SHA1 Hashes

Great question! This is a common pitfall when using raw hash values as X.509 certificate serial numbers—let's break down why it happens and how to fix it.

Why OpenSSL Sees Some Hashes as Negative

X.509 certificates require serial numbers to be positive integers, and OpenSSL follows the ASN.1 encoding standard for representing these integers. ASN.1 INTEGER types are signed, which means:

  • If the first byte of the serial number has its highest bit (bit 7) set (i.e., the byte value is ≥ 0x80), OpenSSL interprets the entire sequence as a negative number.
  • This violates the X.509 requirement, leading to errors or invalid certificates.

The Solution: Ensure Positive Integer Encoding

The fix is simple: adjust the SHA1 hash to comply with ASN.1's positive integer rules. Here's how to do it properly:

Step-by-Step Approach

  1. Generate your 20-byte SHA1 hash as usual (CA common name + 10 random bytes → SHA1).
  2. Check the first byte of the hash:
    • If the byte is ≥ 0x80 (highest bit set), prepend a 0x00 byte to the hash. This leading zero tells ASN.1 the number is positive, resulting in a 21-byte serial number.
    • If the byte is < 0x80, use the raw 20-byte hash directly as the serial number.

Example Code (C with OpenSSL)

Here’s how you’d implement this in code when setting the certificate serial number:

#include <openssl/x509.h>
#include <string.h>
#include <stdlib.h>

// Assume sha1_hash contains your 20-byte SHA1 result
unsigned char sha1_hash[20];
// ... (generate the hash here)

unsigned char *serial_data;
int serial_length;

// Check if we need to add a leading zero
if (sha1_hash[0] & 0x80) {
    serial_length = 21;
    serial_data = malloc(serial_length);
    serial_data[0] = 0x00;
    memcpy(serial_data + 1, sha1_hash, 20);
} else {
    serial_length = 20;
    serial_data = malloc(serial_length);
    memcpy(serial_data, sha1_hash, 20);
}

// Create the ASN.1 INTEGER and assign it to the certificate
ASN1_INTEGER *serial = ASN1_INTEGER_new();
if (ASN1_INTEGER_set_octet_string(serial, serial_data, serial_length)) {
    X509_set_serialNumber(your_x509_cert, serial);
}

// Clean up allocated memory
free(serial_data);
ASN1_INTEGER_free(serial);

Key Notes

  • This approach preserves the uniqueness of your SHA1-based serial number (adding a leading zero only when necessary, so no two distinct hashes will result in the same serial number).
  • While many implementations prefer serial numbers ≤20 bytes for compatibility, adding one extra byte (to 21) is generally safe and won't cause issues with most systems.
  • Never just flip the highest bit to 0—this would alter the hash value and risk collisions (two different inputs could produce the same serial number).

内容的提问来源于stack exchange,提问作者Timothy John Laird

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:03:37