PBOC-TLV编码格式解码

      PBOC的IC卡大部分数据都是 TLV 格式的TLV tag, length value 的缩写,tag是这个数据元的标示,length是这个数据元值的部分的长度,value则是该数据元的值。其中tag在pboc中最多占两个字节,第一个字节的编码规则 。 b8 b7 两位标识 tag 所属类别 这个可以暂时不用理 。b6 决定当前的 TLV 数据是一个单一的数据和复合结构的数据 复合的 TLV 是指 value 域里也包含一个或多个 TLV, 类似嵌套的编码格式 . b5~b1 如果全为 1 ,则说明这个 tag 下面还有一个子字节 占两个字节 否则 tag 占一个字节 。如果tag占用两个字节,第二个字节的编码格式, B8决定tag是否还有后绪的字节存在,因为前面说过,PBOC/EMV里的tag最多占两个字节所以该位保持为0。

     下面是解析TLV格式的java代码:

import java.util.HashMap;
import java.util.Map;

public class TLVDecode {
	Map tlvMap = new HashMap();

	/*
	 * 递归解析TLV格式数据
	 *  xuys 
	 *  2014-3-2
	 */
	public void decodeTLV(String srcTLV, int len) {
		if (srcTLV.substring(0, srcTLV.length()).length() > 0) {
			String[] st = new String[srcTLV.substring(0, srcTLV.length())
					.length() / 2];
			for (int t = 0; t < srcTLV.substring(0, srcTLV.length()).length() / 2; t++) {
				st[t] = srcTLV.substring(0, srcTLV.length()).substring(2 * t,
						2 * t + 2);
			}
			if ((Integer.valueOf(st[0], 16) & 0x20) != 0x20) { // 单一结构
				if ((Integer.parseInt(st[0], 16) & 0x1f) != 0x1f) { // tag为一个字节
					StringBuilder sbd = new StringBuilder();
					int dataLen = Integer.valueOf(st[1], 16) == 0x81 ? Integer
							.valueOf(st[2], 16) : Integer.valueOf(st[1], 16);
					int dt = 2;
					if (dataLen > 0x80) {
						dt = 3;
					}
					for (int t = dt; t < dataLen + dt; t++) {
						sbd.append(st[t]);
					}
					tlvMap.put(st[0], sbd.toString());
					if (len > dataLen + dt) {
						StringBuilder lastTlv = new StringBuilder();
						for (int t = dataLen + dt; t < st.length; t++) {
							lastTlv.append(st[t]);
						}
						decodeTLV(lastTlv.toString(), st.length
								- (dataLen + dt));
					}
				} else {// tag为两个字节
					StringBuilder sbd = new StringBuilder();
					int dataLen = Integer.valueOf(st[2], 16) == 0x81 ? Integer
							.valueOf(st[3], 16) : Integer.valueOf(st[2], 16);
					int dt = 3;
					if (dataLen > 0x80) {
						dt = 4;
					}
					for (int t = dt; t < dataLen + dt; t++) {
						sbd.append(st[t]);
					}
					tlvMap.put(st[0] + st[1], sbd.toString());
					if (len > dataLen + dt) {
						StringBuilder lastTlv = new StringBuilder();

						for (int t = dataLen + dt; t < st.length; t++) {
							lastTlv.append(st[t]);
						}
						decodeTLV(lastTlv.toString(), st.length
								- (dataLen + dt));
					}
				}

			} else { // 复合结构
				if ((Integer.valueOf(st[0], 16) & 0x1f) != 0x1f) { // tag为一个字节
					StringBuilder sbd = new StringBuilder();
					int dataLen = Integer.valueOf(st[1], 16) == 0x81 ? Integer
							.valueOf(st[2], 16) : Integer.valueOf(st[1], 16);
					int dt = 2;
					if (dataLen > 0x80) {
						dt = 3;
					}
					for (int t = dt; t < dataLen + dt; t++) {
						sbd.append(st[t]);
					}
					tlvMap.put(st[0], sbd.toString());
					decodeTLV(sbd.toString(), sbd.length() / 2);
					if (len > dataLen + dt) {
						StringBuilder lastTlv = new StringBuilder();
						for (int t = dataLen + dt; t < st.length; t++) {
							lastTlv.append(st[t]);
						}
						decodeTLV(lastTlv.toString(), st.length);
					}
				} else {// tag为两个字节
					StringBuilder sbd = new StringBuilder();
					// int tk = Integer.valueOf(st[2], 16);
					int dataLen = Integer.valueOf(st[2], 16) == 0x81 ? Integer
							.valueOf(st[3], 16) : Integer.valueOf(st[2], 16);
					int dt = 3;
					if (dataLen > 0x80) {
						dt = 4;
					}
					for (int t = dt; t < dataLen + dt; t++) {
						sbd.append(st[t]);
					}
					tlvMap.put(st[0] + st[1], sbd.toString());
					decodeTLV(sbd.toString(), sbd.length() / 2);
					if (len > dataLen + 4) {
						StringBuilder lastTlv = new StringBuilder();
						for (int t = dataLen + dt; t < st.length; t++) {
							lastTlv.append(st[t]);
						}
						decodeTLV(lastTlv.toString(), st.length);
					}
				}
			}
		}
	}

	public Map getTlvMap() {
		return tlvMap;
	}

	public void setTlvMap(Map tlvMap) {
		this.tlvMap = tlvMap;
	}

	/**
	 * @param args
	 * 测试程序
	 */
	public static void main(String[] args) {
		TLVDecode t = new TLVDecode();
		t.decodeTLV(
				"7081E09081B04174C908D9EFBB0F8978BF8C964C22F9ACAA03C5FAE97AC8DFB829C3320E22A4BF45A8DF8010A2B81B3770F801BA1F4FEBA72195FFBBAA48274DB0B44903709FF49D9BD4F414938E32C21419A2E877E08D1E21F8DA7725860CAF3D98FB61D3F5C2B95A9BE870741EA85DE4E82A1BEDEA2BC175AE4927A26817277BA0674198500D176A779641CEAE4BB9E25039A3AAC448BCDD7781238D7882A86DCCB8CB913820494C1BB9574201DEF582EC0404D65A9F320103922420CF86C702825B7A3DD811C5F0F61D6EED533458FEFE81C931AB58910BE9A2033E85C1918F0103",

				"7081E09081B04174C908D9EFBB0F8978BF8C964C22F9ACAA03C5FAE97AC8DFB829C3320E22A4BF45A8DF8010A2B81B3770F801BA1F4FEBA72195FFBBAA48274DB0B44903709FF49D9BD4F414938E32C21419A2E877E08D1E21F8DA7725860CAF3D98FB61D3F5C2B95A9BE870741EA85DE4E82A1BEDEA2BC175AE4927A26817277BA0674198500D176A779641CEAE4BB9E25039A3AAC448BCDD7781238D7882A86DCCB8CB913820494C1BB9574201DEF582EC0404D65A9F320103922420CF86C702825B7A3DD811C5F0F61D6EED533458FEFE81C931AB58910BE9A2033E85C1918F0103"
						.length() / 2);
		for (String tt : t.tlvMap.keySet()) {
			System.out.println(tt + " : " + t.tlvMap.get(tt));
		}
	}

}

 

你可能感兴趣的:(PBOC/EMV)