All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.binaryfoo.decoders.apdu.APDUSequenceDecoder.kt Maven / Gradle / Ivy

There is a newer version: 0.1.8
Show newest version
package io.github.binaryfoo.decoders.apdu

import io.github.binaryfoo.DecodedData
import io.github.binaryfoo.Decoder
import io.github.binaryfoo.decoders.DecodeSession

import java.util.ArrayList
import io.github.binaryfoo.decoders.IssuerPublicKeyDecoder
import io.github.binaryfoo.decoders.SignedStaticApplicationDataDecoder
import io.github.binaryfoo.decoders.ICCPublicKeyDecoder
import io.github.binaryfoo.decoders.SignedDynamicApplicationDataDecoder
import io.github.binaryfoo.decoders.annotator.BackgroundReading
import io.github.binaryfoo.hex.HexDumpElement
import kotlin.collections.firstOrNull
import kotlin.collections.forEach
import kotlin.collections.listOf
import kotlin.text.Regex
import kotlin.text.split
import kotlin.text.substring
import kotlin.text.toUpperCase

class APDUSequenceDecoder(private val replyDecoder: ReplyAPDUDecoder, vararg commandDecoders: CommandAPDUDecoder) : Decoder {
    private val _commandDecoders: Array = arrayOf(*commandDecoders)
    private val signedDataRecoverers = listOf(
        IssuerPublicKeyDecoder(),
        ICCPublicKeyDecoder(),
        SignedStaticApplicationDataDecoder(),
        SignedDynamicApplicationDataDecoder()
    )

    override fun decode(input: String, startIndexInBytes: Int, session: DecodeSession): List {
        var runningStartIndexInBytes = startIndexInBytes
        val list = ArrayList()
        input.toUpperCase().split(Regex("\\s+")).filter { it.isNotBlank() }.forEach { line ->
            try {
                val commandDecoder = getCommandDecoder(line)
                val decoded: DecodedData
                if (commandDecoder != null) {
                    session.currentCommand = commandDecoder.getCommand()
                    decoded = commandDecoder.decode(line, runningStartIndexInBytes, session)
                    decoded.category = "c-apdu"
                    decoded.backgroundReading = BackgroundReading.readingFor(commandDecoder.getCommand())
                } else {
                    decoded = replyDecoder.decode(line, runningStartIndexInBytes, session)
                    decoded.category = "r-apdu"
                }
                decoded.hexDump = HexDumpElement.splitIntoByteLengthStrings(line, runningStartIndexInBytes)
                runningStartIndexInBytes = decoded.endIndex
                list.add(decoded)
            } catch (e: Exception) {
                list.add(DecodedData.primitive(line, "Failed to decode: " + e.message, 0, 0))
            }
        }
        postProcess(list, session)
        return list
    }

    private fun getCommandDecoder(input: String): CommandAPDUDecoder? {
        val command = APDUCommand.fromHex(input.substring(0, 4))
        return _commandDecoders.firstOrNull { it.getCommand() == command }
    }

    override fun validate(input: String?): String? {
        return null
    }

    override fun getMaxLength(): Int {
        return Integer.MAX_VALUE
    }

    fun postProcess(decoded: List, session: DecodeSession) {
        for (processor in signedDataRecoverers) {
            try {
                processor.decodeSignedData(session, decoded)
            } catch(e: Exception) {
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy