java - 使用自动标签的开源 Java ASN.1 解码器

标签 java tags asn.1 decoder ber

我刚开始使用 ASN.1 编码流,我很难找到免费的类编译器和解码器,最好是 Java。

我有一个编码的十六进制字符串:

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 通用枚举。从通知来看这是有道理的,但我猜 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 使其工作。

最佳答案

这是让 jASN1 与自动标签一起工作的非常肮脏的 hack。这不是一个通用的解决方案,需要花费大量时间手动编辑所有生成的类,所以我仍在寻找一个完整的解决方案。

在方法中为不同序列生成的类:

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 通用类,标签号是通用类型之一或类似构造序列的东西。您可以通过打印出解码后的标识符和预期的标识符来快速查看差异:

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

因此,您可以强制要求自动标记的预期标识符正确,将 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

一些注意事项:在大型协议(protocol)中,完成所有相关解码步骤需要花费大量时间。这很容易出错。对协议(protocol)的更改需要重新生成类并合并更改,这将是痛苦的。以上都不涉及编码。我还没有完全测试所有内容,但我相信这是唯一需要的更改。

所以,是的,请继续发布任何建议,但我希望以上内容对真正陷入困境并需要快速破解的人有用。

关于java - 使用自动标签的开源 Java ASN.1 解码器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37056554/

相关文章:

c# - 在 C# 中创建 ASN1 编码签名以发送到 Java

java - 有条件删除行后缀并添加前缀

php - 使用 "toxi"模式的 mysql 标签查询

html - 使用 XSLT 独立插入开始和结束 HTML 标签

git - 更改 git 标签的日期(或基于它的 GitHub 发布)

c++ - 是否有一个好的 C++ 库来读取、创建和修改 BER 编码文件?

c++ - 带有可选字段的 ASN.1 编码

java - 简单的 Spring @CreatedDate 注释对我不起作用

java - 如何将 jar 文件包含到 Scala 代码中

java - Android - iOS block 回调的 Java 等价物?