Fixed that challengeHHD_UC sometimes got decoded wrong, there was then a byte missing as binary data got unmasked

This commit is contained in:
dankito 2020-05-16 17:55:01 +02:00
parent 998c6d0c01
commit 231bf41cb3
7 changed files with 49 additions and 17 deletions

View File

@ -491,7 +491,7 @@ open class ResponseParser @JvmOverloads constructor(
protected open fun parseTanResponse(segment: String, dataElementGroups: List<String>): TanResponse { protected open fun parseTanResponse(segment: String, dataElementGroups: List<String>): TanResponse {
val binaryJobHashValue = if (dataElementGroups.size > 2) parseStringToNullIfEmpty(dataElementGroups[2]) else null val binaryJobHashValue = if (dataElementGroups.size > 2) parseStringToNullIfEmpty(dataElementGroups[2]) else null
val binaryChallengeHHD_UC = if (dataElementGroups.size > 5) parseStringToNullIfEmpty(dataElementGroups[5]) else null val binaryChallengeHHD_UC = if (dataElementGroups.size > 5 && dataElementGroups[5].isNotEmpty()) dataElementGroups[5] else null
return TanResponse( return TanResponse(
parseCodeEnum(dataElementGroups[1], TanProcess.values()), parseCodeEnum(dataElementGroups[1], TanProcess.values()),

View File

@ -20,11 +20,11 @@ open class TanImageDecoder {
val mimeType = challengeHHD_UC.substring(2, mimeTypeEnd) val mimeType = challengeHHD_UC.substring(2, mimeTypeEnd)
val imageLength = getLength(bytes[mimeTypeEnd], bytes[mimeTypeEnd + 1])
val imageStart = mimeTypeEnd + 2 val imageStart = mimeTypeEnd + 2
val imageString = challengeHHD_UC.substring(imageStart, imageStart + imageLength)
val imageBytes = imageString.toByteArray(HbciCharset.DefaultCharset) // sometimes it happened that imageStart + getLength(bytes[mimeTypeEnd], bytes[mimeTypeEnd + 1])
// was greater than challengeHHD_UC.length + 1 -> ignore image length and simply return all bytes starting with imageStart
val imageBytes = bytes.copyOfRange(imageStart, bytes.size)
return TanImage(mimeType, imageBytes) return TanImage(mimeType, imageBytes)
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -8,13 +8,21 @@ import net.dankito.fints.model.*
import net.dankito.fints.response.segments.AccountType import net.dankito.fints.response.segments.AccountType
import net.dankito.fints.response.segments.ChangeTanMediaParameters import net.dankito.fints.response.segments.ChangeTanMediaParameters
import net.dankito.fints.response.segments.JobParameters import net.dankito.fints.response.segments.JobParameters
import java.io.File
import java.math.BigDecimal import java.math.BigDecimal
import java.nio.charset.Charset
import java.util.* import java.util.*
abstract class FinTsTestBase { abstract class FinTsTestBase {
companion object { companion object {
const val TestFilesFolderName = "test_files/"
const val TransactionsMt940Filename = "TransactionsMt940.txt"
const val BankCode = "12345678" const val BankCode = "12345678"
const val BankCountryCode = Laenderkennzeichen.Germany const val BankCountryCode = Laenderkennzeichen.Germany
@ -87,4 +95,14 @@ abstract class FinTsTestBase {
return JobParameters("", 1, 1, 1, ":0:0") return JobParameters("", 1, 1, 1, ":0:0")
} }
/**
* testFilename has to be a file in src/test/resources/test_files/ folder
*/
protected open fun loadTestFile(testFilename: String, charset: Charset = Charsets.UTF_8): String {
val fileStream = FinTsTestBase::class.java.classLoader.getResourceAsStream(File(TestFilesFolderName, testFilename).path)
return fileStream.reader(charset).readText()
}
} }

View File

@ -1,6 +1,7 @@
package net.dankito.fints.response package net.dankito.fints.response
import net.dankito.fints.FinTsTestBase import net.dankito.fints.FinTsTestBase
import net.dankito.fints.messages.HbciCharset
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion
@ -11,6 +12,7 @@ import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Si
import net.dankito.fints.messages.segmente.id.ISegmentId import net.dankito.fints.messages.segmente.id.ISegmentId
import net.dankito.fints.messages.segmente.id.MessageSegmentId import net.dankito.fints.messages.segmente.id.MessageSegmentId
import net.dankito.fints.response.segments.* import net.dankito.fints.response.segments.*
import net.dankito.fints.tan.TanImageDecoder
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
@ -102,6 +104,27 @@ class ResponseParserTest : FinTsTestBase() {
assertThat(result.messageFeedback?.feedbacks?.map { it.message }).containsExactly("Nachricht nicht erwartet.", "Dialoginitialisierung abgebrochen.") assertThat(result.messageFeedback?.feedbacks?.map { it.message }).containsExactly("Nachricht nicht erwartet.", "Dialoginitialisierung abgebrochen.")
} }
@Test
fun `decode TanChallenge HHD_UC`() {
// given
val response = loadTestFile("Decode_TanChallengeHhdUc_WithMaskedCharacter.txt", HbciCharset.DefaultCharset)
// when
val result = underTest.parse(response)
// then
assertThat(result.successful).isTrue()
assertThat(result.tanResponse).isNotNull
val decodedChallengeHhdUc = TanImageDecoder().decodeChallenge(result.tanResponse?.challengeHHD_UC ?: "")
assertThat(decodedChallengeHhdUc.decodingSuccessful).isTrue()
assertThat(decodedChallengeHhdUc.imageBytes.size).isEqualTo(3664)
}
@Test @Test
fun parseMessageHeader() { fun parseMessageHeader() {

View File

@ -1,16 +1,12 @@
package net.dankito.fints.transactions package net.dankito.fints.transactions
import net.dankito.fints.FinTsTestBase
import net.dankito.fints.model.AccountData import net.dankito.fints.model.AccountData
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Test import org.junit.Test
class Mt940AccountTransactionsParserTest {
companion object { class Mt940AccountTransactionsParserTest : FinTsTestBase() {
const val TestFilesFolderName = "test_files/"
const val TransactionsMt940FileRelativePath = TestFilesFolderName + "TransactionsMt940.txt" // TODO: place in common file
}
private val underTest = Mt940AccountTransactionsParser() private val underTest = Mt940AccountTransactionsParser()
@ -20,8 +16,7 @@ class Mt940AccountTransactionsParserTest {
fun parseTransactions() { fun parseTransactions() {
// given // given
val fileStream = Mt940ParserTest::class.java.classLoader.getResourceAsStream(TransactionsMt940FileRelativePath) val transactionsString = loadTestFile(TransactionsMt940Filename)
val transactionsString = fileStream.reader().readText()
// when // when

View File

@ -15,9 +15,6 @@ import java.util.*
class Mt940ParserTest : FinTsTestBase() { class Mt940ParserTest : FinTsTestBase() {
companion object { companion object {
const val TestFilesFolderName = "test_files/"
const val TransactionsMt940FileRelativePath = TestFilesFolderName + "TransactionsMt940.txt"
const val Currency = "EUR" const val Currency = "EUR"
@ -134,8 +131,7 @@ class Mt940ParserTest : FinTsTestBase() {
fun parseTransactions() { fun parseTransactions() {
// given // given
val fileStream = Mt940ParserTest::class.java.classLoader.getResourceAsStream(TransactionsMt940FileRelativePath) val transactionsString = loadTestFile(TransactionsMt940Filename)
val transactionsString = fileStream.reader().readText()
// when // when