как преобразовать идентификаторы объекта в шестнадцатеричные строки - PullRequest
2 голосов
/ 31 июля 2010

Есть ли какой-либо [не специфичный для языка программирования] способ получения шестнадцатеричных версий идентификаторов объектов?

например:

OID 1.2.840.10040.4.1: dsa

шестнадцатеричная строка = 2a 86 48 ce 38 04 01

для них, кажется, нет простого списка доступа. я ищу OID, используемые в сертификатах X509

Ответы [ 4 ]

6 голосов
/ 04 августа 2010

Вы можете использовать CryptEncodeObjectEx для декодирования большинства криптографических объектов, включая OID.

В случае OID кодирование и декодирование очень просты, поэтому вы можете сделать это вручную.

Два первых числа 1.2 будут закодированы немного особым образом. Например, x.y будет закодировано как 40 * x + y. В случае 1.2 мы имеем 40 * 1 + 2 = 42 или 0x2a.

Все последующие символы будут интерпретироваться как 7-битные числа, где старший бит (бит 7, если мы начнем с 0) равен 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, как вы уже знаете.

Все это вы можете прочитать в 8.19 ITU-T X.690 (ISO / IEC 8825-1)

.

ОБНОВЛЕНО на основании комментария: Что-то не так в вашей программе кодирования / декодирования. 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, где первый байт 0x06 типа данных OID кодирования BER означает, что следующий байт 0x09 означает длину данных, а следующие 9 байтов 2A 86 48 86 F7 0D 01 01 01 являются кодированным OID 1.2.840.113549.1.1 0,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
2 голосов
/ 25 марта 2012

Вы объяснили, как выполнить преобразование для значений от 0 до 65536 (0xFFFF).

Не могли бы вы объяснить ваш расчет для более высоких значений? как 113549?

1 голос
/ 12 июля 2013

Я наконец получил это.Спасибо.Я написал последовательность для кодирования RSA.(когда RSADSI равен 113549)

113549 - это 1bb8d (гекса)

в двоичном формате, 1bb8d - это 0001 1011 1011 1000 1001.

- это 7-битное кодирование, поэтомукак

00 0110 |111 0111 |000 1001

=> 0x06 |0x77 |0x0d

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

=> 0x86 0xf7 0x0d

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

0x86 |0xf7 |0x0d

0 голосов
/ 05 ноября 2015

Для 113549

Гекса: 1bb8d

двоичный: 0001 1011 1011 1000 1101

Шаг 1: Создать группу с 7биты:

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

Шаг 2: Добавить дополнительный бит для 8 битов (0 добавляется только в самый правый байт и 1 добавляется ввсе остальные байты):

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

Step3: Преобразование двоичного числа в шестнадцатеричное:

0x86 | 0xf7 | 0x0d

...