ASN.1使用go struct进行编组会使标签不匹配错误 [英] ASN.1 Unmarshalling using go structs gives tags don't match error

查看:126
本文介绍了ASN.1使用go struct进行编组会使标签不匹配错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将ASN.1编组/编组为以下定义:

I am trying to do ASN.1 marshal/unmarshal for the following definition:

ACEI    ::= SEQUENCE {
message         MessageFields,
neRegNumber     OCTET STRING OPTIONAL,
gpsInfo         GpsInfo OPTIONAL,
siteInfo        OCTET STRING OPTIONAL,
nlementID   INTEGER(0..16777216) OPTIONAL,
...
}

GpsInfo         ::= SEQUENCE {
gpsLat      INTEGER(-900000000..900000000) OPTIONAL,
gpsLong     INTEGER(-1800000000..1800000000) OPTIONAL,
gpsAlt      INTEGER OPTIONAL,
...
}
MessageFields       ::= SEQUENCE {
messageSequence     INTEGER (1..65535),
bsId    INTEGER (1..65535) OPTIONAL,
neID        INTEGER(0..16777216) OPTIONAL, -- unsigned int
nelementID  INTEGER(0..16777216) OPTIONAL, -- unsigned int
...
}

相应的go结构为:

type ACEI struct {
    Message          MessageFields
    NeRegNumber      []byte `asn1:"optional"`
    GPSInfo          GPSInfo `asn1:"optional"`
    SiteInfo         []byte `asn1:"optional"`
    NElementID       int `asn1:"optional"`
}

type GPSInfo struct {
    GpsLatitude  int `asn1:"optional"`
    GpsLongitude int `asn1:"optional"`
    GpsAltitude  int `asn1:"optional"`
}

type MessageFields struct {
    MessageSequence  int
    BsId             int `asn1:"optional"`
    NeID             int `asn1:"optional"`
    NElementID       int `asn1:"optional"`
}

我要填充结构,将它们编组,然后将其转换为十六进制.当我这样做时,获得的十六进制序列(seqA)为:

I am filling in the structs, marshalling them and then converting them to hex. When I do that, the hex sequence (seqA) obtained is:

302e300f020101020204d2020215b302021a0a040430413042300b02019c020200be020200c80404304330440202309c

302e300f020101020204d2020215b302021a0a040430413042300b02019c020200be020200c80404304330440202309c

当我在 http://asn1-playground.oss.com/上执行相同操作时,我得到以下十六进制序列(seqB):

When I do the same on http://asn1-playground.oss.com/, I get the following hex sequence (seqB):

302AA00F 80010181 0204D282 0215B383 021A0A81 020A0BA2 0B80019C 810200BE820200C8 83020C0D 8402309C

302AA00F 80010181 0204D282 0215B383 021A0A81 020A0BA2 0B80019C 810200BE 820200C8 83020C0D 8402309C

我将这两个十六进制序列都提供给解组功能;在正确解组seqA的同时,解组seqB给我以下错误:

I fed in both these hex sequences to the unmarshal function; while the seqA is correctly unmarshalled, unmarshalling seqB gives me the following error:

解组时出错:asn1:结构错误:标记不匹配(16与{class:2 tag:0长度:15 isCompound:true}){可选:false显式的:false application:false defaultValue:标记:stringType:0 timeType:0 set:false omitEmpty:false} MessageFields @ 2

Error while unmarshalling: asn1: structure error: tags don't match (16 vs {class:2 tag:0 length:15 isCompound:true}) {optional:false explicit:false application:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} MessageFields @2

这是封送/取消封送的代码:

This is the code that marshals/unmarshals:

func main() {
    //Marshalling
    messageSequence := structs.MessageFields{1, 1234, 5555, 6666}
    gpsInfo := structs.GPSInfo{-100, 190, 200}
    val := structs.ACEI{messageSequence, []byte("0A0B"), gpsInfo, []byte("0C0D"), 12444}
    hexmdata := asn1Marshal(val)

    //Unmarshalling hex sequence (seqA) generated by go code
    res1, _ := asn1Unmarshal(hexmdata)
    fmt.Println(res1)

    //Unmarshalling hex sequence (seqB) generated by http://asn1-playground.oss.com/ 
    res2, _ := asn1Unmarshal(strings.ToLower("302AA00F800101810204D2820215B383021A0A81020A0BA20B80019C810200BE820200C883020C0D8402309C"))
    fmt.Println(res2)
}

