如何将对象标识符转换为十六进制字符串

发布于 2024-09-12 09:35:35 字数 191 浏览 12 评论 0原文

有没有[非特定于编程语言]的方法来获取对象标识符的十六进制版本?

前任:

OID 1.2.840.10040.4.1:DSA

十六进制字符串 = 2a 86 48 ce 38 04 01

似乎没有一个易于访问的列表。我正在寻找 X509 证书中使用的 OID

Is there any [non programming language specific] way to get hex versions of object identifiers?

ex:

OID 1.2.840.10040.4.1: dsa

hex string = 2a 86 48 ce 38 04 01

there doesnt seem to be an easy to access list for them. im looking for the OIDs used in X509 certificates

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

栩栩如生 2024-09-19 09:35:35

您可以使用 CryptEncodeObjectEx 解码大多数加密对象(包括 OID)。

对于 OID,编码和解码非常简单,因此您可以手动执行此操作。

前两个数字 1.2 将用一种特殊的方式进行编码。例如 xy 将被编码为 40*x+y。对于 1.2,我们有 40*1+2 = 42 或 0x2a。

接下来的所有字符将被解释为 7 位数字,其中最高位(如果从 0 开始,则为 7 位)为 0,表示该字节是最后一位;如果该位不是最后一位,则为 1。例如,840 是 0x348。为了对其进行编码,我们应该使用 2 个字节,最后一个字节将被保存为 0x48。在前一个中,应该保存 0x3 以及 0x48 中的附加位(因为是 7 位编码而不是 8 位编码)。所以我们应该在第一个字节中编码0x3*2=0x6。因为 0x6 将不是整数编码中的最后一个字节(后面将是 0x48 字节),所以我们应该将 0x80 添加到编码值中。所以我们收到 0x80+0x6=0x86。所以840将被编码为0x86和0x48。

同样的,10040 就是 0x2738。最后一个字节是0x38,第一个字节是0x27*2(因为7位编码):0x27*2=0x4e。因为 0x4e 不是最后一个字节,所以我们应该在编码值中添加 0x80:0x4e+0x80=0xce。所以10040将被编码为两个字节0xce和0x38。

4 和 1 将被编码为 0x04 和 0x01。

所以 1.2.840.10040.4.1 应该被编码为 2a 86 48 ce 38 04 01 就像你已经知道的那样。

所有这些您都可以在 ITU-T X.690 (ISO/IEC 8825-1) 的 8.19 中

根据注释更新阅读:您的编码/解码程序出现问题。 OID“1.2.840.113549.1.1.1”将表示为 2A 86 48 86 F7 0D 01 01 01 而不是 2a 86 48 83 f6 8d 01 01 01 > 就像你写的那样。要验证这一点,您可以使用以下小型 C 程序:

#define STRICT
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#pragma comment (lib, "Crypt32.lib")

void PrintOffset(DWORD dwMargineOffset)
{
    while (dwMargineOffset--)
        _tprintf (TEXT(" "));
}

void HexDump (PBYTE pData, DWORD dwDataLength)
{
    while (dwDataLength--) {
        _tprintf (TEXT("%02X"), *pData++);
        if (dwDataLength) _tprintf (TEXT(" "));
    }
}

void DumpOID (DWORD dwMargineOffset, PBYTE pData, DWORD dwDataLength)
{
    PCCRYPT_OID_INFO pCryptOidInfo;
    DWORD dw, i;
    char szOID[256];
    // i
    // first byte is encoded as x.y 40*x+y = 43 = 0x2B
    //
    //_tprintf(TEXT("%d.%d"), *pData/40, *pData%40);
    i = wsprintfA (szOID, "%d.%d", *pData/40, *pData%40);
    dwDataLength--;
    pData++;

    while (dwDataLength--) {
        if (*pData & 0x80) {
            dw = 0;
#pragma warning(disable:4127)
            while (TRUE) {
#pragma warning(default:4127)
                dw <<= 7;  // *128
                dw += (*pData & 0x7F);
                if (*pData++ & 0x80)
                    dwDataLength--;
                else
                    break;
            }
            //_tprintf(TEXT(".%d"), dw);
            i += wsprintfA (szOID+i, ".%d", dw);
        }
        else
            //_tprintf(TEXT(".%d"), *pData++);
            i += wsprintfA (szOID+i, ".%d", *pData++);
    }

    PrintOffset(dwMargineOffset);
    _tprintf (TEXT("%hs"), szOID);

    // try find OID in the list of known IODs
    pCryptOidInfo = CryptFindOIDInfo (CRYPT_OID_INFO_OID_KEY, szOID, 0);
    if (pCryptOidInfo)
        _tprintf (TEXT(" (\"%ls\")"), pCryptOidInfo->pwszName);
    else
        _tprintf (TEXT(" (Unknown OID)"));
}

