Вы можете использовать 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