func asn1Unmarshal(hexmdata string) (structs.ACEI, error){
    fmt.Println(hexmdata)
    s, _ := hex.DecodeString(hexmdata)
    res := structs.ACEI{}
    _, err := asn1.Unmarshal(s, &res)
    if err != nil {
        fmt.Println("Error while unmarshalling: ", err)
    }
    return res, err
}

func asn1Marshal(data structs.ACEI) string {
    mdata, _ := asn1.Marshal(data)
    hexmdata := hex.EncodeToString(mdata)
    return hexmdata
}

  1. 为什么相同定义的十六进制序列不同?
  2. 如何更正解组seqB时出现的错误?

相反,当转到 http://asn1-playground时,转到代码序列(seqA).oss.com/给我这个错误:

Conversely, the go code sequence (seqA) when fed to http://asn1-playground.oss.com/ gives me this error:

ACEI SEQUENCE: tag = [UNIVERSAL 16] constructed; length = 46
D0033E: Tag mismatch or tag not expected: [UNIVERSAL 16] (expected tag [0]); check field 'message' (type: MessageFields) of PDU #1 'ACEI'.
  *SKIPPED*: tag = [UNIVERSAL 16] constructed; length = 15
    <skipped>
D0033E: Tag mismatch or tag not expected: [UNIVERSAL 4] (expected tag [0]); check field 'message' (type: MessageFields) of PDU #1 'ACEI'.
  *SKIPPED*: tag = [UNIVERSAL 4] primitive; length = 4
    <skipped>
D0033E: Tag mismatch or tag not expected: [UNIVERSAL 16] (expected tag [0]); check field 'message' (type: MessageFields) of PDU #1 'ACEI'.
  *SKIPPED*: tag = [UNIVERSAL 16] constructed; length = 11
    <skipped>
D0033E: Tag mismatch or tag not expected: [UNIVERSAL 4] (expected tag [0]); check field 'message' (type: MessageFields) of PDU #1 'ACEI'.
  *SKIPPED*: tag = [UNIVERSAL 4] primitive; length = 4
    <skipped>
D0033E: Tag mismatch or tag not expected: [UNIVERSAL 2] (expected tag [0]); check field 'message' (type: MessageFields) of PDU #1 'ACEI'.
  *SKIPPED*: tag = [UNIVERSAL 2] primitive; length = 2
    <skipped>
D0049E: Field omitted: "message"; check PDU #1 'ACEI'.
S0012E: Decoding of PDU #1 failed with the return code '5'.

根据@YaFred的建议编辑结构后,我的结构现在看起来像这样:

EDIT 2: After editing the structs according to @YaFred's suggestion, my structs look like this now:

type ACEI struct {
        Message          MessageFields `asn1:"application,tag:0,implicit"`
        NeRegNumber      []byte `asn1:"application,tag:1,implicit,optional"`
        GPSInfo          GPSInfo `asn1:"application,tag:2,implicit,optional"`
        SiteInfo         []byte `asn1:"application,tag:3,implicit,optional"`
        NElementID int `asn1:"application,tag:4,implicit,optional"`
    }

type GPSInfo struct {
    GpsLatitude  int `asn1:"application,tag:0,implicit,optional"`
    GpsLongitude int `asn1:"application,tag:1,implicit,optional"`
    GpsAltitude int `asn1:"application,tag:2,implicit,optional"`
}

type MessageFields struct {
    MessageSequence  int `asn1:"application,tag:0,implicit"`
    BsId int `asn1:"application,tag:1,implicit,optional"`
    NeID        int `asn1:"application,tag:2,implicit,optional"`
    NElementID int `asn1:"application,tag:3,implicit,optional"`
}

使用这些结构进行编组可以为我提供与从asn游乐场获得的十六进制代码相同的十六进制代码.但是,解组失败并显示以下错误:

Marshalling using these structs gives me the same hex code as that obtained from asn playground. But, the unmarshalling fails with the following error:

十六进制代码:302aa00f800101810204d2820215b383021a0a81020a0ba20b80019c810200be820200c883020c0d8402309c

Hex code: 302aa00f800101810204d2820215b383021a0a81020a0ba20b80019c810200be820200c883020c0d8402309c

错误(当我尝试使用go代码解组十六进制代码(从asn游乐场)时遇到的错误):

Error (the same error I was getting before when I tried to unmarshall hex code (from asn playground) using go code):

