fix: HNVSK carries the signature's security profile version (PIN:2 for two-step) - #38
Merged
robocode13 merged 1 commit intoSep 13, 2026
Conversation
…r two-step) The encryption header was hardcoded to `PIN:1` while the signature header correctly sends `PIN:2` for a two-step TAN method. Consorsbank (BLZ 76030080) rejects that combination with `9010 Ungültiger Signaturaufbau: Fehler im Segmentaufbau` + `9800 Der Dialog wurde abgebrochen`, so no two-step dialog could ever be opened there. Evidence that the bank checks both headers: hbci4java commit 1982a78 (2019-09-17, "always send profile version 1") broke Consorsbank with this exact error and was reverted the same day in 9813da9; hbci4java has derived both headers from one getProfileVersion() ever since. python-fints has the mirror-image bug (HNSHK stuck at 1) and fails identically (raphaelm/python-fints#99). Measured against the live bank with this change: the dialog init is accepted (`0030 Auftrag empfangen - Sicherheitsfreigabe erforderlich`), the TAN step completes (`Angemeldet`), and HKSAL/HKKAZ follow with `3076`. DKB, ING and Postbank were not re-tested; the specification (FinTS 3.0 Security, PIN/TAN) defines the profile version per dialog, not per segment, so sending the same value in both headers is the conforming form. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113JyWvWThppT9YzAHQG6RA
robocode13
force-pushed
the
fix/hnvsk-security-profile-version
branch
from
September 13, 2026 09:25
c4b581c to
05224cc
Compare
Owner
|
Thank you for the contribution. I tested it successfully with four banks (DKB, ING, Renault, Baader) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
CustomerMessage.encode()hardcodes the encryption header toPIN:1, whilesign()correctly putsPIN:2into the signature header for a two-step TAN method. Consorsbank (BLZ 76030080,brokerage-hbci.consorsbank.de) rejects every message built that way:so a two-step dialog can never be opened there; only the one-step, method-less sync succeeds.
Why the bank is right to complain
SigHeadandCryptHeadfrom onegetProfileVersion()(1for one-step,2otherwise). On 2019-09-17 its author switched to "always send 1" (commit1982a78) — Consorsbank immediately broke with this exact9010and he reverted the same day (9813da9, "Sollte sich Consors tatsächlich an der Profil-Version stören?").The fix
HNVSK takes its
secVersionfrom the signature it wraps — one line. Two tests pin the behaviour (two-step →PIN:2in both headers, one-step →PIN:1in both).Measured
Against the live bank with this change and nothing else: dialog init with method 901 accepted (
0030 Auftrag empfangen - Sicherheitsfreigabe erforderlich+ HITAN reference), TAN step completes (Angemeldet, UPD received), HKSAL and HKKAZ follow with3076 Keine starke Authentifizierung erforderlich. I have not re-tested other banks; every bank that acceptedPIN:1before did so while the signature already saidPIN:2, so the risk is a bank that requires the headers to disagree, which none of the reference implementations do.Related: #36 fixes the second thing Consorsbank rejects (HKKAZ v7 without the IBAN); I'll add the measurements there.
🤖 Generated with Claude Code
https://claude.ai/code/session_0113JyWvWThppT9YzAHQG6RA