96 lines
No EOL
2.3 KiB
Kotlin
96 lines
No EOL
2.3 KiB
Kotlin
package net.dankito.fints.tan
|
|
|
|
import kotlin.math.floor
|
|
|
|
|
|
open class FlickercodeDecoder {
|
|
|
|
open fun decodeChallenge(challenge: String): String {
|
|
var code = challenge.toUpperCase().replace ("[^a-fA-F0-9]", "")
|
|
|
|
/* length check: first byte */
|
|
val len = code.length / 2 - 1
|
|
code = toHex(len, 2) + code.substring(2)
|
|
|
|
/* luhn checksum */
|
|
val luhndata = getPayload(code)
|
|
var luhnsum = 0
|
|
var i = 0
|
|
|
|
while (i < luhndata.length) {
|
|
luhnsum += 1 * parseIntToHex(luhndata[i]) + quersumme(2 * parseIntToHex(luhndata[i + 1]))
|
|
i += 2
|
|
}
|
|
|
|
luhnsum = (10 - luhnsum % 10) % 10
|
|
code = code.substring(0, code.length - 2) + toHex(luhnsum, 1) + code.substring(code.length - 1)
|
|
|
|
/* xor checksum */
|
|
var xorsum = 0
|
|
i = 0
|
|
while (i < code.length - 2) {
|
|
xorsum = xorsum xor parseIntToHex(code[i])
|
|
i++
|
|
}
|
|
|
|
code = code.substring(0, code.length - 1) + toHex(xorsum, 1)
|
|
|
|
return code
|
|
}
|
|
|
|
open fun toHex(number: Int, minLength: Int): String {
|
|
var result = number.toString (16).toUpperCase()
|
|
|
|
while (result.length < minLength) {
|
|
result = '0' + result
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
fun quersumme(number: Int): Int {
|
|
var quersumme = 0
|
|
var temp = number
|
|
|
|
while (temp != 0) {
|
|
quersumme += temp % 10
|
|
temp = floor(temp / 10.0).toInt()
|
|
}
|
|
|
|
return quersumme
|
|
}
|
|
|
|
fun getPayload(code: String): String {
|
|
var i = 0
|
|
var payload = ""
|
|
|
|
var len = parseIntToHex(code.substring(0, 2))
|
|
i += 2
|
|
|
|
while (i < code.length-2) {
|
|
/* skip bcd identifier */
|
|
i += 1
|
|
/* parse length */
|
|
len = parseIntToHex(code.substring(i, i + 1))
|
|
i += 1
|
|
// i = 4
|
|
var endIndex = i + len * 2
|
|
if (endIndex > code.length) {
|
|
endIndex = code.length
|
|
}
|
|
payload += code.substring(i, endIndex)
|
|
i += len * 2
|
|
}
|
|
|
|
return payload
|
|
}
|
|
|
|
protected open fun parseIntToHex(char: Char): Int {
|
|
return parseIntToHex(char.toString())
|
|
}
|
|
|
|
protected open fun parseIntToHex(string: String): Int {
|
|
return Integer.parseInt(string, 16)
|
|
}
|
|
|
|
} |