解组时出错:asn1:结构错误:标签不匹配(0vs {class:2 tag:0 length:15 isCompound:true}){可选:false显式:假应用:真默认值:标记:0xc042008348stringType:0 timeType:0 set:false omitEmpty:false} MessageFields @ 2

Error while unmarshalling: asn1: structure error: tags don't match (0 vs {class:2 tag:0 length:15 isCompound:true}) {optional:false explicit:false application:true defaultValue: tag:0xc042008348 stringType:0 timeType:0 set:false omitEmpty:false} MessageFields @2

从结构中删除应用程序"标签可帮助我按预期解组十六进制代码.

EDIT 3: Removing the "application" tag from the structs helps me unmarshal the hex code as expected.

推荐答案

在其中输入类型的位置(使用工具以及

Where you input your types (with your tool as well as with http://asn1-playground.oss.com/), you must use a module. If not, it is not a valid asn1 specification (and your tool as well as oss.com should reject it).

My-module DEFINITIONS ::= 
BEGIN 

ACEI    ::= SEQUENCE {
etc ...

END

在不知道模块标记上下文的情况下工具接受编码类型的事实是在 https://上出现许多问题的原因stackoverflow.com/questions/tagged/asn.1

The fact that tools accept to encode types without knowing the module tagging context is the reason for many questions on https://stackoverflow.com/questions/tagged/asn.1

要回答第二个问题(关于长度的差异),您应该显示给oss.com的值是什么.

To answer the second question (about the difference of length), you should show what values you gave to oss.com .. it's likely:

neRegNumber  '0A0B'H
siteInfo     '0C0D'H    

它们都是2个字节长

但是当您编写 [] byte("0A0B")时,您肯定会要求Go为您提供字符串"0A0B"的字节(以ASCII表示30 41 30 42)

But when you write []byte("0A0B") you are certainly asking Go to give you the bytes of the string "0A0B" (indeed 30 41 30 42 in ASCII)

我认为 [] byte {10,11} 应该为您提供'0A0B'H

已编辑

如果您的工具没有采用asn.1模块,您仍然可以自己进行自动标记

If your tool does not take an asn.1 module, you can still do the automatic tagging yourself

ACEI    ::= SEQUENCE {
message         [0] IMPLICIT MessageFields,
neRegNumber     [1] IMPLICIT OCTET STRING OPTIONAL,
gpsInfo         [2] IMPLICIT GpsInfo OPTIONAL,
siteInfo        [3] IMPLICIT OCTET STRING OPTIONAL,
nlementID       [4] IMPLICIT INTEGER(0..16777216) OPTIONAL,
...
}

GpsInfo         ::= SEQUENCE {
gpsLat      [0] IMPLICIT INTEGER(-900000000..900000000) OPTIONAL,
gpsLong     [1] IMPLICIT INTEGER(-1800000000..1800000000) OPTIONAL,
gpsAlt      [2] IMPLICIT INTEGER OPTIONAL,
...
}
MessageFields       ::= SEQUENCE {
messageSequence     [0] IMPLICIT INTEGER (1..65535),
bsId                [1] IMPLICIT INTEGER (1..65535) OPTIONAL,
neID                [2] IMPLICIT INTEGER(0..16777216) OPTIONAL, -- unsigned int
nelementID          [3] IMPLICIT INTEGER(0..16777216) OPTIONAL, -- unsigned int
...
}

编辑2(基于与@Aarvi聊天)

EDITED 2 (based on chat with @Aarvi)

我只是想到 https://golang.org/pkg/encoding/asn1/不涉及ASN.1编译器.

It just occurred to me that https://golang.org/pkg/encoding/asn1/ does not involve an ASN.1 compiler.

取而代之的是手动编写和注释Go结构.

Instead a Go struct is manually written and annotated.

因此,遵循ASN.1类型(在选择了AUTOMATICS TAGS的模块中)

So following ASN.1 type (in a module with AUTOMATICS TAGS selected)

GpsInfo         ::= SEQUENCE {
   gpsLat      INTEGER(-900000000..900000000) OPTIONAL,
   gpsLong     INTEGER(-1800000000..1800000000) OPTIONAL,
   gpsAlt      INTEGER OPTIONAL,
   ...
}

必须像这样手动编写

type GPSInfo struct {
    GpsLatitude  int `asn1:"tag:0,implicit,optional"`
    GpsLongitude int `asn1:"tag:1,implicit,optional"`
    GpsAltitude int `asn1:"tag:2,implicit,optional"`
}

这篇关于ASN.1使用go struct进行编组会使标签不匹配错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