int main()
{
    BOOL bIsSuccess;
    DWORD cbEncoded = 0;
    PBYTE pbyData = NULL;
    BYTE byData[] = {0x2a, 0x86, 0x48, 0x83, 0xf6, 0x8d, 0x01, 0x01, 0x01};
    BYTE byData2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01};
    LPSTR pszOid = "1.2.840.113549.1.1.1";
    DumpOID (0, byData, sizeof(byData));
    _tprintf (TEXT("\n"));
    DumpOID (0, byData2, sizeof(byData2));
    _tprintf (TEXT("\n"));

    bIsSuccess = CryptEncodeObjectEx (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                                      X509_OBJECT_IDENTIFIER,
                                      (const void *)&pszOid,
                                      CRYPT_ENCODE_ALLOC_FLAG,
                                      NULL,
                                      &pbyData,
                                      &cbEncoded);
    if (bIsSuccess) {
        HexDump (pbyData, cbEncoded);
        _tprintf (TEXT("\n"));
        pbyData = (PBYTE) LocalFree (pbyData);
    }

    return 0;
}

该程序产生以下输出 06 09 2A 86 48 86 F7 0D 01 01 01,其中 BER 编码的第一个字节 0x06 表示 OID 数据类型,下一个字节 0x09 表示数据长度,接下来的 9 个字节 2A 86 48 86 F7 0D 01 01 01 是编码后的 OID 1.2.840.113549.1.1.1。

程序的完整输出是

1.2.840.8226433.1.1 (Unknown OID)
1.2.840.113549.1.1.1 ("RSA")
06 09 2A 86 48 86 F7 0D 01 01 01

You can use CryptEncodeObjectEx to decode the most cryptographic objects inclusive OIDs.

In case of OIDs the encoding and decoding is pity simple so you can do this manually.

Two first numbers 1.2 will be encoded with a little special way. For example x.y will be encoded as 40*x+y. In case of 1.2 we have 40*1+2 = 42 or 0x2a.

All next characters will be interpret as 7-bit numbers where the highest bit (bit number 7 if we start with 0) is 0 is the byte is the last one and 1 if the bit is not the last one. For example, 840 is 0x348. To encode this we should use 2 bytes in the last one will be saved 0x48. In the previous one should be saved 0x3 with an additional bit from 0x48 (because of 7 bit codding and not 8 bit encoding). So we should encode 0x3*2=0x6 in the first byte. Because 0x6 will be the not the last byte in the encoding of the integer (0x48 byte will follow) we should add 0x80 to the encoded value. So we receive 0x80+0x6=0x86. So 840 will be encoded as 0x86 and 0x48.

In the same way 10040 is 0x2738. The last byte is 0x38 and the first one is 0x27*2 (because of 7 bit codding): 0x27*2=0x4e. Because 0x4e is not the last byte we should add 0x80 to the encoded value: 0x4e+0x80=0xce. So 10040 will be encoded as two bytes 0xce and 0x38.

The 4 and 1 will be encoded just as 0x04 and 0x01.

So 1.2.840.10040.4.1 should be encoded as 2a 86 48 ce 38 04 01 like you already knows.

All this you can read in 8.19 of ITU-T X.690 (ISO/IEC 8825-1)

UPDATED based on the comment: Something is wrong in you encoding/decoding program. The OID "1.2.840.113549.1.1.1" will be do represented as 2A 86 48 86 F7 0D 01 01 01 and not as 2a 86 48 83 f6 8d 01 01 01 like you wrote. To verify this you can use following small C program:

#define STRICT
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#pragma comment (lib, "Crypt32.lib")

void PrintOffset(DWORD dwMargineOffset)
{
    while (dwMargineOffset--)
        _tprintf (TEXT(" "));
}

void HexDump (PBYTE pData, DWORD dwDataLength)
{
    while (dwDataLength--) {
        _tprintf (TEXT("%02X"), *pData++);
        if (dwDataLength) _tprintf (TEXT(" "));
    }
}

void DumpOID (DWORD dwMargineOffset, PBYTE pData, DWORD dwDataLength)
{
    PCCRYPT_OID_INFO pCryptOidInfo;
    DWORD dw, i;
    char szOID[256];
    // i
    // first byte is encoded as x.y 40*x+y = 43 = 0x2B
    //
    //_tprintf(TEXT("%d.%d"), *pData/40, *pData%40);
    i = wsprintfA (szOID, "%d.%d", *pData/40, *pData%40);
    dwDataLength--;
    pData++;

    while (dwDataLength--) {
        if (*pData & 0x80) {
            dw = 0;
#pragma warning(disable:4127)
            while (TRUE) {
#pragma warning(default:4127)
                dw <<= 7;  // *128
                dw += (*pData & 0x7F);
                if (*pData++ & 0x80)
                    dwDataLength--;
                else
                    break;
            }
            //_tprintf(TEXT(".%d"), dw);
            i += wsprintfA (szOID+i, ".%d", dw);
        }
        else
            //_tprintf(TEXT(".%d"), *pData++);
            i += wsprintfA (szOID+i, ".%d", *pData++);
    }

    PrintOffset(dwMargineOffset);
    _tprintf (TEXT("%hs"), szOID);

    // try find OID in the list of known IODs
    pCryptOidInfo = CryptFindOIDInfo (CRYPT_OID_INFO_OID_KEY, szOID, 0);
    if (pCryptOidInfo)
        _tprintf (TEXT(" (\"%ls\")"), pCryptOidInfo->pwszName);
    else
        _tprintf (TEXT(" (Unknown OID)"));
}

int main()
{
    BOOL bIsSuccess;
    DWORD cbEncoded = 0;
    PBYTE pbyData = NULL;
    BYTE byData[] = {0x2a, 0x86, 0x48, 0x83, 0xf6, 0x8d, 0x01, 0x01, 0x01};
    BYTE byData2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01};
    LPSTR pszOid = "1.2.840.113549.1.1.1";
    DumpOID (0, byData, sizeof(byData));
    _tprintf (TEXT("\n"));
    DumpOID (0, byData2, sizeof(byData2));
    _tprintf (TEXT("\n"));

    bIsSuccess = CryptEncodeObjectEx (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                                      X509_OBJECT_IDENTIFIER,
                                      (const void *)&pszOid,
                                      CRYPT_ENCODE_ALLOC_FLAG,
                                      NULL,
                                      &pbyData,
                                      &cbEncoded);
    if (bIsSuccess) {
        HexDump (pbyData, cbEncoded);
        _tprintf (TEXT("\n"));
        pbyData = (PBYTE) LocalFree (pbyData);
    }

    return 0;
}

The program produce the following output 06 09 2A 86 48 86 F7 0D 01 01 01 where the first byte 0x06 of the BER encoding mean OID data type, the next byte 0x09 means the data length and next 9 bytes 2A 86 48 86 F7 0D 01 01 01 are the encoded OID 1.2.840.113549.1.1.1.

The full output of the program is

1.2.840.8226433.1.1 (Unknown OID)
1.2.840.113549.1.1.1 ("RSA")
06 09 2A 86 48 86 F7 0D 01 01 01
§对你不离不弃 2024-09-19 09:35:35

您已经解释了如何对 0 到 65536 (0xFFFF) 之间的值进行转换。

您能解释一下更高值的计算吗?比如113549?

You have explained how to make convertion for values between 0 to 65536 (0xFFFF).

Could you explain your calculation for higher values ? like 113549 ?

夜雨飘雪 2024-09-19 09:35:35

我终于明白了。谢谢。我写了RSA编码的序列。 (当RSADSI为113549时)

113549为二进制格式的1bb8d(Hexa)

,1bb8d为0001 1011 1011 1000 1001。

它是7位编码,因此表示为

00 0110 | 111 0111 | 000 1001

=> 0x06 | 0x06 0x77 | 0x77 0x0d

=> 0x06+0x80|0x77+0x80|0x0d

=> 0x86 0xf7 0x0d

========================================

0x86 | 0x86 0xf7 0x0d 0xf7 | 0xf7 0x0d

I finally got it. Thank you. I wrote the sequence of for RSA encoding. (when RSADSI is 113549)

113549 is 1bb8d(Hexa)

as binary format, 1bb8d is 0001 1011 1011 1000 1001.

it is 7 bit encoding, so expressed as

00 0110 | 111 0111 | 000 1001

=> 0x06 | 0x77 | 0x0d

=> 0x06+0x80|0x77+0x80|0x0d

=> 0x86 0xf7 0x0d

====================================

0x86 | 0xf7 | 0x0d

与风相奔跑 2024-09-19 09:35:35

对于 113549

十六进制:1bb8d

二进制:0001 1011 1011 1000 1101

第 1 步:使用 7 创建组 位:

*0*0001 10 |11 1011 1 |000 1101

第 2 步:8 位添加额外位(< code>0 仅添加到最右边的字节中,1 添加到所有其他字节中):

*1*000 0110 | *1*111 0111 | *0*000 1101

第三步:将二进制转换为十六进制:

0x86 | 0xf7 | 0xf7 0x0d

For 113549

Hexa: 1bb8d

binary: 0001 1011 1011 1000 1101

Step 1: Create group with 7 bits:

*0*0001 10 |11 1011 1 |000 1101

Step 2: Add extra bit for 8 bits (0 added into only right most byte and 1 added into all other bytes):

*1*000 0110 | *1*111 0111 | *0*000 1101

Step3: Convert binary to hexadecimal:

0x86 | 0xf7 | 0x0d

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文