4

私はASN.1でエンコードされたストリームを扱うのは初めてで、できればJava用の無料のクラスコンパイラとデコーダを見つけるのに苦労しています。

エンコードされた 16 進文字列があります。

String test("30820274800200a2810105820410300c3d830401bb0afc84...

表記の例を次に示します。

SEMI DEFINITIONS AUTOMATIC TAGS ::= BEGIN

IntersectionSituationData ::= SEQUENCE {
    dialogID        SemiDialogID,                   -- 0xA2     
    seqID           SemiSequenceID,                 -- 0x05 Data
    groupID         GroupID,                        
    -- Some more members
}

SemiDialogID ::= ENUMERATED {
   intersectionSitDataDep       (162),  -- 0xA2 
   -- additional DialogIDs
}
SemiSequenceID ::= ENUMERATED {
    data                (5),    -- Data 
    -- additional SeqIDs
}

JAC を使い始めました: https://sourceforge.net/projects/jac-asn1/ しかし、自動タグはサポートされていません。

次に jASN1 を試してみました: https://www.openmuc.org/asn1/ 自動タグをサポートしているかどうかはわかりません。Notation は問題なくコンパイルされているようですが、正しくデコードできず、タグ付けが間違っているように見えます。

エンコードされた文字列の先頭を取ると: 30 82 02 74 80 02 00 a2... これは私の理解です:

30 = Sequence
82 = Length encoded in 2 octets
02 74 = Length = 2x256 + 7x16 +4 == 638 bytes, correct
80 ?? is this a result of automatic encoding? x80= 128= 8th bit set = context-specific class, number 0?
02 = length of value is 2 octets
00 a2 is value == xA2 as expected from SemiDialogID

しかし、「IntersectionSituationData」のテストをエンコードすると、次のようになります。 30 81 8a 0a 02 00 a2 つまり、タイプは 'x0a' == 10 で、ASN.1 Universal ENUMERATED です。それは彼の通知を見ると理にかなっていますが、自動タグがjASN1によって無視されていると推測しています。生成された Java クラスを見ると、SemiDialogID が、ユニバーサル クラス識別子を使用する BerEnum を拡張していることがわかります。

// SemiDialogID.java
public class SemiDialogID extends BerEnum {
   ...
}

//BerEnum.java
public class BerEnum extends BerInteger {

   public final static BerIdentifier identifier = new BerIdentifier(BerIdentifier.UNIVERSAL_CLASS,
        BerIdentifier.PRIMITIVE, BerIdentifier.ENUMERATED_TAG);

jASN1 を自動タグで動作させるために必要なことはありますか、それとも別のライブラリが必要ですか? 後者の場合、人々は何を推奨しますか? 理想的には、使いやすいオープン ソースの Java ソリューションを探しています。C ソリューションで間に合わせ、JNI を使用して動作させることができると思います。

4

2 に答える 2

1

これは、jASN1 を自動タグで動作させるための非常に汚いハックです。これは一般的な解決策ではなく、生成されたすべてのクラスを手動で編集するには多くの時間がかかるため、まだ完全な解決策を探しています。

メソッド内のさまざまなシーケンス用に生成されたクラス内:

public int decode(InputStream is, boolean explicit) throws IOException {

タグ/識別子をチェックする次のようなコードが表示されます。

    if (berIdentifier.equals(MsgCount.identifier)) {
        msgCnt = new MsgCount();
        subCodeLength += msgCnt.decode(is, false);
        subCodeLength += berIdentifier.decode(is);
    }
    else {
        throw new IOException("Identifier does not match the mandatory sequence element identifer.");
    }

識別子が一致しないため、例外がスローされます。生成されたクラスは通常、ASN ユニバーサル クラスを想定しており、タグ番号はユニバーサル タイプの 1 つまたは構築されたシーケンスのようなものです。デコードされた識別子と予想される識別子を出力することで、違いをすばやく確認できます。

System.out.println("Decoded: " + berIdentifier + ", expected: " + MsgCount.identifier);

したがって、クラスを CONTEXT_CLASS に設定し、最終的な整数、タグ番号、t をシーケンス内のフィールドのインデックスに設定して、自動タグに対して予想される識別子を強制的に正しくすることができます。

BerIdentifier identifier2 = new BerIdentifier(BerIdentifier.CONTEXT_CLASS, BerIdentifier.PRIMITIVE, 2); // Hardcode the true idenifier
if (berIdentifier.equals(identifier2)) {   // Check the decoded identifier matches our hard-coded value, instead of the generated
        msgCnt = new MsgCount();
        ...  // Carry on as before

いくつかの注意事項: 大規模なプロトコルでは、関連するすべてのデコード手順を実行するのに多くの時間がかかります。これはエラーが発生しやすいです。プロトコルを変更するには、クラスを再生成し、変更をマージする必要がありますが、これは面倒です。上記のいずれもエンコーディングを扱っていません。すべてを完全にテストしたわけではありませんが、必要な変更はこれだけだと思います。

はい、提案を投稿し続けてください。しかし、本当に行き詰まり、簡単なハックが必要な人にとって、上記が役立つことを願っています。

于 2016-05-06T20:07:32.773 に答える
1

バージョン 1.6.0 以降、jASN1 は自動タグ付けをサポートしています。

于 2017-07-04T12:07:21.740 に答える