Skip to content

Commit 2b646b8

Browse files
author
markus.rauscher
committed
Fix HNSHK security profile version for two-step PIN/TAN authentication
The HNSHK signature header always used SecurityProfile(PIN, 1) (one-step) even when two-step TAN authentication was active. This caused an inconsistency: HNVSK (encryption) correctly used PIN:2 for two-step, but HNSHK (signature) still said PIN:1. Banks that strictly validate the security profile version (notably HypoVereinsbank/UniCredit) rejected the HKTAN segment with error 9210 ("Auftrag abgelehnt") because the signature header claimed one-step authentication while a two-step TAN segment was present in the message. This also fixes _bootstrap_mode never being reset after fetch_tan_mechanisms(), which caused 9075 SCA errors to be silently swallowed instead of properly raised. Fixes #213
1 parent e1384c0 commit 2b646b8

2 files changed

Lines changed: 6 additions & 1 deletion

File tree

fints/client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,9 @@ def fetch_tan_mechanisms(self):
13051305
else:
13061306
self.set_tan_mechanism('999')
13071307
self._ensure_system_id()
1308+
# Bootstrap phase (anonymous dialog with sf=999) is complete.
1309+
# Reset so that errors in subsequent authenticated dialogs are properly raised.
1310+
self._bootstrap_mode = False
13081311
if self.get_current_tan_mechanism():
13091312
# We already got a reply through _ensure_system_id
13101313
return self.get_current_tan_mechanism()

fints/security.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,14 @@ def __init__(self, pin):
9999
self.pin = pin
100100
self.pending_signature = None
101101
self.security_function = None
102+
self.security_method_version = 1
102103

103104
def sign_prepare(self, message: FinTSMessage):
104105
_now = datetime.datetime.now()
105106
rand = random.SystemRandom()
106107

107108
self.pending_signature = HNSHK4(
108-
security_profile=SecurityProfile(SecurityMethod.PIN, 1),
109+
security_profile=SecurityProfile(SecurityMethod.PIN, self.security_method_version),
109110
security_function=self.security_function,
110111
security_reference=rand.randint(1000000, 9999999),
111112
security_application_area=SecurityApplicationArea.SHM,
@@ -178,6 +179,7 @@ def __init__(self, client, security_function, *args, **kwargs):
178179
super().__init__(*args, **kwargs)
179180
self.client = client
180181
self.security_function = security_function
182+
self.security_method_version = 2
181183

182184
def _get_tan(self):
183185
retval = self.client._pending_tan

0 commit comments

Comments
 (0)