这应该是非常基本的但是,我一直在摸不着头脑,所以我想我应该四处询问,所以提前感谢你的帮助。
所以我的问题是,我有这个序列:
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
我似乎无法找出原因。你们能帮我一把吗?
谢谢!
答案 0 :(得分: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
字段进行编码。这是一种标记类型,此处取决于可以构建的全局EXPLICIT
或IMPLICIT
选项:
- 如果是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
总而言之,我们(假设全球有意)
30 0c
80 04 75 73 65 72
81 04 70 61 73 73
总共14个字节
或全局EXPLICIT
30 0e
A0 06
16 04 75 73 65 72
81 04 70 61 73 73
总共16个字节
答案 1 :(得分:0)
userid
有效载荷为4个字节,加上1个字节用于有效载荷长度(4)和标签(IA5String)。这导致6字节TLV。 password
值为4个字节,加上1个字节表示有效负载长度(4)和标记(IA5String)。 SEQUENCE的有效载荷大小为12个字节。添加长度字节(12)和标记(SEQUENCE),您将得到14字节结构。
Microsoft网站上的更多信息:DER Transfer Syntax,Encoded Length and Value Bytes
答案 2 :(得分: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模块定义可以声明隐式标记,但我假设情况不是这样,因为您提到的现有解决方案也会给出长度为14对于SEQUENCE标签。
答案 3 :(得分: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;
}
}