简体   繁体   中英

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.

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.

I next tried jASN1: https://www.openmuc.org/asn1/ It doesn't say if it supports automatic tags or not. 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.

If we take the start of the encoded string: 30 82 02 74 80 02 00 a2... This is my understanding:

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. That makes sense form looking at he notification but I am guessing Automatic tags is being ignored by jASN1. When I look at the generated Java classes we see SemiDialogID extends BerEnum, which uses universal clas identifier:

// 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? IF the latter, what do people recommend? Ideally I am looking for an open source java solution that is easy to use. I guess I could make do with a C solution and use JNI to get it to work.

Here is a very dirty hack to get jASN1 to work with automatic tags. 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:

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. 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:

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支持自动标记。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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