SHA-512 和 SHA-256 的 ASN.1 OID(Object Identifier)前缀的详细对比,包括它们的结构差异、DER 编码以及实际应用中的注意事项。
1. ASN.1 OID 定义对比
SHA-256
- OID:
2.16.840.1.101.3.4.2.1
DER 编码(19字节):
30 31 30 0D 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20
- 哈希长度标识:
04 20
(表示哈希值长度为 32字节)。
SHA-512
- OID:
2.16.840.1.101.3.4.2.3
DER 编码(19字节):
30 51 30 0D 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40
- 哈希长度标识:
04 40
(表示哈希值长度为 64字节)。
2. 关键区别
字段 | SHA-256 | SHA-512 |
OID 值 |
|
|
DER 编码 |
|
|
总长度 | 19 字节 | 19 字节 |
哈希长度标识 |
|
|
OID 部分差异 | 最后一位 | 最后一位 |
3. 代码实现(C语言硬编码)
SHA-256 的 ASN.1 OID
const unsigned char SHA256_ASN1_OID[] = {
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
0x00, 0x04, 0x20
};
SHA-512 的 ASN.1 OID
const unsigned char SHA512_ASN1_OID[] = {
0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
0x00, 0x04, 0x40
};
4. 在 PKCS#1 签名填充中的应用
SHA-256 填充示例
// PKCS#1 v1.5 签名填充(SHA-256)
void pad_with_sha256(const unsigned char *hash, unsigned char *padded) {
const unsigned char SHA256_OID[] = { ... }; // 如上定义
padded[0] = 0x00;
padded[1] = 0x01;
memset(padded + 2, 0xFF, padding_len); // 填充 0xFF
padded[2 + padding_len] = 0x00;
memcpy(padded + 3 + padding_len, SHA256_OID, 19); // 写入 ASN.1
memcpy(padded + 22 + padding_len, hash, 32); // 写入哈希值
}
SHA-512 填充示例
// PKCS#1 v1.5 签名填充(SHA-512)
void pad_with_sha512(const unsigned char *hash, unsigned char *padded) {
const unsigned char SHA512_OID[] = { ... }; // 如上定义
padded[0] = 0x00;
padded[1] = 0x01;
memset(padded + 2, 0xFF, padding_len); // 填充 0xFF
padded[2 + padding_len] = 0x00;
memcpy(padded + 3 + padding_len, SHA512_OID, 19); // 写入 ASN.1
memcpy(padded + 22 + padding_len, hash, 64); // 写入哈希值
}
5. 为什么长度标识不同?
04 20
(SHA-256):
-
04
= OCTET STRING 标签。20
= 32字节(十六进制的 0x20 = 十进制的 32)。
04 40
(SHA-512):
-
40
= 64字节(十六进制的 0x40 = 十进制的 64)。
6. 动态生成 ASN.1 OID(OpenSSL 示例)
#include <stdio.h>
#include <openssl/x509.h>
#include <openssl/evp.h>
void print_oid(const EVP_MD *md)
{
X509_ALGOR *algor = X509_ALGOR_new();
if (!algor)
{
printf("Error: X509_ALGOR_new failed.\n");
return;
}
X509_ALGOR_set_md(algor, md);
unsigned char *buf = NULL;
int len = i2d_X509_ALGOR(algor, &buf); // DER 编码
if (len <= 0)
{
printf("Error: i2d_X509_ALGOR failed.\n");
X509_ALGOR_free(algor);
return;
}
printf("OID (DER): ");
for (int i = 0; i < len; i++)
{
printf("%02x ", buf[i]);
}
printf("\n");
OPENSSL_free(buf);
X509_ALGOR_free(algor);
}
// compile command: gcc sha_256_asn_1_oid.c -lcrypto
int main()
{
// 初始化 OpenSSL(可选,但推荐)
OpenSSL_add_all_algorithms();
printf("SHA-256 OID: ");
print_oid(EVP_sha256());
printf("SHA-512 OID: ");
print_oid(EVP_sha512());
return 0;
}
7. 总结
- SHA-256 和 SHA-512 的 ASN.1 OID 前缀长度相同(19字节),但以下部分不同:
-
- OID 的最后一个字节(
01
vs03
)。 - 哈希长度标识(
04 20
vs04 40
)。
- OID 的最后一个字节(
- 实际应用时:
-
- 硬编码 OID 需严格匹配哈希算法。
- 签名和验签双方必须使用相同的 OID,否则会验证失败。
如果需要其他哈希算法(如 SHA-384)的 OID,可通过类似方式从 RFC 或 OpenSSL 中获取。