简体   繁体   English

Opensource Java ASN.1解码器,可以使用自动标签

[英]Opensource Java ASN.1 decoder that work with automatic tags

I'm new to working with ASN.1 encoded streams and I'm having a hard time finding a free class compiler and decoder, preferably for Java. 我刚开始使用ASN.1编码流,我很难找到一个免费的类编译器和解码器,最好是Java。

I have an encoded hex string: 我有一个编码的十六进制字符串

String test("30820274800200a2810105820410300c3d830401bb0afc84...

Here is an example of the notation: 以下是符号的示例:

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
}

I started using JAC: https://sourceforge.net/projects/jac-asn1/ But it doesn't support Automatic tags. 我开始使用JAC: https//sourceforge.net/projects/jac-asn1/但它不支持自动标记。

I next tried jASN1: https://www.openmuc.org/asn1/ It doesn't say if it supports automatic tags or not. 我接下来尝试过jASN1: https ://www.openmuc.org/asn1/它没有说它是否支持自动标签。 It seems to compile the Notation without complaining, but I can't get it to decode correctly and it looks like the tagging if wrong. 它似乎在没有抱怨的情况下编译Notation,但是我无法正确解码它看起来像标记错误。

If we take the start of the encoded string: 30 82 02 74 80 02 00 a2... This is my understanding: 如果我们采用编码字符串的开头: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

But if I encode a test of "IntersectionSituationData" I get the following: 30 81 8a 0a 02 00 a2 ie the type is 'x0a' == 10 which is ASN.1 Universal ENUMERATED. 但是,如果我对“IntersectionSituationData”的测试进行编码,我得到以下结果:30 81 8a 0a 02 00 a2即类型为'x0a'== 10,即ASN.1 Universal ENUMERATED。 That makes sense form looking at he notification but I am guessing Automatic tags is being ignored by jASN1. 这看起来很有意义,但我猜测自动标签被jASN1忽略了。 When I look at the generated Java classes we see SemiDialogID extends BerEnum, which uses universal clas identifier: 当我查看生成的Java类时,我们看到SemiDialogID扩展了BerEnum,它使用了通用clas标识符:

// 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);

Is there something I need to do to get jASN1 to work with automatic tags or do I need a different library? 有什么我需要做的是让jASN1使用自动标签或者我需要一个不同的库吗? IF the latter, what do people recommend? 如果是后者,人们会推荐什么? Ideally I am looking for an open source java solution that is easy to use. 理想情况下,我正在寻找一个易于使用的开源Java解决方案。 I guess I could make do with a C solution and use JNI to get it to work. 我想我可以使用C解决方案并使用JNI来使其工作。

Here is a very dirty hack to get jASN1 to work with automatic tags. 这是一个非常脏的黑客,让jASN1使用自动标签。 This isn't a general solution and takes a lot of time to manually edit all of the generated classes, so I am still looking for a complete solution. 这不是一般解决方案,需要花费大量时间手动编辑所有生成的类,因此我仍在寻找完整的解决方案。

Inside the generated classes for the different Sequences in the method: 在方法中不同Sequences的生成类中:

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

You will see some code like this, which is checking the tag/identifier: 你会看到一些像这样的代码,它正在检查标签/标识符:

    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.");
    }

The exception is thrown because the identifiers don't match. 抛出异常是因为标识符不匹配。 The generated class is typically expecting an ASN Universal class, with the tag number being one of the universal types or something like a constructed sequence. 生成的类通常期望ASN Universal类,标记号是通用类型之一或类似构造序列的类。 You can quickly see the differences by printing out the decoded identifier and the expected identifier: 您可以通过打印出已解码的标识符和预期的标识符来快速查看差异:

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

You can therefore then force the expected identifier to be correct for the automatic tags, setting the Class to be CONTEXT_CLASS, and the final integer, the tag number, t be the index of the field in the sequence: 因此,您可以强制预期标识符对于自动标记是正确的,将Class设置为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

Some caveats: In a large protocol it take a lot of time to go through all of the relevant decode steps. 一些警告:在大型协议中,需要花费大量时间来完成所有相关的解码步骤。 This is prone to error. 这很容易出错。 A change to the protocol requires regenerating the classes and merging changes which will be painful. 对协议的更改需要重新生成类并合并将会很痛苦的更改。 None of the above deals with encoding. 以上都不涉及编码。 I have not fully tested everything but I do believe this is the only changes required. 我还没有完全测试过所有内容,但我相信这是唯一需要进行的更改。

So yes, please keep posting any suggestions but I hope the above is useful for anyone who gets really stuck and needs a quick hack. 所以,是的,请继续发布任何建议,但我希望上述内容对任何真正陷入困境并需要快速入侵的人都有用。

从版本1.6.0开始,jASN1支持自动标记。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM