私は現在、ASN.1 DER形式のX.509v3証明書とエポックファイルをデコードすることになっているASN.1パーサーを構築しています。パーサーは、私が得ることができなかった1つの問題とは別にうまく機能しています。 DER形式をデコードすると、公開鍵に次の形式のBITSTRINGが使用されていることがわかります。
BIT STRING, **encapsulates** {
SEQUENCE {
INTEGER
// public key hex string
しかし、署名を見ると、それはencapsulates
タグなしのBITSTRINGで表されており、署名の16進バッファーのみが含まれていることがわかります。
SEQUENCE {
OBJECT IDENTIFIER sha256WithRSAEncryption (1 2 840 113549 1 1 11)
NULL
}
BIT STRING
// RAW signature hex buffer }
パーサーにとって、BITSTRINGがバッファーのみを含むか(署名の場合など)、他のいくつかのタイプをカプセル化するか(公開鍵の場合など)を知ることが重要です。両方のDERエンコーディングでは、カプセル化の使用を示唆するような違いは見つかりませんでした。
私の質問:パーサーコードでこれらの2つのシナリオをどのように区別できますか?
解析しているデータの種類を知らなければ、それを本当に知ることはできません。
デコードするデータのタイプがわかっている場合は、ASNモジュールと関連ドキュメントを使用してパーサーを調整する必要があります。さらに、いくつかの知的作業を行う必要がある場合があります。
bITSTRINGにはバッファのみが含まれます(署名の場合と同様)。
これは生のバッファではなく、ネストされたタイプの場合もあります。たとえば、ECDSA署名を見ると、エンコードされた署名がネストされた複合型であることがわかります。
ECDSA-Sig-Value ::= SEQUENCE {
r INTEGER,
s INTEGER
}
または他のいくつかのタイプをカプセル化します(公開鍵の場合のように)
繰り返しますが、常にではありません。 RSAキーはBIT_STRING
でネストされた構造を使用しますが、ECキーは次のことを行いません:
これらは、仮定が失敗する例にすぎません。署名にはネスト構造があり、公開鍵にはそれがない場合があります。それはコンテキストに依存し、ドキュメンテーションがないと何を期待するのかわかりません。したがって、ドキュメントを使用することをお勧めします。たとえば、ほとんどのPKIX ASNモジュールを含む RFC5912 です。
解析しているデータがわからない場合は、現在の型がプリミティブであるか、または構築されているか(CONSTRUCTED
ビットセットなし)をプロアクティブにチェックするために、大変な作業を行う必要があります。可能であれば、ネストされた型を展開しようとします。
C#で記述された離散構造にASNバイナリデータをデコードする汎用の生のパーサーがあります: Asn1DerParser.NET およびパーサークラス: Asn1Reader
BIT STRING
は、「値はビットのシーケンスである」という基本的なタイプであり、これらのビットの解釈方法に関する追加情報はまったくありません。値ビット自体がネストされた構造のDERエンコーディングであると想定されるか、「単なるビット」であるかによって、エンコーディングに違いはありません。
「通常の」答えは@ Crypt32によって与えられたものです。構造(X.509証明書など)をデコードするとき、デコードする構造の種類を知っているはずであり、それに応じて動作します。これは実際にはかなり複雑になる可能性があります。たとえば、SubjectPublicKeyInfo
構造体には、公開鍵のタイプを識別するAlgorithmIdentifier
と、公開鍵の値を含むBIT STRING
が含まれています。公開鍵がRSA鍵の場合、BIT STRING
の値はDERエンコードされた構造(2つのSEQUENCE
のINTEGER
)であると想定されます。ただし、これがEC公開鍵の場合、BIT STRING
の包含は、ASN.1またはDERのない、エンコードされた生の公開ポイントになります。
ツールが診断用である場合、ヒューリスティックを使用できます。一般的なASN.1/DERパーサーである DDer を確認することをお勧めします(実際には、BERをサポートしています)。 「バイナリ値」(BIT STRING
またはOCTET STRING
)を検出すると、その値自体がASN.1オブジェクトとしてデコードできるかどうかを確認しようとします。 BER/DERエンコーディングは非常に冗長であるため、署名のような任意のランダムな値がDERエンコーディングとエラーなしで一致することはほとんどありません(基本的には10000回に1回程度)。
(DDerには、テキストベースの表現からDERエンコーディングへの逆の操作を行うMDerと呼ばれる関連ツールも付属しています。これは、テストオブジェクトの作成に便利です。)
ビット文字列とオクテット文字列の両方に、データまたは埋め込みASN.1を含めることができます。構文解析の前に、どのフォーマットをとるべきかを知るのに役立ちますが、それは必ずしも必要ではありません。 (これらのASN.1デコーダーは、完全に解析する前に何をデコードするかを認識していません。)オクテット文字列を解析するときは、単に内容を見て、それがASN.1プリミティブ(1バイトのヘッダー、その後にサイズ情報が続き、その後にサイズで示されるデータ量が続きます)。
ビット文字列は、分析が少し複雑です。ビット文字列には、オフセットビットの数を示すバイトが含まれます。ビット文字列はバイト単位で保持されますが、オブジェクトに格納される実際のビット数は、8の倍数から1〜7の範囲になります。オフセットは0です。含まれているバイトを見て、含まれているデータがASN.1プリミティブであるかどうかを評価できます。