1.TLV
BER编码的一种,ASN1标准,全称Tag(标签),Length(长度),Value(值)。
IS-IS数据通信领域中,tlv三元组: tag-length-value(TLV)。T、L字段的长度往往固定(通常为1~4bytes),V字段长度可变。顾名思义,T字段表示报文类型,L字段表示报文长度、V字段往往用来存放报文的内容。
前面有讲,哎,来个法师,2金开个传送门,
https://blog.csdn.net/qq_14945847/article/details/79369041
但是TLV格式怎么解析呢?
2.解析TLV
public class Tlv {
/** 子域Tag标签 */
private String tag;
/** 子域取值的长度 */
private int length;
/** 子域取值 */
private String value;
public Tlv(String tag, int length, String value) {
this.length = length;
this.tag = tag;
this.value = value;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "tag=[" + this.tag + "]," + "length=[" + this.length + "]," + "value=[" + this.value + "]";
}
}
/**
* 将字符串转换为TLV对象
*
*/
public abstract class TlvUtils {
/**
* 将16进制字符串转换为TLV对象列表
* @param hexString
* @return
*/
public static List builderTlvList(String hexString) {
List tlvs = new ArrayList();
int position = 0;
while (position != StringUtils.length(hexString)) {
String _hexTag = getTag(hexString, position);
position += _hexTag.length();
LPositon l_position = getLengthAndPosition(hexString, position);
int _vl = l_position.get_vL();
position = l_position.get_position();
String _value = StringUtils.substring(hexString, position, position + _vl * 2);
position = position + _value.length();
tlvs.add(new Tlv(_hexTag, _vl, _value));
}
return tlvs;
}
/**
* 将16进制字符串转换为TLV对象MAP
* @param hexString
* @return
*/
public static Map builderTlvMap(String hexString) {
Map tlvs = new HashMap();
int position = 0;
while (position != hexString.length()) {
String _hexTag = getTag(hexString, position);
position += _hexTag.length();
LPositon l_position = getLengthAndPosition(hexString, position);
int _vl = l_position.get_vL();
position = l_position.get_position();
String _value = hexString.substring(position, position + _vl * 2);
position = position + _value.length();
tlvs.put(_hexTag, new Tlv(_hexTag, _vl, _value));
}
return tlvs;
}
/**
* 返回最后的Value的长度
*
* @param hexString
* @param position
* @return
*/
private static LPositon getLengthAndPosition(String hexString, int position) {
String firstByteString = hexString.substring(position, position + 2);
int i = Integer.parseInt(firstByteString, 16);
String hexLength = "";
if (((i >>> 7) & 1) == 0) {
hexLength = hexString.substring(position, position + 2);
position = position + 2;
} else {
// 当最左侧的bit位为1的时候,取得后7bit的值,
int _L_Len = i & 127;
position = position + 2;
hexLength = hexString.substring(position, position + _L_Len * 2);
// position表示第一个字节,后面的表示有多少个字节来表示后面的Value值
position = position + _L_Len * 2;
}
return new LPositon(Integer.parseInt(hexLength, 16), position);
}
/**
* 取得子域Tag标签
*
* @param hexString
* @param position
* @return
*/
private static String getTag(String hexString, int position) {
String firstByte = StringUtils.substring(hexString, position, position + 2);
int i = Integer.parseInt(firstByte, 16);
if ((i & 0x1f) == 0x1f) {
return hexString.substring(position, position + 4);
} else {
return hexString.substring(position, position + 2);
}
}
}
LPosition.java
/**
* @author liyongfei
* @description:
* @date 2019/10/15 14:00
*/
public class LPositon{
private int _vL;
private int _position;
public LPositon(int _vL, int _position) {
this._vL = _vL;
this._position = _position;
}
public int get_vL() {
return _vL;
}
public void set_vL(int _vL) {
this._vL = _vL;
}
public int get_position() {
return _position;
}
public void set_position(int _position) {
this._position = _position;
}
}
3.测试
import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
/**
* @author liyongfei
* @description:
* @date 2019/10/17 14:19
*/
public class TlvUtilsTest {
public static void main(String[] args) throws DecoderException {
//1.2.86.11.7.7550307"
String tlvString = "0C 12 E8 87 AA E5 AE 9A E4 B9 89 E6 89 A9 E5 B1 95 E5 9F 9F";
System.out.println("转化前:"+tlvString);
String hexString = StringUtils.remove(tlvString," ");
List tlvList = TlvUtils.builderTlvList(hexString);
StringBuilder stringBuilder = new StringBuilder();
System.out.println(JSON.toJSONString(tlvList));
for (Tlv tlv :tlvList){
stringBuilder.append(new String(Hex.decodeHex(tlv.getValue())));
}
System.out.println("转化后:"+stringBuilder.toString());
}
}
4.测试结果
"0C 12 E8 87 AA E5 AE 9A E4 B9 89 E6 89 A9 E5 B1 95 E5 9F 9F"其实就是一个数字证书里面的一个值,其实内容就是“自定义扩展
域”