ASN.1长度编码(使用BER)

问题描述 投票:2回答:4

这应该是非常基本的但是,我已经在它周围摸了一下,所以我想我应该四处询问,所以提前感谢你的帮助。

所以我的问题是,我有这个序列:

User::=SEQUENCE {
userid [0] IA5String,
password [1] Implicit IA5String}

我想使用BER对以下内容进行编码,具有以下值:

{userid = "user", password = "pass"}

所以我们有3个“字段”TLV:

Tag is: 001 10000

我的问题是长度本身,应该是08(我认为来自“user”的04字节加上来自“pass”的04字节)。

但在我的解决方案中:

L -> 0 0 0 0 1 1 1 0 (=14)  0E

我似乎无法找出原因。你们能帮我一把吗?

谢谢!

asn.1
4个回答
3
投票

在BER和DER编码规则中,每个数据元素被编码为Tag-Length-Value序列。

在谈论未构造的类型(例如INTEGER或IA5String)时,值是根据该类型的规则编码的实际值。

当谈论构造类型(例如,SEQUENCE或SET)值时,包括在构造类型内的不同字段的BER / DER编码值。

考虑到这一点,我们可以采取你的类型

User::=SEQUENCE {
    userid [0] IA5String,
    password [1] IMPLICIT IA5String}

和你的数据价值

{userid = "user", password = "pass"}

我们可以开始编码了。

首先是SEQUENCE的标签,即0x30,然后它会长度,我们还不知道。现在我们应该编码构造的SEQUENCE的值。所以我们开始编码不同的字段。

我们需要编码userid字段。这是一个标记类型,在这里,取决于可以构造或不构造的全局EXPLICITIMPLICIT选项: - 如果是EXPLICIT,我们将有标签0xA0(对于构造上下文0),长度然后标记类型:IA5String是标记0x16(UNIVERSAL 22),其长度为0x04,其值为0x75 73 65 72 - 如果为IMPLICIT,我们将使用标记0x80(对于非构造的上下文0),长度为0x04,值为75 73 65 72

最后,我们需要对密码进行编码,在这种情况下我们没有疑问,添加了IMPLICIT关键字以强制隐式标记。所以我们将得到标签0x81(对于非构造的上下文1),长度为0x04,值为70 61 73 73

总而言之,我们有(假设全球IMPLICIT)

30 0c
   80 04 75 73 65 72
   81 04 70 61 73 73

总共14个字节

或者如果全球显示

30 0e
   A0 06
      16 04 75 73 65 72
   81 04 70 61 73 73

总共16个字节


0
投票

userid有效载荷是4个字节,加上1个字节用于有效载荷长度(4)和标签(IA5String)。这导致6字节TLV。 password值为4个字节,加上1个字节用于有效载荷长度(4)和标签(IA5String)。 SEQUENCE的有效载荷大小为12个字节。添加长度字节(12)和标记(SEQUENCE),您将得到14字节结构。

有关Microsoft网站的更多信息:DER Transfer SyntaxEncoded Length and Value Bytes


0
投票

请注意,序列的元素被标记,第一个显式(意味着在完整IA5String编码之前的“额外”标记/长度),第二个隐式(意味着替换原始IA5String标记/长度的标记/长度)。

所以,完整的编码将是300ea006160475736572810470617373:

30 CONSTRUCTED SEQUENCE
0e Length 14
a0 CONSTRUCTED TAGGED 0
06 Length 6
16 IA5String
04 Length 4
75 'u'
73 's'
65 'e'
72 'r'
81 TAGGED 1
04 Length 4
70 'p'
61 'a'
73 's'
73 's'

请注意,ASN.1模块定义可以默认声明隐式标记,但我假设情况并非如此,因为您提到的现有解决方案也为SEQUENCE标记提供了长度14。


0
投票
package binaryhex;

public class BinaryHex {

    public static void main(String[] args) {
        String s = "A8 59 A0 47 A0 15 80 01 01 81 02 01 F4 82 01 01 83 09 31 32 37 2E 30 2E 30 2E 31 81 07 32 33 30 5F 32 32 37 82 0E 32 30 31 36 30 38 32 32 31 34 35 36 31 30 83 01 00 84 01 00 A5 0F 80 03 44 53 4D 81 08 31 32 33 34 35 36 37 38 81 0E 32 30 31 36 30 38 32 32 31 34 35 36 31 30";
        String hexDumpStrWithoutSpace = s.replaceAll("\\s+", "");
        int length = calculateLength(hexDumpStrWithoutSpace);
        System.out.println("LENGTH: " + length);
    }

    private static int calculateLength(String hexDumpStrWithoutSpace) {
        int decimalValue = 0;
        boolean tag = false;
        int i = 0;
        while (!tag) {
            String typeSub = hexDumpStrWithoutSpace.substring(i, i + 2);
            StringBuilder typeBinSB = new StringBuilder();
            for (int j = 0; j < typeSub.length(); j++) {
                typeBinSB.append(hexToBinary("" + typeSub.charAt(j)));
            }
            String typeBin = typeBinSB.toString();
            if (typeBin.charAt(2) == '0') {
                int tagInt = Integer.parseInt(typeBin.substring(3), 2);
                System.out.println("TAG: " + tagInt);
                tag = true;
            } else {
                String tagStr = typeBin.substring(3 - i / 2);
                if (tagStr.equals("11111")) {
                    i = i + 2;
                    continue;
                } else {
                    int tagInt = Integer.parseInt(tagStr, 2);
                    System.out.println("TAG: " + tagInt);
                    tag = true;
                    i = i + 2;
                }

            }
        }

        for (; i < hexDumpStrWithoutSpace.length();) {
            String lengthSub = hexDumpStrWithoutSpace.substring(i, i + 2);

            StringBuilder lengthBinSB = new StringBuilder();
            for (int j = 0; j < lengthSub.length(); j++) {
                lengthBinSB.append(hexToBinary("" + lengthSub.charAt(j)));
            }
            String lengthBin = lengthBinSB.toString();
            if (lengthBin.charAt(0) == '0') {
                Integer lengthInt = Integer.parseInt(lengthBin, 2);
                decimalValue = lengthInt + i;
                break;
            } else {
                Integer lengthOctets = Integer.parseInt(lengthBin.substring(1), 2);
                StringBuilder toBinSB = new StringBuilder();

                for (int k = 0; k < lengthOctets; k++) {
                    i = i + 2;
                    String toBin = hexDumpStrWithoutSpace.substring(i, i + 2);
                    for (int j = 0; j < toBin.length(); j++) {
                        toBinSB.append(hexToBinary("" + toBin.charAt(j)));
                    }
                }
                String lengthResult = toBinSB.toString();
                Integer lengthValue = Integer.parseInt(lengthResult, 2);
                decimalValue = lengthValue + i - 2;
                break;
            }
        }

        return decimalValue;
    }

    static String hexToBinary(String hex) {
        int i = Integer.parseInt(hex, 16);
        String bin = Integer.toBinaryString(i);
        if (bin.length() < 4) {
            while (bin.length() < 4) {
                bin = "0" + bin;
            }
        }
        return bin;
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.