Implemented signing messages (but cannot tell yet if it's working)
This commit is contained in:
parent
a6a7930c29
commit
bed585fc04
|
@ -1,12 +1,17 @@
|
|||
package net.dankito.fints
|
||||
|
||||
import net.dankito.fints.messages.MessageBuilder
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemID
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
||||
import net.dankito.fints.model.AccountCredentials
|
||||
import net.dankito.fints.model.BankInfo
|
||||
import net.dankito.fints.model.ProductInfo
|
||||
import net.dankito.fints.util.IBase64Service
|
||||
import net.dankito.utils.web.client.IWebClient
|
||||
import net.dankito.utils.web.client.OkHttpWebClient
|
||||
import net.dankito.utils.web.client.RequestParameters
|
||||
import net.dankito.utils.web.client.WebClientResponse
|
||||
|
||||
|
||||
open class FinTsClient(
|
||||
|
@ -16,15 +21,37 @@ open class FinTsClient(
|
|||
) {
|
||||
|
||||
|
||||
fun getBankInfo(bankInfo: BankInfo, productInfo: ProductInfo) {
|
||||
fun getAnonymousBankInfo(bankInfo: BankInfo, productInfo: ProductInfo) {
|
||||
val requestBody = messageBuilder.createAnonymousDialogInitMessage(bankInfo.countryCode, bankInfo.bankCode,
|
||||
productInfo.productName, productInfo.productVersion)
|
||||
|
||||
val response = getResponseForMessage(requestBody, bankInfo)
|
||||
|
||||
handleResponse(response)
|
||||
}
|
||||
|
||||
fun getBankInfo(credentials: AccountCredentials, bankInfo: BankInfo, productInfo: ProductInfo) {
|
||||
val requestBody = messageBuilder.createDialogInitMessage(bankInfo.countryCode, bankInfo.bankCode,
|
||||
credentials.customerId, KundensystemID.PinTan, KundensystemStatusWerte.Benoetigt, 0, 0, Dialogsprache.German,
|
||||
productInfo.productName, productInfo.productVersion)
|
||||
|
||||
val response = getResponseForMessage(requestBody, bankInfo)
|
||||
|
||||
handleResponse(response)
|
||||
}
|
||||
|
||||
|
||||
protected open fun getResponseForMessage(requestBody: String, bankInfo: BankInfo): WebClientResponse {
|
||||
val encodedRequestBody = base64Service.encode(requestBody)
|
||||
|
||||
val response = webClient.post(RequestParameters(bankInfo.finTsServerAddress, encodedRequestBody, "application/octet-stream"))
|
||||
return webClient.post(
|
||||
RequestParameters(bankInfo.finTsServerAddress, encodedRequestBody, "application/octet-stream")
|
||||
)
|
||||
}
|
||||
|
||||
protected open fun handleResponse(response: WebClientResponse) {
|
||||
val responseBody = response.body
|
||||
|
||||
if (response.isSuccessful && responseBody != null) {
|
||||
|
||||
val decodedResponse = decodeBase64Response(responseBody)
|
||||
|
|
|
@ -18,7 +18,7 @@ package net.dankito.fints.messages
|
|||
* nicht den Richtlinien entspricht, so ist dieser abzuweisen. Eine kreditinstitutsseitige Korrektur
|
||||
* der Auftragsdaten erfolgt nicht.
|
||||
*/
|
||||
class HbciCharset {
|
||||
open class HbciCharset {
|
||||
|
||||
companion object {
|
||||
val DefaultCharset = Charsets.ISO_8859_1
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
package net.dankito.fints.messages
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.*
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion
|
||||
import net.dankito.fints.messages.nachrichten.Nachricht
|
||||
import net.dankito.fints.messages.segmente.ISegmentNumberGenerator
|
||||
import net.dankito.fints.messages.segmente.Segment
|
||||
import net.dankito.fints.messages.segmente.SegmentNumberGenerator
|
||||
import net.dankito.fints.messages.segmente.implementierte.IdentifikationsSegment
|
||||
import net.dankito.fints.messages.segmente.implementierte.Nachrichtenabschluss
|
||||
import net.dankito.fints.messages.segmente.implementierte.Nachrichtenkopf
|
||||
import net.dankito.fints.messages.segmente.implementierte.Verarbeitungsvorbereitung
|
||||
import net.dankito.fints.messages.segmente.implementierte.*
|
||||
import net.dankito.fints.util.FinTsUtils
|
||||
|
||||
|
||||
/**
|
||||
* Takes the Segments of they payload, may signs and encrypts them, calculates message size,
|
||||
* adds the message header and closing, and formats the whole message to string.
|
||||
*/
|
||||
open class MessageBuilder(protected val generator: ISegmentNumberGenerator = SegmentNumberGenerator()) {
|
||||
open class MessageBuilder(protected val generator: ISegmentNumberGenerator = SegmentNumberGenerator(),
|
||||
protected val utils: FinTsUtils = FinTsUtils()) {
|
||||
|
||||
companion object {
|
||||
const val MessageHeaderLength = 30
|
||||
|
@ -39,8 +39,8 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
productVersion: String
|
||||
): String {
|
||||
|
||||
return createDialogInitMessage(bankCountryCode, bankCode, KundenID.Anonymous, KundensystemID.Anonymous,
|
||||
BPDVersion.VersionNotReceivedYet, UPDVersion.VersionNotReceivedYet, Dialogsprache.Default, productName, productVersion)
|
||||
return createDialogInitMessage(bankCountryCode, bankCode, KundenID.Anonymous, KundensystemID.Anonymous, KundensystemStatusWerte.NichtBenoetigt,
|
||||
BPDVersion.VersionNotReceivedYet, UPDVersion.VersionNotReceivedYet, Dialogsprache.Default, productName, productVersion, false)
|
||||
}
|
||||
|
||||
open fun createDialogInitMessage(
|
||||
|
@ -48,23 +48,29 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
bankCode: String,
|
||||
customerId: String,
|
||||
customerSystemId: String,
|
||||
status: KundensystemStatusWerte,
|
||||
bpdVersion: Int,
|
||||
updVersion: Int,
|
||||
language: Dialogsprache,
|
||||
productName: String,
|
||||
productVersion: String
|
||||
productVersion: String,
|
||||
signMessage: Boolean = true
|
||||
): String {
|
||||
|
||||
return createMessage(listOf(
|
||||
IdentifikationsSegment(generator.resetSegmentNumber(1), bankCountryCode, bankCode, customerId, customerSystemId),
|
||||
return createMessage(signMessage, bankCountryCode, bankCode, customerId, listOf(
|
||||
IdentifikationsSegment(generator.resetSegmentNumber(if (signMessage) 2 else 1), bankCountryCode, bankCode, customerId, customerSystemId, status),
|
||||
Verarbeitungsvorbereitung(generator.getNextSegmentNumber(), bpdVersion, updVersion, language, productName, productVersion)
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
open fun createMessage(payloadSegments: List<Segment>): String {
|
||||
open fun createMessage(signMessage: Boolean, bankCountryCode: Int, bankCode: String, customerId: String,
|
||||
payloadSegments: List<Segment>): String {
|
||||
|
||||
val payload = payloadSegments.joinToString(Nachricht.SegmentSeparator) { it.format() }
|
||||
val signedPayload = if (signMessage) { signPayload(2, bankCountryCode, bankCode, customerId, payloadSegments) }
|
||||
else { payloadSegments }
|
||||
|
||||
val payload = signedPayload.joinToString(Nachricht.SegmentSeparator) { it.format() }
|
||||
|
||||
val messageSize = payload.length + MessageHeaderLength + MessageClosingLength + AddedSeparatorsLength
|
||||
val messageNumber = Nachrichtennummer.FirstMessageNumber
|
||||
|
@ -77,4 +83,29 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
.joinToString(Nachricht.SegmentSeparator, postfix = Nachricht.SegmentSeparator)
|
||||
}
|
||||
|
||||
protected open fun signPayload(headerSegmentNumber: Int, bankCountryCode: Int, bankCode: String, customerId: String,
|
||||
payloadSegments: List<Segment>): List<Segment> {
|
||||
val controlReference = "1" // TODO
|
||||
|
||||
val signatureHeader = PinTanSignaturkopf(
|
||||
headerSegmentNumber,
|
||||
Sicherheitsfunktion.PIN_TAN_911, // TODO
|
||||
controlReference,
|
||||
"0",
|
||||
utils.formatDateTodayAsInt(),
|
||||
utils.formatTimeNowAsInt(),
|
||||
bankCountryCode,
|
||||
bankCode,
|
||||
customerId
|
||||
)
|
||||
|
||||
val signatureClosing = Signaturabschluss(
|
||||
generator.getNextSegmentNumber(),
|
||||
controlReference,
|
||||
"" // TODO
|
||||
)
|
||||
|
||||
return listOf(signatureHeader, *payloadSegments.toTypedArray(), signatureClosing)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package net.dankito.fints.messages.datenelemente.abgeleiteteformate
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Format: JJJJMMTT gemäß ISO 8601
|
||||
*
|
||||
* Erlaubt sind alle existenten Datumsangaben.
|
||||
*/
|
||||
open class Datum(date: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(date, 8, existenzstatus) {
|
||||
|
||||
companion object {
|
||||
const val HbciDateFormat = "yyyyMMdd"
|
||||
}
|
||||
|
||||
}
|
|
@ -9,5 +9,5 @@ import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDat
|
|||
*
|
||||
* Maximal 30 Zeichen
|
||||
*/
|
||||
abstract class Identifikation(identifikation: String, existenzstatus: Existenzstatus)
|
||||
: AlphanumerischesDatenelement(identifikation, existenzstatus, 30)
|
||||
abstract class Identifikation(identification: String, existenzstatus: Existenzstatus)
|
||||
: AlphanumerischesDatenelement(identification, existenzstatus, 30)
|
|
@ -0,0 +1,19 @@
|
|||
package net.dankito.fints.messages.datenelemente.abgeleiteteformate
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.ZiffernDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Format: hhmmss gemäß ISO 8601
|
||||
*
|
||||
* Gültige Uhrzeit. Es ist immer Ortszeit des sendenden Systems einzustellen.
|
||||
* Unterschiedliche Zeitzonen werden nicht unterstützt
|
||||
*/
|
||||
open class Uhrzeit(time: Int, existenzstatus: Existenzstatus) : ZiffernDatenelement(time, 6, existenzstatus) {
|
||||
|
||||
companion object {
|
||||
const val HbciTimeFormat = "HHmmss"
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,7 @@ import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenele
|
|||
* die im Nachrichtenkopf eingestellt ist und lediglich das syntaktische Format der
|
||||
* Nachricht, nicht jedoch deren Inhalt kennzeichnet.
|
||||
*/
|
||||
class BPDVersion(version: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(version, 3, existenzstatus) {
|
||||
open class BPDVersion(version: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(version, 3, existenzstatus) {
|
||||
|
||||
companion object {
|
||||
const val VersionNotReceivedYet = 0
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation
|
||||
|
||||
|
||||
/**
|
||||
* Eindeutig vergebene Kennung, anhand deren die Identifizierung des Benutzers erfolgt.
|
||||
* Die Vergabe obliegt dem Kreditinstitut. Das Kreditinstitut hat zu gewährleisten,
|
||||
* dass die Benutzerkennung institutsweit eindeutig ist. Sie kann beliebige Informationen
|
||||
* enthalten, darf aber bei Verwendung des RAH-Verfahrens aus Sicherheitsgründen nicht aus
|
||||
* benutzer- oder kreditinstitutsspezifischen Merkmalen hergeleitet werden.
|
||||
*/
|
||||
open class Benutzerkennung(identification: String) : Identifikation(identification, Existenzstatus.Mandatory)
|
|
@ -4,4 +4,4 @@ import net.dankito.fints.messages.Existenzstatus
|
|||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation
|
||||
|
||||
|
||||
class DialogId(dialogId: String) : Identifikation(dialogId, Existenzstatus.Mandatory)
|
||||
open class DialogId(dialogId: String) : Identifikation(dialogId, Existenzstatus.Mandatory)
|
|
@ -1,7 +1,7 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte
|
||||
|
||||
|
||||
enum class Dialogsprache(val code: String) {
|
||||
enum class Dialogsprache(override val code: String) : ICodeEnum {
|
||||
|
||||
Default("0"),
|
||||
|
||||
|
|
|
@ -20,16 +20,11 @@ import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
|||
* - 2: Englisch, Code ‚en’ (English), Subset Englisch, Codeset 1 (Latin 1)
|
||||
* - 3: Französisch, Code ‚fr’ (French), Subset Französisch, Codeset 1 (Latin 1)
|
||||
*/
|
||||
class DialogspracheDatenelement(language: Dialogsprache, existenzstatus: Existenzstatus)
|
||||
open class DialogspracheDatenelement(language: Dialogsprache, existenzstatus: Existenzstatus)
|
||||
: Code(language.code, AllowedValues, existenzstatus) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = listOf(
|
||||
Dialogsprache.Default.code,
|
||||
Dialogsprache.German.code,
|
||||
Dialogsprache.English.code,
|
||||
Dialogsprache.French.code
|
||||
)
|
||||
val AllowedValues = allCodes<Dialogsprache>()
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
|
||||
|
||||
open class FinTsKundensystemStatus : KundensystemStatus(KundensystemStatusWerte.NichtBenoetigt, Existenzstatus.Mandatory)
|
|
@ -31,4 +31,4 @@ import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenele
|
|||
* - Version 2.2: 220 (Spezifikationsstatus: obsolet)
|
||||
* - Version 3.0: 300
|
||||
*/
|
||||
class HbciVersionDatenelement(version: HbciVersion) : NumerischesDatenelement(version.versionNumber, 3, Existenzstatus.Mandatory)
|
||||
open class HbciVersionDatenelement(version: HbciVersion) : NumerischesDatenelement(version.versionNumber, 3, Existenzstatus.Mandatory)
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte
|
||||
|
||||
|
||||
inline fun <reified T : Enum<T>> allCodes(): List<String> {
|
||||
return enumValues<T>().map { (it as ICodeEnum).code }
|
||||
}
|
||||
|
||||
interface ICodeEnum {
|
||||
|
||||
val code: String
|
||||
|
||||
}
|
|
@ -21,6 +21,8 @@ open class KundensystemID(customerSystemId: String) : Identifikation(customerSys
|
|||
|
||||
companion object {
|
||||
const val Anonymous = "0"
|
||||
|
||||
const val PinTan = Anonymous
|
||||
}
|
||||
|
||||
}
|
|
@ -17,12 +17,7 @@ open class KundensystemStatus(status: KundensystemStatusWerte, existenzstatus: E
|
|||
: Code(status.code, AllowedValues, existenzstatus) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = listOf(
|
||||
KundensystemStatusWerte.NichtBenoetigt.code,
|
||||
KundensystemStatusWerte.Benoetigt.code
|
||||
)
|
||||
|
||||
val Anonymous = KundensystemStatusWerte.NichtBenoetigt
|
||||
val AllowedValues = allCodes<KundensystemStatusWerte>()
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte
|
||||
|
||||
|
||||
enum class KundensystemStatusWerte(val code: String) {
|
||||
enum class KundensystemStatusWerte(override val code: String) : ICodeEnum {
|
||||
|
||||
NichtBenoetigt("0"),
|
||||
|
||||
|
|
|
@ -9,4 +9,4 @@ import net.dankito.fints.messages.datenelemente.basisformate.ZiffernDatenelement
|
|||
* Das DE ist mit führenden Nullen auf die vorgegebene feste Länge aufzufüllen.
|
||||
* Dies ist erforderlich, damit die Nachrichtenlänge nicht mit der Länge des DE variiert.
|
||||
*/
|
||||
class Nachrichtengroesse(messageSize: Int) : ZiffernDatenelement(messageSize, 12, Existenzstatus.Mandatory)
|
||||
open class Nachrichtengroesse(messageSize: Int) : ZiffernDatenelement(messageSize, 12, Existenzstatus.Mandatory)
|
|
@ -17,7 +17,7 @@ import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenele
|
|||
* Nachrichten, deren Nummerierung nicht streng monoton aufsteigend erfolgt ist, werden
|
||||
* institutsseitig bzw. kundenseitig abgelehnt.
|
||||
*/
|
||||
class Nachrichtennummer(number: Int) : NumerischesDatenelement(number, 4, Existenzstatus.Mandatory) {
|
||||
open class Nachrichtennummer(number: Int) : NumerischesDatenelement(number, 4, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
const val FirstMessageNumber = 1
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.TextDatenelement
|
||||
|
||||
|
||||
open class NotAllowedDatenelement : TextDatenelement("", Existenzstatus.NotAllowed)
|
|
@ -15,5 +15,5 @@ import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDat
|
|||
* Kundenprodukte, die nach dem durch die Deutsche Kreditwirtschaft festgelegten Verfahren registriert
|
||||
* sind, müssen in dieses DE die vergebene Produktregistrierungsnummer einstellen.
|
||||
*/
|
||||
class Produktbezeichnung(name: String, existenzstatus: Existenzstatus)
|
||||
open class Produktbezeichnung(name: String, existenzstatus: Existenzstatus)
|
||||
: AlphanumerischesDatenelement(name, existenzstatus, 25)
|
|
@ -11,5 +11,5 @@ import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDat
|
|||
* Kundenprodukt, nicht eine ggf. verwendete interne FinTS-/HBCI-Bibliothek, zu füllen, um
|
||||
* Support-Anfragen leichter beantworten zu können.
|
||||
*/
|
||||
class Produktversion(version: String, existenzstatus: Existenzstatus)
|
||||
open class Produktversion(version: String, existenzstatus: Existenzstatus)
|
||||
: AlphanumerischesDatenelement(version, existenzstatus, 5)
|
|
@ -8,7 +8,7 @@ import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenele
|
|||
* Versionsnummer der Userparameterdaten (UPD). Bei jeder kreditinstitutsseitigen Änderung
|
||||
* wird die Version inkrementiert. (S. auch DE BPD-Version).
|
||||
*/
|
||||
class UPDVersion(version: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(version, 3, existenzstatus) {
|
||||
open class UPDVersion(version: Int, existenzstatus: Existenzstatus) : NumerischesDatenelement(version, 3, existenzstatus) {
|
||||
|
||||
companion object {
|
||||
const val VersionNotReceivedYet = 0
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class BereichDerSicherheitsapplikation(val abbreviation: String, override val code: String) : ICodeEnum {
|
||||
|
||||
SignaturkopfUndHBCINutzdaten("SHM", "1"),
|
||||
|
||||
VonSignaturkopfBisSignaturabschluss("SHT", "2")
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Information darüber, welche Daten vom kryptographischen Prozess verarbeitet werden.
|
||||
* Diese Information wird benötigt um z. B. zwischen relevanter und belangloser Reihenfolge
|
||||
* von Signaturen zu unterscheiden (vgl. [HBCI], Kapitel VI.4).
|
||||
*
|
||||
* Wenn SHM gewählt wird, so bedeutet dies, dass nur über den eigenen Signaturkopf sowie die
|
||||
* HBCI-Nutzdaten ein Hashwert gebildet wird, der in die Signatur eingeht. Dies entspricht
|
||||
* bei Mehrfachsignaturen einer bedeutungslosen Reihenfolge.
|
||||
*
|
||||
* Wenn SHT gewählt wird, dann werden auch alle schon vorhandenen Signaturköpfe und
|
||||
* -abschlüsse mitsigniert. Das heißt, dass die Reihenfolge der Signaturen relevant ist.
|
||||
*
|
||||
* Codierung:
|
||||
* - 1: Signaturkopf und HBCI-Nutzdaten (SHM)
|
||||
* - 2: Von Signaturkopf bis Signaturabschluss (SHT)
|
||||
*/
|
||||
open class BereichDerSicherheitsapplikationKodiert(domain: BereichDerSicherheitsapplikation)
|
||||
: Code(domain.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<BereichDerSicherheitsapplikation>()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Bezeichner für den Hashalgorithmusparameter.
|
||||
*
|
||||
* Codierung:
|
||||
* 1: IVC (Initialization value, clear text)
|
||||
*/
|
||||
open class BezeichnerFuerHashalgorithmusparameter : AlphanumerischesDatenelement("1", Existenzstatus.Mandatory, 3)
|
|
@ -0,0 +1,14 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Identifikation der Funktion der beschriebenen Partei, in diesem Falle des Kunden.
|
||||
*
|
||||
* Codierung:
|
||||
* - 1: Message Sender (MS), wenn ein Kunde etwas an sein Kreditinstitut sendet.
|
||||
* - 2: Message Receiver (MR), wenn das Kreditinstitut etwas an seinen Kunden sendet.
|
||||
*/
|
||||
open class BezeichnerFuerSicherheitspartei : AlphanumerischesDatenelement("1", Existenzstatus.Mandatory, 3)
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class DatumUndZeitbezeichner(override val code: String) : ICodeEnum {
|
||||
|
||||
Sicherheitszeitstempel("1"),
|
||||
|
||||
CertificateRevocationTime("2")
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Enthält die Bedeutung des Zeitstempels.
|
||||
*
|
||||
* Codierung:
|
||||
* 1: Sicherheitszeitstempel (STS)
|
||||
* 6: Certificate Revocation Time (CRT)
|
||||
*/
|
||||
open class DatumUndZeitbezeichnerKodiert(identifier: DatumUndZeitbezeichner)
|
||||
: Code(identifier.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<DatumUndZeitbezeichner>()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class Hashalgorithmus(override val code: String) : ICodeEnum {
|
||||
|
||||
SHA_256("3"),
|
||||
|
||||
SHA_384("4"),
|
||||
|
||||
SHA_512("5"),
|
||||
|
||||
SHA_256_SHA_256("6"),
|
||||
|
||||
Gegenseitig_vereinbart("999")
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Code des verwendeten Hash-Algorithmus.
|
||||
*
|
||||
* Codierung:
|
||||
* 1: SHA-1 (nicht zugelassen)
|
||||
* 2: belegt
|
||||
* 3: SHA-256
|
||||
* 4: SHA-384
|
||||
* 5: SHA-512
|
||||
* 6: SHA-256 / SHA-256
|
||||
* 999: Gegenseitig vereinbart (ZZZ); (nicht zugelassen)
|
||||
*/
|
||||
open class HashalgorithmusKodiert(algorithm: Hashalgorithmus) : Code(algorithm.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<Hashalgorithmus>()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Identifikation
|
||||
|
||||
|
||||
/**
|
||||
* Code, welcher die (Kommunikations-)Partei identifiziert. Bei Verwendung des
|
||||
* RAH-Verfahrens ist die Kundensystem-ID einzustellen.
|
||||
*/
|
||||
open class IdentifizierungDerPartei(identification: String) : Identifikation(identification, Existenzstatus.Optional) {
|
||||
|
||||
companion object {
|
||||
const val SynchronizingCustomerSystemId = "0"
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class Operationsmodus(override val code: String) : ICodeEnum {
|
||||
|
||||
/**
|
||||
* Nur für Verschlüsselung erlaubt (vgl. [HBCI], Kapitel VI.2.2)
|
||||
*/
|
||||
Cipher_Block_Chaining("2"),
|
||||
|
||||
/**
|
||||
* nicht zugelassen
|
||||
*/
|
||||
ISO_9796_1("16"),
|
||||
|
||||
/**
|
||||
* nicht zugelassen
|
||||
*/
|
||||
ISO_9796_2_mit_Zufallszahl("17"),
|
||||
|
||||
/**
|
||||
* nicht zugelassen
|
||||
*/
|
||||
RSASSA_PKCS_1_V1_5("18"),
|
||||
|
||||
/**
|
||||
* Nur für Verschlüsselung erlaubt
|
||||
*/
|
||||
RSAES_PKCS_1_V1_5("18"),
|
||||
|
||||
/**
|
||||
* Nur für Signatur erlaubt
|
||||
*/
|
||||
RSASSA_PSS("19"),
|
||||
|
||||
/**
|
||||
* nicht zugelassen
|
||||
*/
|
||||
Gegenseitig_vereinbart("999")
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Information über den Operationsmodus für den jeweils verwendeten Kryptoalgorithmus
|
||||
* (zur Signaturbildung oder zur Verschlüsselung).
|
||||
*
|
||||
* Codierung:
|
||||
* Siehe S. 102 oder [Operationsmodus]
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.6 DEG „Signaturalgorithmus“, S. 58):
|
||||
*
|
||||
* Operationsmodus, kodiert
|
||||
* FinTS-Füllwert, z. B. „16“
|
||||
*/
|
||||
open class OperationsmodusKodiert(mode: Operationsmodus) : Code(mode.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<Operationsmodus>()
|
||||
|
||||
val FinTsMockValue = Operationsmodus.ISO_9796_1
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
open class PinOrTan(pinOrTan: String) : AlphanumerischesDatenelement(pinOrTan, Existenzstatus.Mandatory)
|
|
@ -0,0 +1,27 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Der Inhalt dieses Feldes sollte derzeit nicht ausgewertet werden. Optional können aber
|
||||
* die nachfolgenden Festlegungen angewendet werden, sofern dies zwischen Kunde und
|
||||
* Kreditinstitut zuvor vereinbart wurde:
|
||||
*
|
||||
* 1. Dialoginitialisierung und -ende:
|
||||
* Die Rolle wird durch den Dialogführenden bestimmt. Es ist nur eine Signatur erlaubt.
|
||||
* Erlaubt ist nur der Wert ISS/wert12.
|
||||
*
|
||||
* 2. Auftragsnachricht:
|
||||
* Grundsätzlich gilt: Sobald die Rolle „WIT“ verwendet wird, muss dieser Benutzer mit der
|
||||
* Benutzerkennung aus der Dialoginitialisierung arbeiten. Auch der Benutzer „WIT“ muss
|
||||
* bankseitig entsprechend der Auftragsart am Konto des Benutzers „ISS“ berechtigt sein.
|
||||
* Die Reihenfolge der Signaturen ist beliebig.
|
||||
*
|
||||
* [Tabelle mit Werten]
|
||||
*
|
||||
* Auch bei Belegung dieses Feldes kann das Kundenprodukt nicht davon ausgehen, dass das
|
||||
* Feld kreditinstitutsseitig ausgewertet wird.
|
||||
*/
|
||||
open class RolleDesSicherheitslieferantenKodiert : AlphanumerischesDatenelement("1", Existenzstatus.Mandatory, 3)
|
|
@ -0,0 +1,14 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class Schluesselart(override val code: String) : ICodeEnum {
|
||||
|
||||
SchluesselZurErzeugungDigitalerSignaturen("D"),
|
||||
|
||||
Signierschluessel("S"),
|
||||
|
||||
Chiffrierschluessel("V")
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Information über die Art des Schlüssels.
|
||||
*
|
||||
* Beim Sicherheitsverfahren RAH steht die Schlüsselart in engem Zusammenhang mit dem
|
||||
* Datenelement "Verwendungszweck für öffentlichen Schlüssel". Die Inhalte beider
|
||||
* Datenelemente sind konsistent zu halten.
|
||||
*
|
||||
* Codierung:
|
||||
* D: Schlüssel zur Erzeugung digitaler Signaturen (DS-Schlüssel)
|
||||
* S: Signierschlüssel
|
||||
* V: Chiffrierschlüssel
|
||||
*
|
||||
* Der DS-Schlüssel steht nur im Zusammenhang mit einer Bankensignaturkarte zur Verfügung.
|
||||
*
|
||||
* Im Falle der Bankensignaturkarte ergibt sich folgende Zuordnung zu den Kartenschlüsseln:
|
||||
* - DS-Schlüssel: SK.CH.DS
|
||||
* - Signierschlüssel: SK.CH.AUT
|
||||
* - Chiffrierschlüssel: SK.CH.KE
|
||||
*/
|
||||
open class SchluesselartDatenelement(key: Schluesselart) : Code(key.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<Schluesselart>()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Schlüsselnummer des entsprechenden Schlüssels.
|
||||
*/
|
||||
open class Schluesselnummer(number: Int) : NumerischesDatenelement(number, 3, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
const val FinTsMockValue = 0
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Versionsnummer des entsprechenden Schlüssels.
|
||||
*/
|
||||
open class Schluesselversion(version: Int) : NumerischesDatenelement(version, 3, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
const val FinTsMockValue = 0
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class Sicherheitsfunktion(override val code: String) : ICodeEnum {
|
||||
|
||||
RAH_7_S("2"),
|
||||
|
||||
RAH_7_D("1"),
|
||||
|
||||
RAH_9_S("2"),
|
||||
|
||||
RAH_10_S("2"),
|
||||
|
||||
PIN_TAN_900("900"),
|
||||
|
||||
PIN_TAN_901("901"),
|
||||
|
||||
PIN_TAN_902("902"),
|
||||
|
||||
PIN_TAN_903("903"),
|
||||
|
||||
PIN_TAN_904("904"),
|
||||
|
||||
PIN_TAN_905("905"),
|
||||
|
||||
PIN_TAN_906("906"),
|
||||
|
||||
PIN_TAN_907("907"),
|
||||
|
||||
PIN_TAN_908("908"),
|
||||
|
||||
PIN_TAN_909("909"),
|
||||
|
||||
PIN_TAN_910("910"),
|
||||
|
||||
PIN_TAN_911("911"),
|
||||
|
||||
PIN_TAN_912("912"),
|
||||
|
||||
PIN_TAN_913("913"),
|
||||
|
||||
PIN_TAN_914("914"),
|
||||
|
||||
PIN_TAN_915("915"),
|
||||
|
||||
PIN_TAN_916("916"),
|
||||
|
||||
PIN_TAN_917("917"),
|
||||
|
||||
PIN_TAN_918("918"),
|
||||
|
||||
PIN_TAN_919("919"),
|
||||
|
||||
PIN_TAN_920("920"),
|
||||
|
||||
PIN_TAN_921("921"),
|
||||
|
||||
PIN_TAN_922("922"),
|
||||
|
||||
PIN_TAN_923("923"),
|
||||
|
||||
PIN_TAN_924("924"),
|
||||
|
||||
PIN_TAN_925("925"),
|
||||
|
||||
PIN_TAN_926("926"),
|
||||
|
||||
PIN_TAN_927("927"),
|
||||
|
||||
PIN_TAN_928("928"),
|
||||
|
||||
PIN_TAN_929("929"),
|
||||
|
||||
PIN_TAN_930("930"),
|
||||
|
||||
PIN_TAN_931("931"),
|
||||
|
||||
PIN_TAN_932("932"),
|
||||
|
||||
PIN_TAN_933("933"),
|
||||
|
||||
PIN_TAN_934("934"),
|
||||
|
||||
PIN_TAN_935("935"),
|
||||
|
||||
PIN_TAN_936("936"),
|
||||
|
||||
PIN_TAN_937("937"),
|
||||
|
||||
PIN_TAN_938("938"),
|
||||
|
||||
PIN_TAN_939("939"),
|
||||
|
||||
PIN_TAN_940("940"),
|
||||
|
||||
PIN_TAN_941("941"),
|
||||
|
||||
PIN_TAN_942("942"),
|
||||
|
||||
PIN_TAN_943("943"),
|
||||
|
||||
PIN_TAN_944("944"),
|
||||
|
||||
PIN_TAN_945("945"),
|
||||
|
||||
PIN_TAN_946("946"),
|
||||
|
||||
PIN_TAN_947("947"),
|
||||
|
||||
PIN_TAN_948("948"),
|
||||
|
||||
PIN_TAN_949("949"),
|
||||
|
||||
PIN_TAN_950("950"),
|
||||
|
||||
PIN_TAN_951("951"),
|
||||
|
||||
PIN_TAN_952("952"),
|
||||
|
||||
PIN_TAN_953("953"),
|
||||
|
||||
PIN_TAN_954("954"),
|
||||
|
||||
PIN_TAN_955("955"),
|
||||
|
||||
PIN_TAN_956("956"),
|
||||
|
||||
PIN_TAN_957("957"),
|
||||
|
||||
PIN_TAN_958("958"),
|
||||
|
||||
PIN_TAN_959("959"),
|
||||
|
||||
PIN_TAN_960("960"),
|
||||
|
||||
PIN_TAN_961("961"),
|
||||
|
||||
PIN_TAN_962("962"),
|
||||
|
||||
PIN_TAN_963("963"),
|
||||
|
||||
PIN_TAN_964("964"),
|
||||
|
||||
PIN_TAN_965("965"),
|
||||
|
||||
PIN_TAN_966("966"),
|
||||
|
||||
PIN_TAN_967("967"),
|
||||
|
||||
PIN_TAN_968("968"),
|
||||
|
||||
PIN_TAN_969("969"),
|
||||
|
||||
PIN_TAN_970("970"),
|
||||
|
||||
PIN_TAN_971("971"),
|
||||
|
||||
PIN_TAN_972("972"),
|
||||
|
||||
PIN_TAN_973("973"),
|
||||
|
||||
PIN_TAN_974("974"),
|
||||
|
||||
PIN_TAN_975("975"),
|
||||
|
||||
PIN_TAN_976("976"),
|
||||
|
||||
PIN_TAN_977("977"),
|
||||
|
||||
PIN_TAN_978("978"),
|
||||
|
||||
PIN_TAN_979("979"),
|
||||
|
||||
PIN_TAN_980("980"),
|
||||
|
||||
PIN_TAN_981("981"),
|
||||
|
||||
PIN_TAN_982("982"),
|
||||
|
||||
PIN_TAN_983("983"),
|
||||
|
||||
PIN_TAN_984("984"),
|
||||
|
||||
PIN_TAN_985("985"),
|
||||
|
||||
PIN_TAN_986("986"),
|
||||
|
||||
PIN_TAN_987("987"),
|
||||
|
||||
PIN_TAN_988("988"),
|
||||
|
||||
PIN_TAN_989("989"),
|
||||
|
||||
PIN_TAN_990("990"),
|
||||
|
||||
PIN_TAN_991("991"),
|
||||
|
||||
PIN_TAN_992("992"),
|
||||
|
||||
PIN_TAN_993("993"),
|
||||
|
||||
PIN_TAN_994("994"),
|
||||
|
||||
PIN_TAN_995("995"),
|
||||
|
||||
PIN_TAN_996("996"),
|
||||
|
||||
PIN_TAN_997("997"),
|
||||
|
||||
PIN_TAN_Einschritt_Verfahren("999")
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Abhängig von Sicherheitsprofil und Schlüsseltyp und HBCI-Version ist folgender Wert einzustellen:
|
||||
*
|
||||
* | Sicherheitsprofil | Schlüsseltyp | ab FinTS V3.0 |
|
||||
* | RAH-7 | S | 2 |
|
||||
* | RAH-7 | D | 1 |
|
||||
* | RAH-9 | S | 2 |
|
||||
* | RAH-10 | S | 2 |
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.4 Segment „Signaturkopf“, S. 58):
|
||||
*
|
||||
* Sicherheitsfunktion, kodiert
|
||||
* Beim Ein-Schritt-Verfahren ist der Wert „999“ einzustellen, beim Zwei-Schritt-Verfahren der entsprechende
|
||||
* in der BPD mitgeteilte Wert für das konkrete Verfahren „900“ bis „997“ (vgl. Kapitel B.8.2).
|
||||
*/
|
||||
open class SicherheitsfunktionKodiert(securityFunction: Sicherheitsfunktion)
|
||||
: Code(securityFunction.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<Sicherheitsfunktion>()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Referenzinformation, mit der die Verbindung zwischen Signaturkopf und dazu gehörigem
|
||||
* Signaturabschluss hergestellt werden kann. Die Sicherheitskontrollreferenz im
|
||||
* Signaturkopf muss mit der entsprechenden Information im Signaturabschluss übereinstimmen.
|
||||
*/
|
||||
open class Sicherheitskontrollreferenz(reference: String) : AlphanumerischesDatenelement(reference, Existenzstatus.Mandatory, 14)
|
|
@ -0,0 +1,18 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Sicherheitsrelevante Nachrichtenidentifikation (Signatur-ID), welche zur Verhinderung der
|
||||
* Doppeleinreichung, respektive Garantie der Nachrichtensequenzintegrität eingesetzt werden kann.
|
||||
*
|
||||
* Bei chipkartenbasierten Verfahren ist der Sequenzzähler der Chipkarte einzustellen. Dies ist
|
||||
* bei Typ-1 Karten der Wert „EF_SEQ“ in der Application DF_BANKING und bei SECCOS Banken-
|
||||
* Signaturkarten der Wert „usage counter“ der beiden Signierschlüssel SK.CH.DS und SK.CH.AUT.
|
||||
*
|
||||
* Bei softwarebasierten Verfahren wird die Sicherheitsreferenznummer auf Basis des DE
|
||||
* Kundensystem-ID und des DE Benutzerkennung der DEG Schlüsselnamen verwaltet.
|
||||
*/
|
||||
open class Sicherheitsreferenznummer(number: Int) : NumerischesDatenelement(number, 16, Existenzstatus.Mandatory)
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class Sicherheitsverfahren(override val code: String) : ICodeEnum {
|
||||
|
||||
RSA_AES_Hybridverfahren("RAH"),
|
||||
|
||||
PIN_TAN_Verfahren("PIN")
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Code des unterstützten Signatur- bzw. Verschlüsselungsalgorithmus.
|
||||
*
|
||||
* Weitere Informationen zu den Verfahren sind Kapitel B.1 zu entnehmen.
|
||||
*
|
||||
* Codierung:
|
||||
* - RAH: RSA-AES-Hybridverfahren
|
||||
* - PIN: PIN/TAN-Verfahren
|
||||
*/
|
||||
open class SicherheitsverfahrenCode(method: Sicherheitsverfahren) : Code(method.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<Sicherheitsverfahren>()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
|
||||
|
||||
|
||||
enum class Signaturalgorithmus(override val code: String) : ICodeEnum {
|
||||
|
||||
NichtZugelassen("1"),
|
||||
|
||||
RSA_Algorithmus("10")
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.allCodes
|
||||
|
||||
|
||||
/**
|
||||
* Kodierte Information über den Signaturalgorithmus.
|
||||
*
|
||||
* Codierung:
|
||||
* 1: nicht zugelassen
|
||||
* 10: RSA-Algorithmus (bei RAH)
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.6 DEG „Signaturalgorithmus“, S. 58):
|
||||
*
|
||||
* Signaturalgorithmus, kodiert
|
||||
* FinTS-Füllwert, z. B. „10“
|
||||
*/
|
||||
open class SignaturalgorithmusKodiert(algorithm: Signaturalgorithmus)
|
||||
: Code(algorithm.code, AllowedValues, Existenzstatus.Mandatory) {
|
||||
|
||||
companion object {
|
||||
val AllowedValues = allCodes<Signaturalgorithmus>()
|
||||
|
||||
val FinTsMockValue = Signaturalgorithmus.RSA_Algorithmus
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
|
||||
enum class VersionDesSicherheitsverfahrens(val methodNumber: Int) {
|
||||
|
||||
PIN_Ein_Schritt(1),
|
||||
|
||||
PIN_Zwei_Schritt(2),
|
||||
|
||||
RAH_7(7),
|
||||
|
||||
RAH_9(9),
|
||||
|
||||
RAH_10(10)
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.NumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Version des unterstützten Sicherheitsverfahrens (s. „Sicherheitsverfahren, Code“).
|
||||
*
|
||||
* In Kombination mit dem Sicherheitsverfahren RAH sind die folgenden Versionen gültig:
|
||||
*
|
||||
* | Version | Signaturverfahren | Schlüssellänge (bit) | Hashverfahren | Schlüsselart* |
|
||||
* | 7 | PKCS#1 PSS | ..2048 | SHA-256 | D, S, V |
|
||||
* | 9 | PKCS#1 PSS | ..2048 | SHA-256 | S, V |
|
||||
* | 10 | PKCS#1 PSS | ..2048 | SHA-256 | S, V |
|
||||
*
|
||||
* *s. Element „Schlüsselart“
|
||||
*
|
||||
* Andere als die genannten Profile sind nicht zulässig.
|
||||
*
|
||||
* Um Multibankfähigkeit zu gewährleisten, ist die Unterstützung des Verfahrens RAH-9 kundenund
|
||||
* kreditisinstitutsseitig verpflichtend.
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.1 DEG „Sicherheitsprofil“, S. 58):
|
||||
*
|
||||
* Version des Sicherheitsverfahrens
|
||||
* - „1“ : bei allen Nachrichten, wenn Dialog im Einschritt-Verfahren
|
||||
* - „2“ : bei allen Nachrichten, wenn Dialog im Zwei-Schritt-Verfahren
|
||||
|
||||
*/
|
||||
open class VersionDesSicherheitsverfahrensDatenelement(version: VersionDesSicherheitsverfahrens)
|
||||
: NumerischesDatenelement(version.methodNumber, 3, Existenzstatus.Mandatory)
|
|
@ -0,0 +1,15 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Code
|
||||
|
||||
|
||||
/**
|
||||
* Kodierte Information über die Verwendung des Hashalgorithmus.
|
||||
*
|
||||
* Im Zusammenhang mit Hash-Funktionen ist derzeit nur folgender Wert möglich:
|
||||
*
|
||||
* Codierung:
|
||||
* 1: Owner Hashing (OHA)
|
||||
*/
|
||||
open class VerwendungDesHashalgorithmusKodiert: Code("1", listOf("1"), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,15 @@
|
|||
package net.dankito.fints.messages.datenelemente.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.basisformate.AlphanumerischesDatenelement
|
||||
|
||||
|
||||
/**
|
||||
* Kodierte Information über die Verwendung des Signaturalgorithmus.
|
||||
*
|
||||
* Im Zusammenhang mit Signaturbildung ist derzeit nur folgender Wert möglich:
|
||||
*
|
||||
* Codierung:
|
||||
* 6: Owner Signing (OSG)
|
||||
*/
|
||||
open class VerwendungDesSignaturalgorithmusKodiert : AlphanumerischesDatenelement("6", Existenzstatus.Mandatory, 3)
|
|
@ -9,8 +9,8 @@ import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
|||
|
||||
open class Segmentkopf @JvmOverloads constructor(
|
||||
identifier: String,
|
||||
segmentNumber: Int,
|
||||
segmentVersion: Int,
|
||||
segmentNumber: Int = 0,
|
||||
bezugssegment: Int? = null
|
||||
|
||||
) : Datenelementgruppe(listOf(
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.PinOrTan
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
|
||||
|
||||
/**
|
||||
* Bei nicht-schlüsselbasierten Sicherheitsverfahren kann der Benutzer hier Angaben
|
||||
* zur Authentisierung machen. Ob das Feld verpflichtend ist, ist vom jeweiligen
|
||||
* Sicherheitsverfahren abhängig.
|
||||
*
|
||||
* Format: s. Spezifikation „Sicherheitsverfahren PIN/TAN“
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.7 Segment „Signaturabschluss“, S. 59)
|
||||
*
|
||||
* Es ist der Signaturabschluss gemäß [HBCI] ab Segmentversion 2 zu verwenden.
|
||||
*
|
||||
* Validierungsresultat
|
||||
* Dieses Feld darf nicht belegt werden.
|
||||
*
|
||||
* Benutzerdefinierte Signatur
|
||||
* Hier werden bei Verwendung des PIN/TAN-Verfahrens PIN und TAN eingestellt. Bei
|
||||
* Verwendung des Zwei-Schritt-Verfahrens mit Prozessvariante 2 darf eine TAN
|
||||
* ausschließlich über den Geschäftsvorfall HKTAN eingereicht werden, wobei pro
|
||||
* HKTAN nur die Verarbeitung einer einzelnen TAN zulässig ist. Ansonsten darf die
|
||||
* DE „TAN“ im Signaturabschluss nicht belegt werden; ihr Inhalt wird in diesem Fall
|
||||
* ignoriert und die TAN vom Institut entwertet. Gleiches gilt bei der nicht
|
||||
* zulässigen Übermittlung von mehreren TANs mit HKTAN. Bei der Verwendung im Rahmen
|
||||
* des Sicherheitsverfahrens HBCI darf die DEG nicht belegt werden. Ihr Inhalt wird
|
||||
* in diesem Fall ignoriert.
|
||||
*/
|
||||
open class BenutzerdefinierteSignatur(pinOrTan: String)
|
||||
: Datenelementgruppe(listOf(
|
||||
PinOrTan(pinOrTan)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,25 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.BezeichnerFuerHashalgorithmusparameter
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Hashalgorithmus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.HashalgorithmusKodiert
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.VerwendungDesHashalgorithmusKodiert
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
|
||||
|
||||
/**
|
||||
* Angaben zu einem kryptographischen Algorithmus, seinen Operationsmodus, sowie dessen Einsatz.
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.5 DEG „Hashalgorithmus“, S. 58):
|
||||
*
|
||||
* Wert des Hashalgorithmusparameters
|
||||
* Dieses Feld darf nicht belegt werden.
|
||||
*/
|
||||
open class HashalgorithmusDatenelementgruppe
|
||||
: Datenelementgruppe(listOf(
|
||||
VerwendungDesHashalgorithmusKodiert(),
|
||||
HashalgorithmusKodiert(Hashalgorithmus.Gegenseitig_vereinbart), // allowed: 3, 4, 5, 6
|
||||
BezeichnerFuerHashalgorithmusparameter()
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,46 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Benutzerkennung
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Schluesselart
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.SchluesselartDatenelement
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Schluesselnummer
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Schluesselversion
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung
|
||||
|
||||
|
||||
/**
|
||||
* Verwendeter Schlüsselname in strukturierter Form. Mit dieser Information kann die Referenz
|
||||
* auf einen Schlüssel hergestellt werden.
|
||||
*
|
||||
* Dabei enthält das DE „Benutzerkennung“ bei Schlüsseln des Kunden die Benutzerkennung, mit
|
||||
* der der Kunde eindeutig identifiziert wird. Bei Schlüsseln des Kreditinstituts ist dagegen
|
||||
* eine beliebige Kennung einzustellen, die dazu dient, den Kreditinstitutsschlüssel eindeutig
|
||||
* zu identifizieren. Diese Kennung darf weder einer anderen gültigen Benutzerkennung des
|
||||
* Kreditinstituts noch der Benutzerkennung für den anonymen Zugang entsprechen.
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.2 DEG „Schlüsselname“, S. 58):
|
||||
*
|
||||
* Schlüsselnummer
|
||||
* FinTS-Füllwert, z. B. „0“
|
||||
*
|
||||
* Schlüsselversion
|
||||
* FinTS-Füllwert, z. B. „0“
|
||||
*/
|
||||
open class Schluesselname(
|
||||
bankCountryCode: Int,
|
||||
bankCode: String,
|
||||
userIdentification: String,
|
||||
key: Schluesselart,
|
||||
keyNumber: Int,
|
||||
keyVersion: Int
|
||||
)
|
||||
: Datenelementgruppe(listOf(
|
||||
Kreditinstitutskennung(bankCountryCode, bankCode),
|
||||
Benutzerkennung(userIdentification),
|
||||
SchluesselartDatenelement(key),
|
||||
Schluesselnummer(keyNumber),
|
||||
Schluesselversion(keyVersion)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,16 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Datum
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Uhrzeit
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.DatumUndZeitbezeichner
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.DatumUndZeitbezeichnerKodiert
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
|
||||
|
||||
open class SicherheitsdatumUndUhrzeit(date: Int, time: Int)
|
||||
: Datenelementgruppe(listOf(
|
||||
DatumUndZeitbezeichnerKodiert(DatumUndZeitbezeichner.Sicherheitszeitstempel), // Als Bezeichner wird „1“ eingestellt, da es sich um einen Sicherheitszeitstempel handelt.
|
||||
Datum(date, Existenzstatus.Optional),
|
||||
Uhrzeit(time, Existenzstatus.Optional)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,32 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.NotAllowedDatenelement
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.BezeichnerFuerSicherheitspartei
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.IdentifizierungDerPartei
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
|
||||
|
||||
/**
|
||||
* Identifikation der im Sicherheitsprozess involvierten Parteien. Dient zur Übermittlung
|
||||
* der CID bei kartenbasierten Sicherheitsverfahren bzw. der Kundensystem-ID bei
|
||||
* softwarebasierten Verfahren (z. B. Speicherung der Schlüssel in einer Schlüsseldatei).
|
||||
*
|
||||
* Wenn eine Synchronisierung der Kundensystem-ID durchgeführt wird, ist als Identifizierung der Partei ‚0’ einzustellen.
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.3 DEG „Sicherheitsidentifikation, Details“, S. 58):
|
||||
*
|
||||
* CID
|
||||
* Dieses Feld darf nicht belegt werden.
|
||||
*
|
||||
* Identifizierung der Partei
|
||||
* Dieses Feld muss eine gültige, zuvor vom Banksystem angeforderte Kundensystem-ID enthalten
|
||||
* (analog zu RAH-/RDH-Verfahren). Dies gilt auch für Zweit- und Drittsignaturen.
|
||||
*/
|
||||
open class SicherheitsidentifikationDetails(partyIdentification: String)
|
||||
: Datenelementgruppe(listOf(
|
||||
BezeichnerFuerSicherheitspartei(),
|
||||
NotAllowedDatenelement(),
|
||||
IdentifizierungDerPartei(partyIdentification)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,33 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsverfahren
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.SicherheitsverfahrenCode
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrensDatenelement
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
|
||||
|
||||
/**
|
||||
* Verfahren zur Absicherung der Transaktionen, das zwischen Kunde und Kreditinstitut
|
||||
* vereinbar wurde. Das Sicherheitsprofil wird anhand der Kombination der beiden Elemente
|
||||
* „Sicherheitsverfahren“ und „Version“ bestimmt (z. B. RDH-9). Für das Sicherheitsverfahren
|
||||
* PINTAN ist als Code der Wert PIN und als Version der Wert 1 einzustellen.
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.1 DEG „Sicherheitsprofil“, S. 58):
|
||||
*
|
||||
* Sicherheitsverfahren, Code
|
||||
* - „PIN“ : bei allen Nachrichten
|
||||
*
|
||||
* Version des Sicherheitsverfahrens
|
||||
* - „1“ : bei allen Nachrichten, wenn Dialog im Einschritt-Verfahren
|
||||
* - „2“ : bei allen Nachrichten, wenn Dialog im Zwei-Schritt-Verfahren
|
||||
*/
|
||||
open class Sicherheitsprofil(
|
||||
method: Sicherheitsverfahren,
|
||||
version: VersionDesSicherheitsverfahrens
|
||||
) : Datenelementgruppe(listOf(
|
||||
SicherheitsverfahrenCode(method),
|
||||
VersionDesSicherheitsverfahrensDatenelement(version)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,26 @@
|
|||
package net.dankito.fints.messages.datenelementgruppen.implementierte.signatur
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.*
|
||||
import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
|
||||
|
||||
|
||||
/**
|
||||
* Angaben zum kryptographischen Algorithmus, zu seinem Operationsmodus,
|
||||
* so wie zu dessen Einsatz, in diesem Fall für die Signaturbildung über RAH.
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.6 DEG „Signaturalgorithmus“, S. 58):
|
||||
*
|
||||
* Signaturalgorithmus, kodiert
|
||||
* FinTS-Füllwert, z. B. „10“
|
||||
*
|
||||
* Operationsmodus, kodiert
|
||||
* FinTS-Füllwert, z. B. „16“
|
||||
*/
|
||||
open class SignaturalgorithmusDatenelementgruppe (algorithm: Signaturalgorithmus, mode: Operationsmodus)
|
||||
: Datenelementgruppe(listOf(
|
||||
VerwendungDesSignaturalgorithmusKodiert(),
|
||||
SignaturalgorithmusKodiert(algorithm),
|
||||
OperationsmodusKodiert(mode)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -1,6 +1,7 @@
|
|||
package net.dankito.fints.messages.nachrichten.implementierte
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Nachrichtennummer.Companion.FirstMessageNumber
|
||||
import net.dankito.fints.messages.nachrichten.Nachricht
|
||||
import net.dankito.fints.messages.segmente.implementierte.IdentifikationsSegment
|
||||
|
@ -23,7 +24,7 @@ open class Dialoginitialisierung(
|
|||
)
|
||||
: Nachricht(listOf(
|
||||
Nachrichtenkopf(1, messageSize, "0", FirstMessageNumber),
|
||||
IdentifikationsSegment(2, bankCountryCode, bankCode, customerId, customerSystemId),
|
||||
IdentifikationsSegment(2, bankCountryCode, bankCode, customerId, customerSystemId, KundensystemStatusWerte.NichtBenoetigt), // TODO: KundensystemStatusWerte
|
||||
Verarbeitungsvorbereitung(3, bpdVersion, updVersion, language, productName, productVersion),
|
||||
Nachrichtenabschluss(4, FirstMessageNumber)
|
||||
))
|
|
@ -1,9 +1,10 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.FinTsKundensystemStatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundenID
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemID
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||
import net.dankito.fints.messages.segmente.Segment
|
||||
|
@ -14,12 +15,13 @@ open class IdentifikationsSegment(
|
|||
bankCountryCode: Int,
|
||||
bankCode: String,
|
||||
customerId: String,
|
||||
customerSystemId: String
|
||||
customerSystemId: String,
|
||||
status: KundensystemStatusWerte
|
||||
|
||||
) : Segment(listOf(
|
||||
Segmentkopf("HKIDN", segmentNumber, 2),
|
||||
Segmentkopf("HKIDN", 2, segmentNumber),
|
||||
Kreditinstitutskennung(bankCountryCode, bankCode),
|
||||
KundenID(customerId),
|
||||
KundensystemID(customerSystemId),
|
||||
FinTsKundensystemStatus()
|
||||
KundensystemStatus(status, Existenzstatus.Mandatory)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -9,10 +9,10 @@ import net.dankito.fints.messages.segmente.Segment
|
|||
/**
|
||||
* Dieses Segment beendet alle Kunden- und Kreditinstitutsnachrichten.
|
||||
*/
|
||||
class Nachrichtenabschluss(
|
||||
open class Nachrichtenabschluss(
|
||||
segmentNumber: Int,
|
||||
messageNumber: Int
|
||||
) : Segment(listOf(
|
||||
Segmentkopf("HNHBS", segmentNumber, 1),
|
||||
Segmentkopf("HNHBS", 1, segmentNumber),
|
||||
Nachrichtennummer(messageNumber)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -13,7 +13,7 @@ open class Nachrichtenkopf(
|
|||
messageNumber: Int
|
||||
|
||||
) : Segment(listOf(
|
||||
Segmentkopf("HNHBK", segmentNumber, 3),
|
||||
Segmentkopf("HNHBK", 3, segmentNumber),
|
||||
Nachrichtengroesse(messageSize),
|
||||
HbciVersionDatenelement(HbciVersion.FinTs_3_0_0),
|
||||
DialogId(dialogId),
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.*
|
||||
|
||||
|
||||
class PinTanSignaturkopf(
|
||||
segmentNumber: Int,
|
||||
securityFunction: Sicherheitsfunktion,
|
||||
securityControlReference: String,
|
||||
/**
|
||||
* Wenn eine Synchronisierung der Kundensystem-ID durchgeführt wird, ist als Identifizierung der Partei ‚0’ einzustellen.
|
||||
*/
|
||||
partyIdentification: String,
|
||||
date: Int,
|
||||
time: Int,
|
||||
bankCountryCode: Int,
|
||||
bankCode: String,
|
||||
userIdentification: String
|
||||
|
||||
) : Signaturkopf(
|
||||
segmentNumber,
|
||||
Sicherheitsverfahren.PIN_TAN_Verfahren,
|
||||
VersionDesSicherheitsverfahrens.PIN_Zwei_Schritt,
|
||||
securityFunction,
|
||||
securityControlReference,
|
||||
partyIdentification,
|
||||
date,
|
||||
time,
|
||||
SignaturalgorithmusKodiert.FinTsMockValue,
|
||||
OperationsmodusKodiert.FinTsMockValue,
|
||||
bankCountryCode,
|
||||
bankCode,
|
||||
userIdentification,
|
||||
Schluesselnummer.FinTsMockValue,
|
||||
Schluesselversion.FinTsMockValue
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.NotAllowedDatenelement
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitskontrollreferenz
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.BenutzerdefinierteSignatur
|
||||
import net.dankito.fints.messages.segmente.Segment
|
||||
|
||||
|
||||
/**
|
||||
* Der Signaturabschluss stellt die Verbindung mit dem dazugehörigen Signaturkopf
|
||||
* her und enthält als "Validierungsresultat" die elektronische Signatur.
|
||||
*/
|
||||
open class Signaturabschluss(
|
||||
segmentNumber: Int,
|
||||
securityControlReference: String,
|
||||
pinOrTan: String
|
||||
)
|
||||
: Segment(listOf(
|
||||
Segmentkopf("HNSHA", 2, segmentNumber),
|
||||
Sicherheitskontrollreferenz(securityControlReference), // has to be the same as in Signaturkopf
|
||||
NotAllowedDatenelement(), // only used for HBCI, not allowed for PIN/TAN
|
||||
BenutzerdefinierteSignatur(pinOrTan)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -0,0 +1,56 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.Existenzstatus
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.*
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.*
|
||||
import net.dankito.fints.messages.segmente.Segment
|
||||
|
||||
|
||||
/**
|
||||
* Der Signaturkopf enthält Informationen über den damit verbundenen Sicherheitsservice, sowie über den Absender.
|
||||
*
|
||||
*
|
||||
* Abweichende Belegung für PIN/TAN Verfahren (Dokument Sicherheitsverfahren PIN/TAN, B.9.4 Segment „Signaturkopf“, S. 58):
|
||||
*
|
||||
* Sicherheitsfunktion, kodiert
|
||||
* Beim Ein-Schritt-Verfahren ist der Wert „999“ einzustellen, beim Zwei-Schritt-Verfahren der entsprechende
|
||||
* in der BPD mitgeteilte Wert für das konkrete Verfahren „900“ bis „997“ (vgl. Kapitel B.8.2).
|
||||
*
|
||||
* Zertifikat
|
||||
* Dieses Feld darf nicht belegt werden.
|
||||
*/
|
||||
open class Signaturkopf(
|
||||
segmentNumber: Int,
|
||||
method: Sicherheitsverfahren,
|
||||
version: VersionDesSicherheitsverfahrens,
|
||||
securityFunction: Sicherheitsfunktion,
|
||||
securityControlReference: String,
|
||||
/**
|
||||
* Wenn eine Synchronisierung der Kundensystem-ID durchgeführt wird, ist als Identifizierung der Partei ‚0’ einzustellen.
|
||||
*/
|
||||
partyIdentification: String,
|
||||
date: Int,
|
||||
time: Int,
|
||||
algorithm: Signaturalgorithmus,
|
||||
mode: Operationsmodus,
|
||||
bankCountryCode: Int,
|
||||
bankCode: String,
|
||||
userIdentification: String,
|
||||
keyNumber: Int,
|
||||
keyVersion: Int
|
||||
|
||||
) : Segment(listOf(
|
||||
Segmentkopf("HNSHK", 4, segmentNumber), // allowed
|
||||
Sicherheitsprofil(method, version), // allowed: method: RAH, PIN;
|
||||
SicherheitsfunktionKodiert(securityFunction), // allowed: 1, 2
|
||||
Sicherheitskontrollreferenz(securityControlReference), // allowed: <>0
|
||||
BereichDerSicherheitsapplikationKodiert(BereichDerSicherheitsapplikation.SignaturkopfUndHBCINutzdaten), // allowed: 1 ?
|
||||
RolleDesSicherheitslieferantenKodiert(), // allowed: 1
|
||||
SicherheitsidentifikationDetails(partyIdentification),
|
||||
Sicherheitsreferenznummer(1), // TODO: is this always 1?
|
||||
SicherheitsdatumUndUhrzeit(date, time),
|
||||
HashalgorithmusDatenelementgruppe(),
|
||||
SignaturalgorithmusDatenelementgruppe(algorithm, mode),
|
||||
Schluesselname(bankCountryCode, bankCode, userIdentification, Schluesselart.Signierschluessel, keyNumber, keyVersion)
|
||||
), Existenzstatus.Mandatory)
|
|
@ -6,7 +6,7 @@ import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
|||
import net.dankito.fints.messages.segmente.Segment
|
||||
|
||||
|
||||
class Verarbeitungsvorbereitung(
|
||||
open class Verarbeitungsvorbereitung(
|
||||
segmentNumber: Int,
|
||||
bpdVersion: Int,
|
||||
updVersion: Int,
|
||||
|
@ -14,7 +14,7 @@ class Verarbeitungsvorbereitung(
|
|||
productName: String,
|
||||
productVersion: String
|
||||
) : Segment(listOf(
|
||||
Segmentkopf("HKVVB", segmentNumber, 3),
|
||||
Segmentkopf("HKVVB", 3, segmentNumber),
|
||||
BPDVersion(bpdVersion, Existenzstatus.Mandatory),
|
||||
UPDVersion(updVersion, Existenzstatus.Mandatory),
|
||||
DialogspracheDatenelement(language, Existenzstatus.Mandatory),
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package net.dankito.fints.util
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Datum
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Uhrzeit
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
open class FinTsUtils {
|
||||
|
||||
companion object {
|
||||
val HbciDateFormat = SimpleDateFormat(Datum.HbciDateFormat)
|
||||
|
||||
val HbciTimeFormat = SimpleDateFormat(Uhrzeit.HbciTimeFormat)
|
||||
}
|
||||
|
||||
|
||||
open fun formatDateToday(): String {
|
||||
return formatDate(Date())
|
||||
}
|
||||
|
||||
open fun formatDate(date: Date): String {
|
||||
return HbciDateFormat.format(date)
|
||||
}
|
||||
|
||||
open fun formatDateTodayAsInt(): Int {
|
||||
return convertToInt(formatDateToday())
|
||||
}
|
||||
|
||||
open fun formatDateAsInt(date: Date): Int {
|
||||
return convertToInt(formatDate(date))
|
||||
}
|
||||
|
||||
|
||||
open fun formatTimeNow(): String {
|
||||
return formatTime(Date())
|
||||
}
|
||||
|
||||
open fun formatTime(time: Date): String {
|
||||
return HbciTimeFormat.format(time)
|
||||
}
|
||||
|
||||
open fun formatTimeNowAsInt(): Int {
|
||||
return convertToInt(formatTimeNow())
|
||||
}
|
||||
|
||||
open fun formatTimeAsInt(time: Date): Int {
|
||||
return convertToInt(formatTime(time))
|
||||
}
|
||||
|
||||
|
||||
protected fun convertToInt(string: String): Int {
|
||||
return string.toInt()
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ package net.dankito.fints.messages.segmente.implementierte
|
|||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundenID
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemID
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.KundensystemStatusWerte
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Laenderkennzeichen
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
@ -13,7 +14,7 @@ class IdentifikationsSegmentTest {
|
|||
fun format() {
|
||||
|
||||
// given
|
||||
val underTest = IdentifikationsSegment(2, Laenderkennzeichen.Germany, "12345678", KundenID.Anonymous, KundensystemID.Anonymous)
|
||||
val underTest = IdentifikationsSegment(2, Laenderkennzeichen.Germany, "12345678", KundenID.Anonymous, KundensystemID.Anonymous, KundensystemStatusWerte.NichtBenoetigt)
|
||||
|
||||
// when
|
||||
val result = underTest.format()
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
class SignaturabschlussTest {
|
||||
|
||||
@Test
|
||||
fun format() {
|
||||
|
||||
// given
|
||||
val segmentNumber = 7
|
||||
val controlReference = "1902675680"
|
||||
val pin = "MyPin"
|
||||
|
||||
val underTest = Signaturabschluss(segmentNumber, controlReference, pin)
|
||||
|
||||
// when
|
||||
val result = underTest.format()
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("HNSHA:$segmentNumber:2+$controlReference++$pin")
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Laenderkennzeichen
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.IdentifizierungDerPartei
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
class SignaturkopfTest {
|
||||
|
||||
@Test
|
||||
fun format() {
|
||||
|
||||
// given
|
||||
val securityFunction = Sicherheitsfunktion.PIN_TAN_911
|
||||
val controlReference = "1902675680"
|
||||
val partyIdentification = IdentifizierungDerPartei.SynchronizingCustomerSystemId
|
||||
val date = 20191002
|
||||
val time = 212757
|
||||
val bankCode = "12345678"
|
||||
val customerId = "0987654321"
|
||||
val keyNumber = 0
|
||||
val keyVersion = 0
|
||||
|
||||
val underTest = PinTanSignaturkopf(2, securityFunction, controlReference, partyIdentification,
|
||||
date, time, Laenderkennzeichen.Germany, bankCode, customerId)
|
||||
|
||||
// when
|
||||
val result = underTest.format()
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("HNSHK:2:4+PIN:2+${securityFunction.code}+$controlReference+1+1+1::0+1+1:$date:$time+1:999:1+6:10:16+280:$bankCode:$customerId:S:$keyNumber:$keyVersion")
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package net.dankito.fints.util
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
|
||||
class FinTsUtilsTest {
|
||||
|
||||
private val underTest = FinTsUtils()
|
||||
|
||||
|
||||
@Test
|
||||
fun formatDate() {
|
||||
|
||||
// given
|
||||
val date = Date(88, 2, 27)
|
||||
|
||||
// when
|
||||
val result = underTest.formatDate(date)
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("19880327")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun formatDateAsInt() {
|
||||
|
||||
// given
|
||||
val date = Date(88, 2, 27)
|
||||
|
||||
// when
|
||||
val result = underTest.formatDateAsInt(date)
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo(19880327)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun formatTime_AM() {
|
||||
|
||||
// given
|
||||
val date = Date(119, 9, 1, 8, 2, 1)
|
||||
|
||||
// when
|
||||
val result = underTest.formatTime(date)
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("080201")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun formatTime_PM() {
|
||||
|
||||
// given
|
||||
val date = Date(119, 9, 1, 18, 22, 51)
|
||||
|
||||
// when
|
||||
val result = underTest.formatTime(date)
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("182251")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun formatTimeAsInt_AM() {
|
||||
|
||||
// given
|
||||
val date = Date(119, 9, 1, 8, 2, 1)
|
||||
|
||||
// when
|
||||
val result = underTest.formatTimeAsInt(date)
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo(80201)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun formatTimeAsInt_PM() {
|
||||
|
||||
// given
|
||||
val date = Date(119, 9, 1, 18, 22, 51)
|
||||
|
||||
// when
|
||||
val result = underTest.formatTimeAsInt(date)
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo(182251)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue