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

cal*_*pto 2 x509certificate x509

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

例如:

OID 1.2.840.10040.4.1:dsa

hex string = 2a 86 48 ce 38 04 01

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

Ole*_*leg 6

您可以使用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 012a 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;
}
Run Code Online (Sandbox Code Playgroud)

程序产生以下输出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
Run Code Online (Sandbox Code Playgroud)

  • 如何为'113549'手动查看计算? (3认同)