オブジェクト識別子の16進バージョンを取得する[プログラミング言語固有ではない]方法はありますか?
元:
OID 1.2.840.10040.4.1:dsa
16進文字列=2a86 48 ce 38 04 01
それらのリストにアクセスするのは簡単ではないようです。X509証明書で使用されるOIDを探しています
オブジェクト識別子の16進バージョンを取得する[プログラミング言語固有ではない]方法はありますか?
元:
OID 1.2.840.10040.4.1:dsa
16進文字列=2a86 48 ce 38 04 01
それらのリストにアクセスするのは簡単ではないようです。X509証明書で使用されるOIDを探しています
を使用CryptEncodeObjectEx
して、OIDを含む最も暗号化されたオブジェクトをデコードできます。
OIDの場合、エンコードとデコードは非常に簡単なので、手動で行うことができます。
最初の2つの数値1.2は、少し特別な方法でエンコードされます。たとえば、xyは40 * x+yとしてエンコードされます。1.2の場合、40 * 1 + 2=42または0x2aになります。
次のすべての文字は7ビットの数値として解釈されます。最上位のビット(0から始める場合はビット番号7)は0で、最後のバイトは1で、最後のビットでない場合は1です。たとえば、840は0x348です。これをエンコードするには、最後の2バイトを使用する必要があります。0x48が保存されます。前のものでは、0x48からの追加ビットで0x3を保存する必要があります(8ビットエンコーディングではなく7ビットコーディングのため)。したがって、最初のバイトで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は2バイトの0xceと0x38としてエンコードされます。
4と1は、0x04と0x01と同じようにエンコードされます。
したがって、1.2.840.10040.4.1は、すでに知っているように2a 86 48 ce 380401としてエンコードする必要があります。
これはすべて、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
はエンコードされたOID1.2.840.113549.11.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
0〜65536(0xFFFF)の値に変換する方法を説明しました。
より高い値の計算について説明していただけますか?113549のように?
私はついにそれを手に入れました。ありがとうございました。RSAエンコーディングのシーケンスを作成しました。(RSADSIが113549の場合)
113549は1bb8d(ヘキサ)です
バイナリ形式として、1bb8dは0001 1011 101110001001です。
これは7ビットエンコーディングであるため、次のように表されます。
00 0110 | 111 0111 | 0001001
=> 0x06 | 0x77 | 0x0d
=> 0x06 + 0x80 | 0x77 + 0x80 | 0x0d
=> 0x86 0xf7 0x0d
====================================
0x86 | 0xf7 | 0x0d
にとって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
ステップ3: 2進数を16進数に変換します。
0x86 | 0xf7 | 0x0d