@coderoftime/fints 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +152 -0
- package/LICENSE +28 -0
- package/README.md +246 -2
- package/dist/client.d.ts +48 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +199 -0
- package/dist/client.js.map +1 -0
- package/dist/core/account.d.ts +168 -0
- package/dist/core/account.d.ts.map +1 -0
- package/dist/core/account.js +245 -0
- package/dist/core/account.js.map +1 -0
- package/dist/core/amount.d.ts +63 -0
- package/dist/core/amount.d.ts.map +1 -0
- package/dist/core/amount.js +192 -0
- package/dist/core/amount.js.map +1 -0
- package/dist/core/balance.d.ts +55 -0
- package/dist/core/balance.d.ts.map +1 -0
- package/dist/core/balance.js +54 -0
- package/dist/core/balance.js.map +1 -0
- package/dist/core/bank-info.d.ts +49 -0
- package/dist/core/bank-info.d.ts.map +1 -0
- package/dist/core/bank-info.js +52 -0
- package/dist/core/bank-info.js.map +1 -0
- package/dist/core/client.d.ts +161 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +2 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/config.d.ts +80 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +153 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/errors.d.ts +153 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +247 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/feedback.d.ts +72 -0
- package/dist/core/feedback.d.ts.map +1 -0
- package/dist/core/feedback.js +127 -0
- package/dist/core/feedback.js.map +1 -0
- package/dist/core/transaction.d.ts +103 -0
- package/dist/core/transaction.d.ts.map +1 -0
- package/dist/core/transaction.js +96 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/transport.d.ts +64 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +149 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/formats/camt.d.ts +32 -0
- package/dist/formats/camt.d.ts.map +1 -0
- package/dist/formats/camt.js +242 -0
- package/dist/formats/camt.js.map +1 -0
- package/dist/formats/mt940.d.ts +54 -0
- package/dist/formats/mt940.d.ts.map +1 -0
- package/dist/formats/mt940.js +376 -0
- package/dist/formats/mt940.js.map +1 -0
- package/dist/formats/readers.d.ts +15 -0
- package/dist/formats/readers.d.ts.map +1 -0
- package/dist/formats/readers.js +42 -0
- package/dist/formats/readers.js.map +1 -0
- package/dist/formats/record-budget.d.ts +7 -0
- package/dist/formats/record-budget.d.ts.map +1 -0
- package/dist/formats/record-budget.js +17 -0
- package/dist/formats/record-budget.js.map +1 -0
- package/dist/formats/sepa-purpose.d.ts +28 -0
- package/dist/formats/sepa-purpose.d.ts.map +1 -0
- package/dist/formats/sepa-purpose.js +89 -0
- package/dist/formats/sepa-purpose.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/session/app-approval.d.ts +66 -0
- package/dist/session/app-approval.d.ts.map +1 -0
- package/dist/session/app-approval.js +226 -0
- package/dist/session/app-approval.js.map +1 -0
- package/dist/session/dialog-runner.d.ts +31 -0
- package/dist/session/dialog-runner.d.ts.map +1 -0
- package/dist/session/dialog-runner.js +111 -0
- package/dist/session/dialog-runner.js.map +1 -0
- package/dist/session/login-guard.d.ts +78 -0
- package/dist/session/login-guard.d.ts.map +1 -0
- package/dist/session/login-guard.js +181 -0
- package/dist/session/login-guard.js.map +1 -0
- package/dist/session/sepa-accounts.d.ts +40 -0
- package/dist/session/sepa-accounts.d.ts.map +1 -0
- package/dist/session/sepa-accounts.js +112 -0
- package/dist/session/sepa-accounts.js.map +1 -0
- package/dist/session/session-setup.d.ts +80 -0
- package/dist/session/session-setup.d.ts.map +1 -0
- package/dist/session/session-setup.js +182 -0
- package/dist/session/session-setup.js.map +1 -0
- package/dist/session/session-state.d.ts +50 -0
- package/dist/session/session-state.d.ts.map +1 -0
- package/dist/session/session-state.js +182 -0
- package/dist/session/session-state.js.map +1 -0
- package/dist/session/signed-dialog.d.ts +77 -0
- package/dist/session/signed-dialog.d.ts.map +1 -0
- package/dist/session/signed-dialog.js +170 -0
- package/dist/session/signed-dialog.js.map +1 -0
- package/dist/session/tan-selection.d.ts +96 -0
- package/dist/session/tan-selection.d.ts.map +1 -0
- package/dist/session/tan-selection.js +189 -0
- package/dist/session/tan-selection.js.map +1 -0
- package/dist/session/user-prompts.d.ts +65 -0
- package/dist/session/user-prompts.d.ts.map +1 -0
- package/dist/session/user-prompts.js +184 -0
- package/dist/session/user-prompts.js.map +1 -0
- package/dist/tan/challenge.d.ts +135 -0
- package/dist/tan/challenge.d.ts.map +1 -0
- package/dist/tan/challenge.js +184 -0
- package/dist/tan/challenge.js.map +1 -0
- package/dist/tan/flicker.d.ts +42 -0
- package/dist/tan/flicker.d.ts.map +1 -0
- package/dist/tan/flicker.js +296 -0
- package/dist/tan/flicker.js.map +1 -0
- package/dist/tan/tan-image.d.ts +22 -0
- package/dist/tan/tan-image.d.ts.map +1 -0
- package/dist/tan/tan-image.js +43 -0
- package/dist/tan/tan-image.js.map +1 -0
- package/dist/tan/tan-models.d.ts +149 -0
- package/dist/tan/tan-models.d.ts.map +1 -0
- package/dist/tan/tan-models.js +153 -0
- package/dist/tan/tan-models.js.map +1 -0
- package/dist/util/async.d.ts +22 -0
- package/dist/util/async.d.ts.map +1 -0
- package/dist/util/async.js +45 -0
- package/dist/util/async.js.map +1 -0
- package/dist/util/bytes.d.ts +22 -0
- package/dist/util/bytes.d.ts.map +1 -0
- package/dist/util/bytes.js +128 -0
- package/dist/util/bytes.js.map +1 -0
- package/dist/util/call-context.d.ts +12 -0
- package/dist/util/call-context.d.ts.map +1 -0
- package/dist/util/call-context.js +30 -0
- package/dist/util/call-context.js.map +1 -0
- package/dist/util/dates.d.ts +55 -0
- package/dist/util/dates.d.ts.map +1 -0
- package/dist/util/dates.js +189 -0
- package/dist/util/dates.js.map +1 -0
- package/dist/util/errors.d.ts +17 -0
- package/dist/util/errors.d.ts.map +1 -0
- package/dist/util/errors.js +24 -0
- package/dist/util/errors.js.map +1 -0
- package/dist/util/immutable-map.d.ts +16 -0
- package/dist/util/immutable-map.d.ts.map +1 -0
- package/dist/util/immutable-map.js +38 -0
- package/dist/util/immutable-map.js.map +1 -0
- package/dist/util/json.d.ts +17 -0
- package/dist/util/json.d.ts.map +1 -0
- package/dist/util/json.js +62 -0
- package/dist/util/json.js.map +1 -0
- package/dist/util/text.d.ts +37 -0
- package/dist/util/text.d.ts.map +1 -0
- package/dist/util/text.js +107 -0
- package/dist/util/text.js.map +1 -0
- package/dist/util/xml.d.ts +36 -0
- package/dist/util/xml.d.ts.map +1 -0
- package/dist/util/xml.js +194 -0
- package/dist/util/xml.js.map +1 -0
- package/dist/v3/account-extension.d.ts +25 -0
- package/dist/v3/account-extension.d.ts.map +1 -0
- package/dist/v3/account-extension.js +173 -0
- package/dist/v3/account-extension.js.map +1 -0
- package/dist/v3/bank-connection.d.ts +34 -0
- package/dist/v3/bank-connection.d.ts.map +1 -0
- package/dist/v3/bank-connection.js +58 -0
- package/dist/v3/bank-connection.js.map +1 -0
- package/dist/v3/dialog.d.ts +112 -0
- package/dist/v3/dialog.d.ts.map +1 -0
- package/dist/v3/dialog.js +241 -0
- package/dist/v3/dialog.js.map +1 -0
- package/dist/v3/message.d.ts +85 -0
- package/dist/v3/message.d.ts.map +1 -0
- package/dist/v3/message.js +303 -0
- package/dist/v3/message.js.map +1 -0
- package/dist/v3/parameter-store.d.ts +75 -0
- package/dist/v3/parameter-store.d.ts.map +1 -0
- package/dist/v3/parameter-store.js +143 -0
- package/dist/v3/parameter-store.js.map +1 -0
- package/dist/v3/parameters.d.ts +105 -0
- package/dist/v3/parameters.d.ts.map +1 -0
- package/dist/v3/parameters.js +450 -0
- package/dist/v3/parameters.js.map +1 -0
- package/dist/v3/protocol.d.ts +61 -0
- package/dist/v3/protocol.d.ts.map +1 -0
- package/dist/v3/protocol.js +113 -0
- package/dist/v3/protocol.js.map +1 -0
- package/dist/v3/queries.d.ts +51 -0
- package/dist/v3/queries.d.ts.map +1 -0
- package/dist/v3/queries.js +120 -0
- package/dist/v3/queries.js.map +1 -0
- package/dist/v3/segments.d.ts +106 -0
- package/dist/v3/segments.d.ts.map +1 -0
- package/dist/v3/segments.js +325 -0
- package/dist/v3/segments.js.map +1 -0
- package/dist/v3/syntax.d.ts +127 -0
- package/dist/v3/syntax.d.ts.map +1 -0
- package/dist/v3/syntax.js +367 -0
- package/dist/v3/syntax.js.map +1 -0
- package/package.json +67 -4
- package/src/client.ts +252 -0
- package/src/core/account.ts +323 -0
- package/src/core/amount.ts +211 -0
- package/src/core/balance.ts +85 -0
- package/src/core/bank-info.ts +66 -0
- package/src/core/client.ts +186 -0
- package/src/core/config.ts +182 -0
- package/src/core/errors.ts +277 -0
- package/src/core/feedback.ts +140 -0
- package/src/core/transaction.ts +161 -0
- package/src/core/transport.ts +189 -0
- package/src/formats/camt.ts +266 -0
- package/src/formats/mt940.ts +419 -0
- package/src/formats/readers.ts +49 -0
- package/src/formats/record-budget.ts +18 -0
- package/src/formats/sepa-purpose.ts +94 -0
- package/src/index.ts +70 -0
- package/src/session/app-approval.ts +278 -0
- package/src/session/dialog-runner.ts +122 -0
- package/src/session/login-guard.ts +221 -0
- package/src/session/sepa-accounts.ts +115 -0
- package/src/session/session-setup.ts +184 -0
- package/src/session/session-state.ts +204 -0
- package/src/session/signed-dialog.ts +192 -0
- package/src/session/tan-selection.ts +203 -0
- package/src/session/user-prompts.ts +193 -0
- package/src/tan/challenge.ts +261 -0
- package/src/tan/flicker.ts +308 -0
- package/src/tan/tan-image.ts +38 -0
- package/src/tan/tan-models.ts +252 -0
- package/src/util/async.ts +48 -0
- package/src/util/bytes.ts +129 -0
- package/src/util/call-context.ts +41 -0
- package/src/util/dates.ts +210 -0
- package/src/util/errors.ts +27 -0
- package/src/util/immutable-map.ts +47 -0
- package/src/util/json.ts +67 -0
- package/src/util/text.ts +112 -0
- package/src/util/xml.ts +183 -0
- package/src/v3/account-extension.ts +185 -0
- package/src/v3/bank-connection.ts +67 -0
- package/src/v3/dialog.ts +283 -0
- package/src/v3/message.ts +373 -0
- package/src/v3/parameter-store.ts +160 -0
- package/src/v3/parameters.ts +524 -0
- package/src/v3/protocol.ts +148 -0
- package/src/v3/queries.ts +190 -0
- package/src/v3/segments.ts +374 -0
- package/src/v3/syntax.ts +369 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { FormatError } from '../util/errors.js';
|
|
2
|
+
import { withoutWhitespace } from '../util/text.js';
|
|
3
|
+
// A combined challenge embeds the flicker code in the challenge text:
|
|
4
|
+
// `CHLGUC` + four-digit length + code + `CHLGTEXT` + four digits + instruction text.
|
|
5
|
+
const codeMarker = 'CHLGUC';
|
|
6
|
+
const textMarker = 'CHLGTEXT';
|
|
7
|
+
const markerLengthDigits = 4;
|
|
8
|
+
/** Whether `message` is a combined challenge with an embedded flicker code. */
|
|
9
|
+
export function hasEmbeddedFlickerCode(message) {
|
|
10
|
+
return message.includes(codeMarker);
|
|
11
|
+
}
|
|
12
|
+
/** The instruction text of a combined challenge; `message` itself if it is none. */
|
|
13
|
+
export function challengeInstruction(message) {
|
|
14
|
+
const start = message.indexOf(textMarker);
|
|
15
|
+
if (start < 0)
|
|
16
|
+
return message;
|
|
17
|
+
const textStart = start + textMarker.length + markerLengthDigits;
|
|
18
|
+
return textStart < message.length ? message.substring(textStart) : '';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Digit counts of the challenge length (LC) and of the data element lengths (LDE) to try when parsing.
|
|
22
|
+
*
|
|
23
|
+
* HHD 1.4 states the LC with three digits, HHD 1.3 with two. Some banks state the LDE of HHD 1.4 with three digits;
|
|
24
|
+
* a code that both LDE widths read is taken with two, as the specification has it.
|
|
25
|
+
*/
|
|
26
|
+
const layouts = [
|
|
27
|
+
{ lcDigits: 3, lengthDigits: 2 },
|
|
28
|
+
{ lcDigits: 3, lengthDigits: 3 },
|
|
29
|
+
{ lcDigits: 2, lengthDigits: 2 },
|
|
30
|
+
];
|
|
31
|
+
/** The most bytes a length field states: HHD 1.3 flags ASCII data in bit 4 of it, HHD 1.4 in bit 6. */
|
|
32
|
+
const maxElementLength = { hhd13: 0x0f, hhd14: 0x3f };
|
|
33
|
+
/** The most bytes of a rendered code, which its one-byte length (LC) states. */
|
|
34
|
+
const maxCodeLength = 0xff;
|
|
35
|
+
/** The characters a TAN generator shows; one byte each. */
|
|
36
|
+
const printableAscii = /^[\x20-\x7E]*$/;
|
|
37
|
+
function hex(value, width) {
|
|
38
|
+
return value.toString(16).toUpperCase().padStart(width, '0');
|
|
39
|
+
}
|
|
40
|
+
/** A chipTAN optical challenge (flicker code) in HHD 1.3 or 1.4 format. */
|
|
41
|
+
export class FlickerCode {
|
|
42
|
+
version;
|
|
43
|
+
lc;
|
|
44
|
+
startCode;
|
|
45
|
+
dataElements;
|
|
46
|
+
constructor(
|
|
47
|
+
/** The HHD version the code follows, told by the control bytes of its start code. */
|
|
48
|
+
version,
|
|
49
|
+
/** Length of the challenge (LC) as stated at the start of the code. */
|
|
50
|
+
lc, startCode, dataElements) {
|
|
51
|
+
this.version = version;
|
|
52
|
+
this.lc = lc;
|
|
53
|
+
this.startCode = startCode;
|
|
54
|
+
this.dataElements = dataElements;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parses the challenge data sent by the bank; throws `FormatError` if it is not a flicker code a TAN generator can
|
|
58
|
+
* take: one with characters after the length it states, an empty data element, data other than printable ASCII, or
|
|
59
|
+
* more data than its length fields can state, such as more than 15 bytes in an element in HHD 1.3 or 255 bytes in all.
|
|
60
|
+
*/
|
|
61
|
+
static parse(code) {
|
|
62
|
+
const cleaned = extractCode(code);
|
|
63
|
+
for (const layout of layouts) {
|
|
64
|
+
try {
|
|
65
|
+
return FlickerCode.parseLayout(new Reader(cleaned), layout.lcDigits, layout.lengthDigits);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// Not this layout; try the next one.
|
|
69
|
+
if (!(error instanceof FormatError))
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
throw new FormatError('Invalid flicker code', code);
|
|
74
|
+
}
|
|
75
|
+
/** Parses `code`, or returns `undefined` if it is not a flicker code. */
|
|
76
|
+
static tryParse(code) {
|
|
77
|
+
try {
|
|
78
|
+
return FlickerCode.parse(code);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error instanceof FormatError)
|
|
82
|
+
return undefined;
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
static parseLayout(code, lcDigits, lengthDigits) {
|
|
87
|
+
const lc = code.decimal(lcDigits);
|
|
88
|
+
const challenge = new Reader(code.take(lc));
|
|
89
|
+
// The start code has a hex length field whose top bit announces control bytes (HHD 1.4); the top bit of each
|
|
90
|
+
// control byte announces another one.
|
|
91
|
+
const startLength = challenge.hex(2);
|
|
92
|
+
const controlBytes = [];
|
|
93
|
+
if ((startLength & 0x80) !== 0) {
|
|
94
|
+
do {
|
|
95
|
+
controlBytes.push(challenge.hex(2));
|
|
96
|
+
} while ((controlBytes.at(-1) & 0x80) !== 0 && controlBytes.length < 10);
|
|
97
|
+
}
|
|
98
|
+
const startCode = new StartCode(challenge.take(startLength & 0x3f), controlBytes);
|
|
99
|
+
const dataElements = [];
|
|
100
|
+
for (let i = 0; i < 3; i++) {
|
|
101
|
+
dataElements.push(new DataElement(challenge.isAtEnd ? undefined : challenge.take(challenge.dataLength(lengthDigits))));
|
|
102
|
+
}
|
|
103
|
+
// Only a layout whose fields fill exactly the LC characters, which end the code, can be the right one.
|
|
104
|
+
if (!challenge.isAtEnd || !code.isAtEnd)
|
|
105
|
+
throw new FormatError('Flicker code fields do not match its length');
|
|
106
|
+
const flicker = new FlickerCode(controlBytes.length === 0 ? 'hhd13' : 'hhd14', lc, startCode, dataElements);
|
|
107
|
+
if (!flicker.fitsTanGenerator)
|
|
108
|
+
throw new FormatError('Flicker code data the TAN generator cannot take');
|
|
109
|
+
return flicker;
|
|
110
|
+
}
|
|
111
|
+
/** Whether the code renders as the bank sent it: its data printable ASCII, every length within its field. */
|
|
112
|
+
get fitsTanGenerator() {
|
|
113
|
+
const elements = [this.startCode, ...this.dataElements];
|
|
114
|
+
return elements.every((element) => element.fits(this.version)) && this.payload().length <= 2 * maxCodeLength;
|
|
115
|
+
}
|
|
116
|
+
/** The data of the start code, which opens the challenge. */
|
|
117
|
+
get startCodeData() {
|
|
118
|
+
return this.startCode.data ?? '';
|
|
119
|
+
}
|
|
120
|
+
/** The first data element of the challenge; `undefined` if the code leaves it out. */
|
|
121
|
+
get dataElement1() {
|
|
122
|
+
return this.dataElements[0]?.data;
|
|
123
|
+
}
|
|
124
|
+
/** The second data element of the challenge; `undefined` if the code leaves it out. */
|
|
125
|
+
get dataElement2() {
|
|
126
|
+
return this.dataElements[1]?.data;
|
|
127
|
+
}
|
|
128
|
+
/** The third data element of the challenge; `undefined` if the code leaves it out. */
|
|
129
|
+
get dataElement3() {
|
|
130
|
+
return this.dataElements[2]?.data;
|
|
131
|
+
}
|
|
132
|
+
/** The hex string transmitted to the TAN generator, including checksums. */
|
|
133
|
+
render() {
|
|
134
|
+
const payload = this.payload();
|
|
135
|
+
return `${payload}${this.luhnChecksum()}${xorChecksum(payload)}`;
|
|
136
|
+
}
|
|
137
|
+
payload() {
|
|
138
|
+
let s = this.startCode.renderLength(this.version);
|
|
139
|
+
for (const c of this.startCode.controlBytes)
|
|
140
|
+
s += hex(c, 2);
|
|
141
|
+
s += this.startCode.renderData();
|
|
142
|
+
for (const element of this.dataElements) {
|
|
143
|
+
s += element.renderLength(this.version);
|
|
144
|
+
s += element.renderData();
|
|
145
|
+
}
|
|
146
|
+
return `${hex(Math.floor((s.length + 2) / 2), 2)}${s}`;
|
|
147
|
+
}
|
|
148
|
+
luhnChecksum() {
|
|
149
|
+
let s = '';
|
|
150
|
+
for (const c of this.startCode.controlBytes)
|
|
151
|
+
s += hex(c, 2);
|
|
152
|
+
s += this.startCode.renderData();
|
|
153
|
+
for (const element of this.dataElements)
|
|
154
|
+
if (element.data !== undefined)
|
|
155
|
+
s += element.renderData();
|
|
156
|
+
let sum = 0;
|
|
157
|
+
for (let i = 0; i + 1 < s.length; i += 2) {
|
|
158
|
+
sum += parseInt(s[i], 16) + digitSum(2 * parseInt(s[i + 1], 16));
|
|
159
|
+
}
|
|
160
|
+
const mod = sum % 10;
|
|
161
|
+
return mod === 0 ? '0' : hex(10 - mod, 1);
|
|
162
|
+
}
|
|
163
|
+
/** Frames to animate: each is `[clock, bit0, bit1, bit2, bit3]` for the five bars. */
|
|
164
|
+
frames() {
|
|
165
|
+
const code = `0FFF${this.render()}`;
|
|
166
|
+
const result = [];
|
|
167
|
+
for (let i = 0; i + 1 < code.length; i += 2) {
|
|
168
|
+
for (const nibble of [code[i + 1], code[i]]) {
|
|
169
|
+
const v = parseInt(nibble, 16);
|
|
170
|
+
const bits = [(v & 1) !== 0, (v & 2) !== 0, (v & 4) !== 0, (v & 8) !== 0];
|
|
171
|
+
result.push([true, ...bits]);
|
|
172
|
+
result.push([false, ...bits]);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/** The code of a combined challenge, or `code` itself without whitespace. */
|
|
179
|
+
function extractCode(code) {
|
|
180
|
+
const compact = withoutWhitespace(code);
|
|
181
|
+
const start = compact.indexOf(codeMarker);
|
|
182
|
+
const codeStart = start + codeMarker.length + markerLengthDigits;
|
|
183
|
+
const end = compact.indexOf(textMarker);
|
|
184
|
+
return start >= 0 && end >= codeStart ? compact.substring(codeStart, end) : compact;
|
|
185
|
+
}
|
|
186
|
+
function xorChecksum(payload) {
|
|
187
|
+
let x = 0;
|
|
188
|
+
for (const c of payload)
|
|
189
|
+
x ^= parseInt(c, 16);
|
|
190
|
+
return hex(x, 1);
|
|
191
|
+
}
|
|
192
|
+
function digitSum(n) {
|
|
193
|
+
let sum = 0;
|
|
194
|
+
while (n !== 0) {
|
|
195
|
+
sum += n % 10;
|
|
196
|
+
n = Math.floor(n / 10);
|
|
197
|
+
}
|
|
198
|
+
return sum;
|
|
199
|
+
}
|
|
200
|
+
/** Reads the fields of a flicker code from left to right; throws `FormatError` when a field is missing or malformed. */
|
|
201
|
+
class Reader {
|
|
202
|
+
code;
|
|
203
|
+
position = 0;
|
|
204
|
+
constructor(code) {
|
|
205
|
+
this.code = code;
|
|
206
|
+
}
|
|
207
|
+
get remaining() {
|
|
208
|
+
return this.code.length - this.position;
|
|
209
|
+
}
|
|
210
|
+
get isAtEnd() {
|
|
211
|
+
return this.remaining === 0;
|
|
212
|
+
}
|
|
213
|
+
take(length) {
|
|
214
|
+
if (length > this.remaining)
|
|
215
|
+
throw new FormatError('Flicker code too short');
|
|
216
|
+
const field = this.code.substring(this.position, this.position + length);
|
|
217
|
+
this.position += length;
|
|
218
|
+
return field;
|
|
219
|
+
}
|
|
220
|
+
decimal(digits) {
|
|
221
|
+
return parseInt(Reader.match(/^[0-9]+$/, this.take(digits)), 10);
|
|
222
|
+
}
|
|
223
|
+
hex(digits) {
|
|
224
|
+
return parseInt(Reader.match(/^[0-9A-Fa-f]+$/, this.take(digits)), 16);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* A data element length field (LDE) of `digits` decimal digits: 1 to 63 characters. The challenge leaves out an
|
|
228
|
+
* element without data, and sets none of the flags in bits 6 and 7, which only the rendered code carries.
|
|
229
|
+
*/
|
|
230
|
+
dataLength(digits) {
|
|
231
|
+
const length = this.decimal(digits);
|
|
232
|
+
if (length === 0 || length > 0x3f)
|
|
233
|
+
throw new FormatError('Invalid data element length');
|
|
234
|
+
return length;
|
|
235
|
+
}
|
|
236
|
+
static match(pattern, field) {
|
|
237
|
+
if (!pattern.test(field))
|
|
238
|
+
throw new FormatError('Invalid length field', field);
|
|
239
|
+
return field;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A data element of the flicker code: a length field (LDE) followed by the data; `undefined` data if the code leaves
|
|
244
|
+
* the element out.
|
|
245
|
+
*/
|
|
246
|
+
class DataElement {
|
|
247
|
+
data;
|
|
248
|
+
constructor(data) {
|
|
249
|
+
this.data = data;
|
|
250
|
+
}
|
|
251
|
+
get isBcd() {
|
|
252
|
+
return this.data === undefined || /^[0-9]+$/.test(this.data);
|
|
253
|
+
}
|
|
254
|
+
/** Whether the data are printable ASCII, and no more bytes than the length field of `version` can state. */
|
|
255
|
+
fits(version) {
|
|
256
|
+
const d = this.data;
|
|
257
|
+
return d === undefined || (printableAscii.test(d) && this.renderData().length / 2 <= maxElementLength[version]);
|
|
258
|
+
}
|
|
259
|
+
renderData() {
|
|
260
|
+
const d = this.data;
|
|
261
|
+
if (d === undefined)
|
|
262
|
+
return '';
|
|
263
|
+
if (!this.isBcd) {
|
|
264
|
+
let ascii = '';
|
|
265
|
+
for (let i = 0; i < d.length; i++)
|
|
266
|
+
ascii += hex(d.charCodeAt(i), 2);
|
|
267
|
+
return ascii;
|
|
268
|
+
}
|
|
269
|
+
return d.length % 2 === 1 ? `${d}F` : d;
|
|
270
|
+
}
|
|
271
|
+
renderLength(version) {
|
|
272
|
+
if (this.data === undefined)
|
|
273
|
+
return '';
|
|
274
|
+
const length = Math.floor(this.renderData().length / 2);
|
|
275
|
+
if (this.isBcd)
|
|
276
|
+
return hex(length, 2);
|
|
277
|
+
if (version === 'hhd14')
|
|
278
|
+
return hex(length + 0x40, 2);
|
|
279
|
+
return `1${hex(length, 1)}`;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/** The start code: a data element whose length field may announce control bytes (HHD 1.4). */
|
|
283
|
+
class StartCode extends DataElement {
|
|
284
|
+
controlBytes;
|
|
285
|
+
constructor(data, controlBytes) {
|
|
286
|
+
super(data);
|
|
287
|
+
this.controlBytes = controlBytes;
|
|
288
|
+
}
|
|
289
|
+
renderLength(version) {
|
|
290
|
+
const s = super.renderLength(version);
|
|
291
|
+
if (version === 'hhd13' || this.controlBytes.length === 0)
|
|
292
|
+
return s;
|
|
293
|
+
return hex(parseInt(s, 16) + 0x80, 2);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=flicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flicker.js","sourceRoot":"","sources":["../../src/tan/flicker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** An image challenge (photoTAN, QR-TAN) with its MIME type. */
|
|
2
|
+
export declare class TanImage {
|
|
3
|
+
/** The media type of `bytes`, for example `image/png`. */
|
|
4
|
+
readonly mimeType: string;
|
|
5
|
+
/** The encoded image. */
|
|
6
|
+
readonly bytes: Uint8Array;
|
|
7
|
+
constructor(
|
|
8
|
+
/** The media type of `bytes`, for example `image/png`. */
|
|
9
|
+
mimeType: string,
|
|
10
|
+
/** The encoded image. */
|
|
11
|
+
bytes: Uint8Array);
|
|
12
|
+
/**
|
|
13
|
+
* Reads the bank's image container: a two-byte length and the MIME type, then a two-byte length and the image.
|
|
14
|
+
*
|
|
15
|
+
* `undefined` unless the MIME type, in any case, is that of a PNG, JPEG, GIF, WebP or BMP image, and the container
|
|
16
|
+
* holds the whole image.
|
|
17
|
+
*/
|
|
18
|
+
static tryParse(data: Uint8Array): TanImage | undefined;
|
|
19
|
+
/** The image as a `data:` URL, for the `src` of an `<img>` only: the bytes are the bank's, whatever their type says. */
|
|
20
|
+
toDataUrl(): string;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=tan-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tan-image.d.ts","sourceRoot":"","sources":["../../src/tan/tan-image.ts"],"names":[],"mappings":"AAKA,gEAAgE;AAChE,qBAAa,QAAQ;IAEjB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,yBAAyB;IACzB,QAAQ,CAAC,KAAK,EAAE,UAAU;;IAH1B,0DAA0D;IACjD,QAAQ,EAAE,MAAM;IACzB,yBAAyB;IAChB,KAAK,EAAE,UAAU;IAG5B;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS;IAavD,wHAAwH;IACxH,SAAS,IAAI,MAAM;CAGpB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { base64Encode, latin1Decode } from '../util/bytes.js';
|
|
2
|
+
/** The formats of photoTAN and QR-TAN images: raster images, which unlike SVG cannot carry scripts. */
|
|
3
|
+
const imageMimeTypes = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/bmp']);
|
|
4
|
+
/** An image challenge (photoTAN, QR-TAN) with its MIME type. */
|
|
5
|
+
export class TanImage {
|
|
6
|
+
mimeType;
|
|
7
|
+
bytes;
|
|
8
|
+
constructor(
|
|
9
|
+
/** The media type of `bytes`, for example `image/png`. */
|
|
10
|
+
mimeType,
|
|
11
|
+
/** The encoded image. */
|
|
12
|
+
bytes) {
|
|
13
|
+
this.mimeType = mimeType;
|
|
14
|
+
this.bytes = bytes;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Reads the bank's image container: a two-byte length and the MIME type, then a two-byte length and the image.
|
|
18
|
+
*
|
|
19
|
+
* `undefined` unless the MIME type, in any case, is that of a PNG, JPEG, GIF, WebP or BMP image, and the container
|
|
20
|
+
* holds the whole image.
|
|
21
|
+
*/
|
|
22
|
+
static tryParse(data) {
|
|
23
|
+
if (data.length < 4)
|
|
24
|
+
return undefined;
|
|
25
|
+
const mimeLength = (data[0] << 8) | data[1];
|
|
26
|
+
if (mimeLength === 0 || data.length < 2 + mimeLength + 2)
|
|
27
|
+
return undefined;
|
|
28
|
+
const mime = latin1Decode(data.subarray(2, 2 + mimeLength)).toLowerCase();
|
|
29
|
+
if (!imageMimeTypes.has(mime))
|
|
30
|
+
return undefined;
|
|
31
|
+
const offset = 2 + mimeLength;
|
|
32
|
+
const imageLength = (data[offset] << 8) | data[offset + 1];
|
|
33
|
+
const start = offset + 2;
|
|
34
|
+
if (start + imageLength > data.length)
|
|
35
|
+
return undefined;
|
|
36
|
+
return new TanImage(mime, data.subarray(start, start + imageLength));
|
|
37
|
+
}
|
|
38
|
+
/** The image as a `data:` URL, for the `src` of an `<img>` only: the bytes are the bank's, whatever their type says. */
|
|
39
|
+
toDataUrl() {
|
|
40
|
+
return `data:${this.mimeType};base64,${base64Encode(this.bytes)}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=tan-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tan-image.js","sourceRoot":"","sources":["../../src/tan/tan-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE9D,uGAAuG;AACvG,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;AAEpG,gEAAgE;AAChE,MAAM,OAAO,QAAQ;IAGR;IAEA;IAJX;IACE,0DAA0D;IACjD,QAAgB;IACzB,yBAAyB;IAChB,KAAiB;QAFjB,aAAQ,GAAR,QAAQ,CAAQ;QAEhB,UAAK,GAAL,KAAK,CAAY;IACzB,CAAC;IAEJ;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAgB;QAC9B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QACtC,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QAC9C,IAAI,UAAU,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC3E,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1E,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAChD,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC;QAC9B,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,MAAM,CAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,GAAG,WAAW,GAAG,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QACxD,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,wHAAwH;IACxH,SAAS;QACP,OAAO,QAAQ,IAAI,CAAC,QAAQ,WAAW,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;IACpE,CAAC;CACF"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/** Whether a TAN method needs the name of a TAN medium. */
|
|
2
|
+
export type TanMediumRequirement =
|
|
3
|
+
/** The method takes no medium name. */
|
|
4
|
+
'notAllowed'
|
|
5
|
+
/** The method takes a medium name but works without one. */
|
|
6
|
+
| 'optional'
|
|
7
|
+
/** The method needs the name of the medium. */
|
|
8
|
+
| 'required';
|
|
9
|
+
/** Reads the FinTS code: `0` not allowed, `1` optional, `2` required. */
|
|
10
|
+
export declare function tanMediumRequirementOf(code: string | undefined): TanMediumRequirement;
|
|
11
|
+
/** What `TanMethod` takes; the bank states the details it knows. */
|
|
12
|
+
export interface TanMethodInit {
|
|
13
|
+
securityFunction: string;
|
|
14
|
+
name: string;
|
|
15
|
+
technicalId?: string | undefined;
|
|
16
|
+
dkMethod?: string | undefined;
|
|
17
|
+
dkVersion?: string | undefined;
|
|
18
|
+
maxTanLength?: number | undefined;
|
|
19
|
+
numericTan?: boolean;
|
|
20
|
+
returnValueText?: string | undefined;
|
|
21
|
+
maxChallengeLength?: number | undefined;
|
|
22
|
+
mediumRequirement?: TanMediumRequirement;
|
|
23
|
+
activeMediaCount?: number | undefined;
|
|
24
|
+
structuredChallenge?: boolean;
|
|
25
|
+
decoupled?: boolean;
|
|
26
|
+
decoupledMaxPolls?: number | undefined;
|
|
27
|
+
decoupledFirstPollDelaySeconds?: number | undefined;
|
|
28
|
+
decoupledPollIntervalSeconds?: number | undefined;
|
|
29
|
+
decoupledManualConfirmation?: boolean;
|
|
30
|
+
decoupledAutomaticPolling?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** A TAN procedure offered by the bank (FinTS "Sicherheitsfunktion"). */
|
|
33
|
+
export declare class TanMethod {
|
|
34
|
+
/** Bank-specific code of the procedure, for example `942`; `999` is the one-step procedure. */
|
|
35
|
+
readonly securityFunction: string;
|
|
36
|
+
/** The name the bank gives the procedure, for example `pushTAN`. */
|
|
37
|
+
readonly name: string;
|
|
38
|
+
/** The bank's technical identification of the procedure. */
|
|
39
|
+
readonly technicalId: string | undefined;
|
|
40
|
+
/** DK procedure family such as `HHD1.4`, `mobileTAN` or `Decoupled`. */
|
|
41
|
+
readonly dkMethod: string | undefined;
|
|
42
|
+
/** Version of the `dkMethod`. */
|
|
43
|
+
readonly dkVersion: string | undefined;
|
|
44
|
+
/** Longest TAN the user may enter. */
|
|
45
|
+
readonly maxTanLength: number | undefined;
|
|
46
|
+
/** Whether the TAN consists of digits only. */
|
|
47
|
+
readonly numericTan: boolean;
|
|
48
|
+
/** The bank's label for the value the user sends back, for example `TAN`. */
|
|
49
|
+
readonly returnValueText: string | undefined;
|
|
50
|
+
/** Longest challenge text the bank sends for this procedure. */
|
|
51
|
+
readonly maxChallengeLength: number | undefined;
|
|
52
|
+
/** Whether a TAN medium name goes with this procedure. */
|
|
53
|
+
readonly mediumRequirement: TanMediumRequirement;
|
|
54
|
+
/**
|
|
55
|
+
* Most TAN media a user can have active at once for this procedure, as the bank's parameters state it ("Anzahl
|
|
56
|
+
* unterstützter aktiver TAN-Medien"); not how many the user has.
|
|
57
|
+
*
|
|
58
|
+
* Where it is above 1 and `needsMediumName`, each message names the medium, since the user may have several.
|
|
59
|
+
*/
|
|
60
|
+
readonly activeMediaCount: number | undefined;
|
|
61
|
+
/** Whether the challenge text is structured (marked up) rather than plain. */
|
|
62
|
+
readonly structuredChallenge: boolean;
|
|
63
|
+
/** Whether approval happens in a separate app instead of entering a TAN. */
|
|
64
|
+
readonly decoupled: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Most status requests the bank allows for a decoupled approval, 0 for any number. The client sends 60 where the bank
|
|
67
|
+
* states none, and polls for 10 minutes at most.
|
|
68
|
+
*/
|
|
69
|
+
readonly decoupledMaxPolls: number | undefined;
|
|
70
|
+
/** How long to wait before the first status request of a decoupled approval, in seconds. */
|
|
71
|
+
readonly decoupledFirstPollDelaySeconds: number | undefined;
|
|
72
|
+
/** How long to wait between two status requests of a decoupled approval, in seconds. */
|
|
73
|
+
readonly decoupledPollIntervalSeconds: number | undefined;
|
|
74
|
+
/** Whether the user may report the approval, rather than the client asking the bank by itself. */
|
|
75
|
+
readonly decoupledManualConfirmation: boolean;
|
|
76
|
+
/** Whether the bank allows the client to ask for the approval by itself. */
|
|
77
|
+
readonly decoupledAutomaticPolling: boolean;
|
|
78
|
+
constructor(init: TanMethodInit);
|
|
79
|
+
/** The one-step procedure (PIN only, no TAN). */
|
|
80
|
+
static readonly oneStep: TanMethod;
|
|
81
|
+
/** Whether this is the one-step procedure. */
|
|
82
|
+
get isOneStep(): boolean;
|
|
83
|
+
/** Whether the bank needs the name of a TAN medium for this procedure. */
|
|
84
|
+
get needsMediumName(): boolean;
|
|
85
|
+
toString(): string;
|
|
86
|
+
}
|
|
87
|
+
/** State of a TAN medium as reported by the bank. */
|
|
88
|
+
export type TanMediumStatus =
|
|
89
|
+
/** The medium is in use. */
|
|
90
|
+
'active'
|
|
91
|
+
/** The medium can be used but is not the active one. */
|
|
92
|
+
| 'available'
|
|
93
|
+
/** The medium is the active follow-up card. */
|
|
94
|
+
| 'activeFollowUpCard'
|
|
95
|
+
/** The medium is an available follow-up card. */
|
|
96
|
+
| 'availableFollowUpCard'
|
|
97
|
+
/** The bank states no status, or one that is not known. */
|
|
98
|
+
| 'unknown';
|
|
99
|
+
/** Reads the FinTS code `1` to `4`. */
|
|
100
|
+
export declare function tanMediumStatusOf(code: string | undefined): TanMediumStatus;
|
|
101
|
+
/** What `TanMedium` takes; the bank states the details it knows. */
|
|
102
|
+
export interface TanMediumInit {
|
|
103
|
+
mediumClass: string;
|
|
104
|
+
status: TanMediumStatus;
|
|
105
|
+
name?: string | undefined;
|
|
106
|
+
securityFunction?: string | undefined;
|
|
107
|
+
cardNumber?: string | undefined;
|
|
108
|
+
cardSequenceNumber?: string | undefined;
|
|
109
|
+
mobileNumber?: string | undefined;
|
|
110
|
+
mobileNumberMasked?: string | undefined;
|
|
111
|
+
validFrom?: Date | undefined;
|
|
112
|
+
validUntil?: Date | undefined;
|
|
113
|
+
lastUsed?: Date | undefined;
|
|
114
|
+
activatedOn?: Date | undefined;
|
|
115
|
+
}
|
|
116
|
+
/** A TAN device registered for the user, such as a phone or TAN generator. */
|
|
117
|
+
export declare class TanMedium {
|
|
118
|
+
/** `G` TAN generator, `M` mobile phone, `L` TAN list, `S` secoder, `B` bilateral. */
|
|
119
|
+
readonly mediumClass: string;
|
|
120
|
+
/** Whether the medium is in use. */
|
|
121
|
+
readonly status: TanMediumStatus;
|
|
122
|
+
/** The name the medium is registered under; this is what the bank wants back to pick the medium. */
|
|
123
|
+
readonly name: string | undefined;
|
|
124
|
+
/** The TAN procedure the medium belongs to (HITAB version 5). */
|
|
125
|
+
readonly securityFunction: string | undefined;
|
|
126
|
+
/** Card number of a TAN generator. */
|
|
127
|
+
readonly cardNumber: string | undefined;
|
|
128
|
+
/** Sequence number of the card of a TAN generator. */
|
|
129
|
+
readonly cardSequenceNumber: string | undefined;
|
|
130
|
+
/** Phone number of a mobile phone medium, if the bank states it in full. */
|
|
131
|
+
readonly mobileNumber: string | undefined;
|
|
132
|
+
/** Phone number with the middle digits hidden. */
|
|
133
|
+
readonly mobileNumberMasked: string | undefined;
|
|
134
|
+
/** The medium is valid from this date. */
|
|
135
|
+
readonly validFrom: Date | undefined;
|
|
136
|
+
/** The medium is valid until this date. */
|
|
137
|
+
readonly validUntil: Date | undefined;
|
|
138
|
+
/** When the medium was used last. */
|
|
139
|
+
readonly lastUsed: Date | undefined;
|
|
140
|
+
/** When the medium was activated. */
|
|
141
|
+
readonly activatedOn: Date | undefined;
|
|
142
|
+
/** Takes copies of the dates of `init`: each medium has its own, which no other one shares. */
|
|
143
|
+
constructor(init: TanMediumInit);
|
|
144
|
+
/** Whether the medium is the one in use. */
|
|
145
|
+
get isActive(): boolean;
|
|
146
|
+
/** The name, or the last digits of the card number, so that logs and crash reports do not collect the number. */
|
|
147
|
+
toString(): string;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=tan-models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tan-models.d.ts","sourceRoot":"","sources":["../../src/tan/tan-models.ts"],"names":[],"mappings":"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"}
|