Есть ли анализатор Java для BER-TLV?
Я новичок в Java, поэтому я хотел бы использовать стандартное решение для стандартной задачи. Длина тегов и значений неизвестна.
7 ответов
Вы можете использовать этот анализатор BER-TLV: исходный код на git или скачать jar.
Примеры:
Как разобрать
byte[] bytes = HexUtil.parseHex("50045649534157131000023100000033D44122011003400000481F");
BerTlvParser parser = new BerTlvParser(LOG);
BerTlvs tlvs = parser.parse(bytes, 0, bytes.length);
Как построить
byte[] bytes = new BerTlvBuilder()
.addHex(new BerTag(0x50), "56495341")
.addHex(new BerTag(0x57), "1000023100000033D44122011003400000481F")
.buildArray();
Maven зависимость
<!-- https://mvnrepository.com/artifact/com.payneteasy/ber-tlv -->
<dependency>
<groupId>com.payneteasy</groupId>
<artifactId>ber-tlv</artifactId>
<version>1.0-8</version>
</dependency>
Я сделал простой парсер на основе информации, представленной здесь: http://www.codeproject.com/Articles/669147/Simple-TLV-Parser
Я не знаю, поддерживает ли этот код все стандарты, но он работает для меня.
public static Map<String, String> parseTLV(String tlv) {
if (tlv == null || tlv.length()%2!=0) {
throw new RuntimeException("Invalid tlv, null or odd length");
}
HashMap<String, String> hashMap = new HashMap<String, String>();
for (int i=0; i<tlv.length();) {
try {
String key = tlv.substring(i, i=i+2);
if ((Integer.parseInt(key,16) & 0x1F) == 0x1F) {
// extra byte for TAG field
key += tlv.substring(i, i=i+2);
}
String len = tlv.substring(i, i=i+2);
int length = Integer.parseInt(len,16);
if (length > 127) {
// more than 1 byte for lenth
int bytesLength = length-128;
len = tlv.substring(i, i=i+(bytesLength*2));
length = Integer.parseInt(len,16);
}
length*=2;
String value = tlv.substring(i, i=i+length);
//System.out.println(key+" = "+value);
hashMap.put(key, value);
} catch (NumberFormatException e) {
throw new RuntimeException("Error parsing number",e);
} catch (IndexOutOfBoundsException e) {
throw new RuntimeException("Error processing field",e);
}
}
return hashMap;
}
Пример кода C# для декодирования bertTlv
public class Tlv : ITlv, IFile
{
List<TlvModel> modelList=new();
string parser = "";
string length = "";
String empty = "";
string ascii = "";
int decValue = 0;
int step = 0;
public Tlv(String data)
{
TlvParser(data.Replace(" ",""));
}
public void readTag()
{
String line = "";
StreamReader sr = new StreamReader("taglist.txt");
while ((line = sr.ReadLine()) != null)
{
modelList.Add(new()
{
tag = line.Split(",")[0].Trim(),
description = line.Split(",")[1].Trim()
});
}
sr.Close();
}
public void insertTag()
{
try
{
StreamWriter sw = new StreamWriter("test.txt");
foreach (var item in modelList)
{
sw.WriteLine($"{item.tag},{item.description}");
}
sw.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}
}
public int writeFile(String parser)
{
StreamWriter sw = new StreamWriter("output.txt");
sw.WriteLine(parser);
sw.Close();
return 0;
}
private int TlvParser(String data, int i = 0, string tag = "")
{
if (i == 0)
{
readTag();
}
if (i < data.Length)
{
tag += data[i];
TlvModel model = getTag(tag);
if (model != null)
{
decValue = int.Parse(data.Substring(i + 1, 2), System.Globalization.NumberStyles.HexNumber);
// lengthControl(data,i+3,decValue);
if (model.description.Contains("Template"))
{
parser += $"{empty}|------ tag: {model.tag}({model.description})\n";
step += 1;
empty = Empty();
return TlvParser(data, i + 3, "");
}
else
{
parser += $"{empty}|------ tag: {model.tag}({model.description}){empty}|------ value --> {ConvertHex(data.Substring(i + 3, decValue * 2))} \n";
}
i += 3 + decValue * 2;
return TlvParser(data, i, "");
}
else
{
return TlvParser(data, i + 1, tag);
}
}
return writeFile(parser);
}
public TlvModel getTag(string tag)
{
return modelList.Find(i => i.tag == tag);
}
public string ConvertHex(string hex)
{
ascii = "";
for (int i = 0; i < hex.Length; i += 2)
{
ascii += System.Convert.ToChar(System.Convert.ToUInt32(hex.Substring(i, 2), 16));
}
return ascii;
}
private string Empty()
{
for (int s = 0; s < step; s++)
{
empty += "\t";
}
return empty;
}
public void setTag(TlvModel model)
{
modelList.Add(model);
insertTag();
}
}
Проект javaemvreader содержит некоторый код для анализа BER-TLV.
Я нашел классы Javacard для BER TLV. Надеюсь, что те помогают
Может быть, эта бесплатная библиотека может быть полезна для вас. Я использовал этот для простого анализа TLV. В любом случае это лицензия MIT, и вы можете ее изменить.
https://github.com/VakhoQ/tlv-encoder