I am trying to remove some Unknown tags
(C3
, BF40
, C2
,.. etc) from ByteArray using TLVUtility (mastercard class from terminalSdk-2.0.3.jar
), Tags was not removing from the ByteArray. I am trying like this,
Here is my TLV Data I have,
ppseResponse = ByteUtility.hexStringToByteArray("6F54840E325041592E5359532E4444463031C30F4920414D2054484520424553542033BF4003C20101A52BBF0C28610C4F07A0000000041010870101610C4F07A0000000043060870103610A4F05B0123456788701099000")
I am trying this to remove the Unknown tags
like,
"BEFORE << ${ByteUtility.byteArrayToHexString(ppseResponse)}".toLog(activity, TAG) //To print Log
val unknownTags = byteArrayOf((0x00C3).toByte(),(0xBF40).toByte(), (0x00C2).toByte())
var removed = TLVUtility.removeTag(ppseResponse, ContentType.TLV,unknownTags)
"AFTER << ${ByteUtility.byteArrayToHexString(removed)}".toLog(activity, TAG) //To print Log
Here is the function removeTag
on terminalSdk-2.0.3.jar
function look likes,
public static byte[] removeTag(byte[] var0, ContentType var1, byte[] var2) {
int var10000;
Throwable var10001;
String var28;
label698: {
var10000 = 2 % 2;
if (var0 != null) {
label691: {
var10000 = g + 85;
f = var10000 % 128;
if (var10000 % 2 == 0) {
byte[] var26 = var2;
byte var27;
label676: {
label675: {
try {
null.hashCode();
if (var26 == null) {
break label675;
}
} catch (Throwable var25) {
throw var25;
}
var27 = 42;
break label676;
}
var27 = 74;
}
switch(var27) {
case 42:
break;
case 74:
default:
break label691;
}
} else if (var2 == null) {
break label691;
}
var10000 = f + 55;
g = var10000 % 128;
switch(var10000 % 2 != 0 ? 0 : 1) {
case 0:
default:
if (var2.length >= 1) {
break label698;
}
break;
case 1:
if (var2.length >= 1) {
break label698;
}
}
}
}
var28 = e(31, '卆', 490).intern();
try {
((Class)q.b(38, 8595, '\ue0f7')).getMethod("e", String.class).invoke((Object)null, var28);
} catch (Throwable var22) {
var10001 = var22.getCause();
if (var10001 != null) {
throw var10001;
}
throw var22;
}
throw new LibraryUncheckedException(ExceptionCode.X6F44);
}
label700: {
if (var1 == ContentType.T) {
var10000 = g + 15;
f = var10000 % 128;
if (var10000 % 2 == 0) {
if (var0.length < 0) {
break label700;
}
} else if (var0.length < 1) {
break label700;
}
}
switch(var1 != ContentType.TLV ? 81 : 64) {
case 81:
if (var1 != ContentType.TDO) {
break;
}
case 64:
default:
if (var0.length < 3) {
var28 = e(47, '\u0000', 560).intern();
try {
((Class)q.b(38, 8595, '\ue0f7')).getMethod("e", String.class).invoke((Object)null, var28);
} catch (Throwable var23) {
var10001 = var23.getCause();
if (var10001 != null) {
throw var10001;
}
throw var23;
}
throw new LibraryUncheckedException(ExceptionCode.X6F43);
}
}
ArrayList var3 = conditionalTlvParsing(var0, var1, e(1, '\u0000', 140).intern(), true);
Iterator var4 = var3.iterator();
while(var4.hasNext()) {
BerTlv var5 = (BerTlv)var4.next();
switch(var5.getTagObject().getNTag() == ByteUtility.byteArrayToInt(var2) ? 39 : 84) {
case 39:
default:
var4.remove();
case 84:
}
}
return formByteArrayFromTlvList(var3, var1);
}
var28 = e(39, '\u0000', 521).intern();
try {
((Class)q.b(38, 8595, '\ue0f7')).getMethod("e", String.class).invoke((Object)null, var28);
} catch (Throwable var24) {
var10001 = var24.getCause();
if (var10001 != null) {
throw var10001;
}
throw var24;
}
throw new LibraryUncheckedException(ExceptionCode.X6F43);
}
I fixed this issue by creating new custom function. Here is the function. Now on this function I am removing all the Unknown Tags
and its Skipping all Known Tags
and Third party data
and Optional Tags
Tags
First we need to define optional Tag,
private var optionalTags: ArrayList<ByteArray> = getOptionalTags()
Here is the function I am adding Optional Tags,
private fun getOptionalTags(): ArrayList<ByteArray> {
optionalTags = ArrayList()
optionalTags.add(ByteUtility.hexStringToByteArray("9F3E")) //Terminal Categories Supported List
optionalTags.add(ByteUtility.hexStringToByteArray("9F3F")) //Selection Data Object List
optionalTags.add(ByteUtility.hexStringToByteArray("9F2A")) //Kernel Identifier
optionalTags.add(ByteUtility.hexStringToByteArray("9F0A")) //Application Selection Registered Proprietary Data
return optionalTags
}
Here is the function to remove the Unknown tags,
private fun removeUnknownTags(ppseResponse: ByteArray): ByteArray {
var parentTags: MutableMap<ByteArray, Int> = LinkedHashMap()
var ppseResp = ppseResponse;
var i = 0
"PPSE (Length: ${ppseResp.size}) : HexString: ${ByteUtility.byteArrayToHexString(ppseResp)} \n ByteArray: ${ppseResp.toList()}".toLog()
while (i < ppseResp.size - 1) {
var removeTag = false;
var currentTag = TLVUtility.getCurrentTag(ppseResp, i);
var nextIndex = i + currentTag.size;
var tLVLengthInfo = TLVUtility.getTLVLengthInfo(ppseResp, nextIndex);
val tagLength = tLVLengthInfo.expectedNumberOfBytes
var tagValueSize = tLVLengthInfo.lengthBytes.size
var tagValue = ByteUtility.getSubByteArray(ppseResp, nextIndex + tagValueSize, tagLength)
"<==- ${i} : ${ByteUtility.byteArrayToHexString(currentTag)} (${TLVUtility.getReferenceTagDetails(currentTag).name}) , Length:${tagLength} (${tLVLengthInfo.lengthBytes.toList()} : ${ByteUtility.byteArrayToHexString(tLVLengthInfo.lengthBytes)}) , Max:${TLVUtility.getReferenceTagDetails(currentTag).maxLen} , Min:${TLVUtility.getReferenceTagDetails(currentTag).minLen} -==>".toLog()
"Value : ${ByteUtility.byteArrayToHexString(tagValue)} , Bytes:${tagValue.toList()}".toLog()
var tagNameLengthValue = ByteUtility.getSubByteArray(ppseResp, i, currentTag.size + tagValueSize + tagLength)
if (TLVUtility.getReferenceTagDetails(currentTag).name.contentEquals("Unknown Tag")) {
var optionalTag = false;
for (optTag in optionalTags) {
if (currentTag.contentEquals(optTag)) {
"${ByteUtility.byteArrayToHexString(currentTag)} is Optional Tag".toLog()
i = nextIndex + tagValueSize + tagLength;
optionalTag = true;
break
}
}
if (!optionalTag)
removeTag = true
} else if (TLVUtility.getReferenceTagDetails(currentTag).name.contentEquals("Third Party Data")) {
i = nextIndex + tagValueSize + tagLength;
} else {
if (!removeTag) {
if (TLVUtility.isTLVEncoded(tagValue)) {
parentTags.put(currentTag, i)
parentTags.entries.stream()
.sorted(Map.Entry.comparingByValue<ByteArray, Int>().reversed())
.forEachOrdered { x -> parentTags.put(x.key, x.value) }
if (tagValue.contentEquals(ByteUtility.hexStringToByteArray("00"))) {
i = nextIndex + tagValueSize + tagLength;
} else
i = nextIndex + tagValueSize
} else {
i = nextIndex + tagValueSize + tagLength;
}
}
}
if (removeTag) {
"-*-*-*-Removing TAG ${ByteUtility.byteArrayToHexString(currentTag)}-*-*-*-".toLog()
ppseResp = ByteUtility.getSubByteArray(ppseResp, 0, i) + ByteUtility.getSubByteArray(ppseResp, i + tagNameLengthValue.size)
var byteDiff = tagNameLengthValue.size
"--Updating Tag Length (Removed Bytes ${byteDiff})--".toLog()
for (tag in parentTags.entries.reversed()) {
var parentBytes = tag.key
var index = tag.value
var sizeIndex = index + parentBytes.size
var unknownTLVLengthInfo = TLVUtility.getTLVLengthInfo(ppseResp, sizeIndex);
val length = unknownTLVLengthInfo.expectedNumberOfBytes
if (i > index && i <= index + length) { //To Check is Parent Tag
"Parent Tag ${ByteUtility.byteArrayToHexString(tag.key)} (Bytes:${tag.key.toList()}) , Position:${tag.value}".toLog()
var lengthByteArray = unknownTLVLengthInfo.lengthBytes
var newLengthByteArray = ByteUtility.intToBerEncodedLength(length - byteDiff).bytes
var lengthDiff = lengthByteArray.size - newLengthByteArray.size;
byteDiff = byteDiff + lengthDiff
ppseResp = ByteUtility.getSubByteArray(ppseResp, 0, sizeIndex) + newLengthByteArray + ByteUtility.getSubByteArray(ppseResp, sizeIndex + lengthByteArray.size)
if (lengthDiff > 0) {
i = i - lengthDiff
for (child in parentTags.entries) {
if (child.value > tag.value) {
parentTags.replace(child.key, child.value - lengthDiff)
}
}
}
// "PPSE After (Length: ${ppseResp.size}): ${ByteUtility.byteArrayToHexString(ppseResp)} \n ByteArray: ${ppseResp.toList()}".toLog()
}
}
}
}
return ppseResp;
}