dosipas-ts 1.0.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/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/decoder.d.ts +16 -0
- package/dist/decoder.d.ts.map +1 -0
- package/dist/decoder.js +265 -0
- package/dist/decoder.js.map +1 -0
- package/dist/encoder.d.ts +16 -0
- package/dist/encoder.d.ts.map +1 -0
- package/dist/encoder.js +171 -0
- package/dist/encoder.js.map +1 -0
- package/dist/fixtures.d.ts +14 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +68 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/oids.d.ts +28 -0
- package/dist/oids.d.ts.map +1 -0
- package/dist/oids.js +43 -0
- package/dist/oids.js.map +1 -0
- package/dist/schemas.d.ts +11 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +17 -0
- package/dist/schemas.js.map +1 -0
- package/dist/signature-fixtures.d.ts +110 -0
- package/dist/signature-fixtures.d.ts.map +1 -0
- package/dist/signature-fixtures.js +142 -0
- package/dist/signature-fixtures.js.map +1 -0
- package/dist/signature-utils.d.ts +29 -0
- package/dist/signature-utils.d.ts.map +1 -0
- package/dist/signature-utils.js +201 -0
- package/dist/signature-utils.js.map +1 -0
- package/dist/signed-data.d.ts +32 -0
- package/dist/signed-data.d.ts.map +1 -0
- package/dist/signed-data.js +87 -0
- package/dist/signed-data.js.map +1 -0
- package/dist/types.d.ts +273 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/verifier.d.ts +67 -0
- package/dist/verifier.d.ts.map +1 -0
- package/dist/verifier.js +309 -0
- package/dist/verifier.js.map +1 -0
- package/package.json +46 -0
- package/schemas/uic-barcode/intercode6.schema.json +204 -0
- package/schemas/uic-barcode/uicBarcodeHeader_v1.schema.json +376 -0
- package/schemas/uic-barcode/uicBarcodeHeader_v2.schema.json +484 -0
- package/schemas/uic-barcode/uicRailTicketData_v1.schema.json +31507 -0
- package/schemas/uic-barcode/uicRailTicketData_v2.schema.json +31623 -0
- package/schemas/uic-barcode/uicRailTicketData_v3.schema.json +32729 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Théophile Helleboid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# dosipas-ts
|
|
2
|
+
|
|
3
|
+
Decode, encode, and verify UIC barcode tickets with Intercode 6 extensions in TypeScript.
|
|
4
|
+
|
|
5
|
+
Handles the full UIC barcode envelope (header versions 1 and 2), FCB rail ticket data (versions 1, 2, and 3), Intercode 6 issuing extensions, dynamic data, and two-level ECDSA signature verification.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install dosipas-ts
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires Node.js 18+. ESM-only.
|
|
14
|
+
|
|
15
|
+
## Decoding
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { decodeTicket, decodeTicketFromBytes } from 'dosipas-ts';
|
|
19
|
+
|
|
20
|
+
// From a hex string (whitespace and trailing 'h' are stripped)
|
|
21
|
+
const ticket = decodeTicket('815563dd8e76...');
|
|
22
|
+
|
|
23
|
+
// From raw bytes
|
|
24
|
+
const ticket = decodeTicketFromBytes(bytes);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The returned `UicBarcodeTicket` object contains:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
ticket.format // "U1" or "U2"
|
|
31
|
+
ticket.headerVersion // 1 or 2
|
|
32
|
+
ticket.security // SecurityInfo (provider, key IDs, algorithms, signatures)
|
|
33
|
+
ticket.railTickets // RailTicketData[] (FCB-decoded ticket data)
|
|
34
|
+
ticket.otherDataBlocks // DataBlock[] (non-FCB data blocks)
|
|
35
|
+
ticket.dynamicData // IntercodeDynamicData (Intercode 6 Level 2, if present)
|
|
36
|
+
ticket.level2Signature // Uint8Array (if present)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Each rail ticket includes typed fields for issuing details, traveler info, transport documents, and control details:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const rt = ticket.railTickets[0];
|
|
43
|
+
|
|
44
|
+
rt.fcbVersion // 1, 2, or 3
|
|
45
|
+
rt.issuingDetail?.issuerNum // RICS code
|
|
46
|
+
rt.issuingDetail?.issuingYear // e.g. 2025
|
|
47
|
+
rt.issuingDetail?.issuingDay // day of year
|
|
48
|
+
rt.issuingDetail?.intercodeIssuing // Intercode 6 issuing extension
|
|
49
|
+
rt.travelerDetail?.traveler?.[0].firstName // traveler name
|
|
50
|
+
rt.transportDocument?.[0].ticketType // e.g. "openTicket", "reservation"
|
|
51
|
+
rt.raw // full decoded object for fields not covered above
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Encoding
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { encodeTicket, encodeTicketToBytes } from 'dosipas-ts';
|
|
58
|
+
|
|
59
|
+
const hex = encodeTicket({
|
|
60
|
+
headerVersion: 2,
|
|
61
|
+
fcbVersion: 2,
|
|
62
|
+
securityProviderNum: 3703,
|
|
63
|
+
keyId: 1,
|
|
64
|
+
level1KeyAlg: '1.2.840.10045.3.1.7',
|
|
65
|
+
level2KeyAlg: '1.2.840.10045.3.1.7',
|
|
66
|
+
level1SigningAlg: '1.2.840.10045.4.3.2',
|
|
67
|
+
level2SigningAlg: '1.2.840.10045.4.3.2',
|
|
68
|
+
level2PublicKey: publicKeyBytes,
|
|
69
|
+
level1Signature: level1SigBytes,
|
|
70
|
+
level2Signature: level2SigBytes,
|
|
71
|
+
railTicket: {
|
|
72
|
+
issuingDetail: {
|
|
73
|
+
securityProviderNum: 3703,
|
|
74
|
+
issuerNum: 3703,
|
|
75
|
+
issuingYear: 2025,
|
|
76
|
+
issuingDay: 44,
|
|
77
|
+
activated: true,
|
|
78
|
+
currency: 'EUR',
|
|
79
|
+
currencyFract: 2,
|
|
80
|
+
intercodeIssuing: {
|
|
81
|
+
networkId: new Uint8Array([0x11, 0x87]),
|
|
82
|
+
productRetailer: { retailChannel: 'mobileApplication' },
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
transportDocument: [
|
|
86
|
+
{ ticketType: 'openTicket', ticket: { /* ... */ } },
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
dynamicData: {
|
|
90
|
+
rics: 3703,
|
|
91
|
+
dynamicContentDay: 0,
|
|
92
|
+
dynamicContentTime: 720,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Or get bytes directly
|
|
97
|
+
const bytes = encodeTicketToBytes({ /* same input */ });
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Signature verification
|
|
101
|
+
|
|
102
|
+
UIC barcodes use a two-level signature scheme:
|
|
103
|
+
|
|
104
|
+
- **Level 2** is self-contained: the public key is embedded in the barcode.
|
|
105
|
+
- **Level 1** requires an external public key from the UIC public key registry.
|
|
106
|
+
|
|
107
|
+
### Verify Level 2 only (no external key needed)
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { verifyLevel2Signature } from 'dosipas-ts';
|
|
111
|
+
|
|
112
|
+
const result = await verifyLevel2Signature(barcodeBytes);
|
|
113
|
+
// { valid: true, algorithm: 'ECDSA P-256 with SHA-256' }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Verify both levels
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { verifySignatures } from 'dosipas-ts';
|
|
120
|
+
|
|
121
|
+
const result = await verifySignatures(barcodeBytes, {
|
|
122
|
+
level1PublicKey: publicKeyBytes,
|
|
123
|
+
});
|
|
124
|
+
// { level1: { valid: true, ... }, level2: { valid: true, ... } }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Using a key provider
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import { verifySignatures, findKeyInXml } from 'dosipas-ts';
|
|
131
|
+
import type { Level1KeyProvider } from 'dosipas-ts';
|
|
132
|
+
|
|
133
|
+
// Parse the UIC public key XML (from https://railpublickey.uic.org)
|
|
134
|
+
const xml = fs.readFileSync('uic-publickeys.xml', 'utf-8');
|
|
135
|
+
|
|
136
|
+
const provider: Level1KeyProvider = {
|
|
137
|
+
async getPublicKey(securityProvider, keyId) {
|
|
138
|
+
const key = findKeyInXml(xml, securityProvider.num!, keyId);
|
|
139
|
+
if (!key) throw new Error('Key not found');
|
|
140
|
+
return key;
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const result = await verifySignatures(barcodeBytes, {
|
|
145
|
+
level1KeyProvider: provider,
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Verify Level 1 directly
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { verifyLevel1Signature } from 'dosipas-ts';
|
|
153
|
+
|
|
154
|
+
const result = await verifyLevel1Signature(barcodeBytes, publicKeyBytes);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Extracting signed data
|
|
158
|
+
|
|
159
|
+
For custom verification workflows, extract the exact signed bytes from a barcode:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { extractSignedData } from 'dosipas-ts';
|
|
163
|
+
|
|
164
|
+
const extracted = extractSignedData(barcodeBytes);
|
|
165
|
+
|
|
166
|
+
extracted.level1DataBytes // bytes signed by level1Signature
|
|
167
|
+
extracted.level2SignedBytes // bytes signed by level2Signature
|
|
168
|
+
extracted.security // security metadata (algorithms, keys, signatures)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## UIC public key XML utilities
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { findKeyInXml, parseKeysXml } from 'dosipas-ts';
|
|
175
|
+
|
|
176
|
+
// Find a specific key
|
|
177
|
+
const key = findKeyInXml(xml, 1187, 1); // issuerCode, keyId
|
|
178
|
+
// Returns Uint8Array or null
|
|
179
|
+
|
|
180
|
+
// Parse all keys
|
|
181
|
+
const keys = parseKeysXml(xml);
|
|
182
|
+
// [{ issuerCode, id, issuerName, publicKey, signatureAlgorithm, ... }]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Built-in fixtures
|
|
186
|
+
|
|
187
|
+
The package exports hex-encoded sample tickets for testing:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import {
|
|
191
|
+
SAMPLE_TICKET_HEX,
|
|
192
|
+
SNCF_TER_TICKET_HEX,
|
|
193
|
+
SOLEA_TICKET_HEX,
|
|
194
|
+
CTS_TICKET_HEX,
|
|
195
|
+
GRAND_EST_U1_FCB3_HEX,
|
|
196
|
+
} from 'dosipas-ts';
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
And signature fixture data:
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { SNCF_TER_SIGNATURES, SOLEA_SIGNATURES, CTS_SIGNATURES } from 'dosipas-ts';
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Supported algorithms
|
|
206
|
+
|
|
207
|
+
| Algorithm | Signing | Key verification |
|
|
208
|
+
|-----------|---------|-----------------|
|
|
209
|
+
| ECDSA P-256 with SHA-256 | Yes | Yes |
|
|
210
|
+
| ECDSA P-384 with SHA-384 | Yes | Yes |
|
|
211
|
+
| ECDSA P-521 with SHA-512 | Yes | Yes |
|
|
212
|
+
| DSA with SHA-224/256 | Detected | Not supported |
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { UicBarcodeTicket } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Decode a UIC barcode ticket from a hex string.
|
|
4
|
+
*
|
|
5
|
+
* @param hex - The hex-encoded barcode payload (whitespace and trailing 'h' are stripped).
|
|
6
|
+
* @returns A fully typed {@link UicBarcodeTicket} object.
|
|
7
|
+
*/
|
|
8
|
+
export declare function decodeTicket(hex: string): UicBarcodeTicket;
|
|
9
|
+
/**
|
|
10
|
+
* Decode a UIC barcode ticket from raw bytes.
|
|
11
|
+
*
|
|
12
|
+
* @param bytes - The binary barcode payload.
|
|
13
|
+
* @returns A fully typed {@link UicBarcodeTicket} object.
|
|
14
|
+
*/
|
|
15
|
+
export declare function decodeTicketFromBytes(bytes: Uint8Array): UicBarcodeTicket;
|
|
16
|
+
//# sourceMappingURL=decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../src/decoder.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,gBAAgB,EAWjB,MAAM,SAAS,CAAC;AAsFjB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAG1D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,gBAAgB,CAkFzE"}
|
package/dist/decoder.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decoder for UIC barcode tickets with Intercode 6 extensions.
|
|
3
|
+
*
|
|
4
|
+
* Decodes a hex-encoded (or binary) UIC barcode payload into a typed
|
|
5
|
+
* {@link UicBarcodeTicket} object. Handles header version detection,
|
|
6
|
+
* FCB rail ticket data dispatch, and Intercode 6 extension decoding.
|
|
7
|
+
*/
|
|
8
|
+
import { SchemaCodec, SchemaBuilder, BitBuffer, } from 'asn1-per-ts';
|
|
9
|
+
import { HEADER_SCHEMAS, RAIL_TICKET_SCHEMAS, INTERCODE_SCHEMAS } from './schemas';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Codec caches
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
const headerCodecCache = new Map();
|
|
14
|
+
const ticketCodecCache = new Map();
|
|
15
|
+
let intercodeIssuingCodec;
|
|
16
|
+
let intercodeDynamicCodec;
|
|
17
|
+
function getHeaderCodec(version) {
|
|
18
|
+
let codec = headerCodecCache.get(version);
|
|
19
|
+
if (codec)
|
|
20
|
+
return codec;
|
|
21
|
+
const schemas = HEADER_SCHEMAS[version];
|
|
22
|
+
if (!schemas) {
|
|
23
|
+
throw new Error(`No schema for header v${version}. Supported: v1, v2`);
|
|
24
|
+
}
|
|
25
|
+
codec = new SchemaCodec(schemas.UicBarcodeHeader);
|
|
26
|
+
headerCodecCache.set(version, codec);
|
|
27
|
+
return codec;
|
|
28
|
+
}
|
|
29
|
+
function getTicketCodecs(version) {
|
|
30
|
+
let codecs = ticketCodecCache.get(version);
|
|
31
|
+
if (codecs)
|
|
32
|
+
return codecs;
|
|
33
|
+
const schemas = RAIL_TICKET_SCHEMAS[version];
|
|
34
|
+
if (!schemas) {
|
|
35
|
+
throw new Error(`No schema for FCB${version}. Supported: FCB1, FCB2, FCB3`);
|
|
36
|
+
}
|
|
37
|
+
codecs = SchemaBuilder.buildAll(schemas);
|
|
38
|
+
ticketCodecCache.set(version, codecs);
|
|
39
|
+
return codecs;
|
|
40
|
+
}
|
|
41
|
+
function getIntercodeIssuingCodec() {
|
|
42
|
+
if (intercodeIssuingCodec)
|
|
43
|
+
return intercodeIssuingCodec;
|
|
44
|
+
intercodeIssuingCodec = new SchemaCodec(INTERCODE_SCHEMAS.IntercodeIssuingData);
|
|
45
|
+
intercodeDynamicCodec = new SchemaCodec(INTERCODE_SCHEMAS.IntercodeDynamicData);
|
|
46
|
+
return intercodeIssuingCodec;
|
|
47
|
+
}
|
|
48
|
+
function getIntercodeDynamicCodec() {
|
|
49
|
+
if (intercodeDynamicCodec)
|
|
50
|
+
return intercodeDynamicCodec;
|
|
51
|
+
getIntercodeIssuingCodec();
|
|
52
|
+
return intercodeDynamicCodec;
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Pattern helpers
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Match Intercode Part 6 issuing extension IDs:
|
|
59
|
+
* - `_<RICS>II1` — numeric RICS code prefix (e.g. `_3703II1`)
|
|
60
|
+
* - `+<CC>II1` — ISO 3166-1 alpha-2 country code prefix (e.g. `+FRII1`)
|
|
61
|
+
*/
|
|
62
|
+
function isIntercodeIssuingExtension(extensionId) {
|
|
63
|
+
return /^[_+](\d+|[A-Z]{2})II1$/.test(extensionId);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Match Intercode Part 6 dynamic data formats:
|
|
67
|
+
* - `_<RICS>.ID1` — numeric RICS code prefix (e.g. `_3703.ID1`)
|
|
68
|
+
* - `FDC1` — French dynamic content variant
|
|
69
|
+
*/
|
|
70
|
+
function isIntercodeDynamicData(dataFormat) {
|
|
71
|
+
return /^_\d+\.ID1$/.test(dataFormat) || dataFormat === 'FDC1';
|
|
72
|
+
}
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Hex / bytes helpers
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
function hexToBytes(hex) {
|
|
77
|
+
const clean = hex.replace(/\s+/g, '').replace(/h$/i, '').toLowerCase();
|
|
78
|
+
if (!/^[0-9a-f]*$/.test(clean))
|
|
79
|
+
throw new Error('Invalid hex characters');
|
|
80
|
+
if (clean.length === 0)
|
|
81
|
+
throw new Error('Hex input is empty');
|
|
82
|
+
if (clean.length % 2 !== 0)
|
|
83
|
+
throw new Error('Hex string must have even length');
|
|
84
|
+
return new Uint8Array(clean.match(/.{1,2}/g).map(b => parseInt(b, 16)));
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Public API
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
/**
|
|
90
|
+
* Decode a UIC barcode ticket from a hex string.
|
|
91
|
+
*
|
|
92
|
+
* @param hex - The hex-encoded barcode payload (whitespace and trailing 'h' are stripped).
|
|
93
|
+
* @returns A fully typed {@link UicBarcodeTicket} object.
|
|
94
|
+
*/
|
|
95
|
+
export function decodeTicket(hex) {
|
|
96
|
+
const bytes = hexToBytes(hex);
|
|
97
|
+
return decodeTicketFromBytes(bytes);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Decode a UIC barcode ticket from raw bytes.
|
|
101
|
+
*
|
|
102
|
+
* @param bytes - The binary barcode payload.
|
|
103
|
+
* @returns A fully typed {@link UicBarcodeTicket} object.
|
|
104
|
+
*/
|
|
105
|
+
export function decodeTicketFromBytes(bytes) {
|
|
106
|
+
// Step 1: Peek the header format using low-level BitBuffer
|
|
107
|
+
const peekBuf = BitBuffer.from(bytes);
|
|
108
|
+
peekBuf.readBit(); // skip optional bitmap (level2Signature present/absent)
|
|
109
|
+
const format = SchemaBuilder.build({ type: 'IA5String' }).decode(peekBuf);
|
|
110
|
+
const headerVersionMatch = format.match(/^U(\d+)$/);
|
|
111
|
+
if (!headerVersionMatch) {
|
|
112
|
+
throw new Error(`Unknown header format "${format}"`);
|
|
113
|
+
}
|
|
114
|
+
const headerVersion = parseInt(headerVersionMatch[1], 10);
|
|
115
|
+
// Step 2: Decode the full header with version-specific schema
|
|
116
|
+
const header = getHeaderCodec(headerVersion).decode(bytes);
|
|
117
|
+
const l2 = header.level2SignedData;
|
|
118
|
+
const l1 = l2.level1Data;
|
|
119
|
+
// Step 3: Extract security info
|
|
120
|
+
const security = {
|
|
121
|
+
securityProviderNum: l1.securityProviderNum,
|
|
122
|
+
securityProviderIA5: l1.securityProviderIA5,
|
|
123
|
+
keyId: l1.keyId,
|
|
124
|
+
level1KeyAlg: l1.level1KeyAlg,
|
|
125
|
+
level2KeyAlg: l1.level2KeyAlg,
|
|
126
|
+
level1SigningAlg: l1.level1SigningAlg,
|
|
127
|
+
level2SigningAlg: l1.level2SigningAlg,
|
|
128
|
+
level2PublicKey: l1.level2PublicKey,
|
|
129
|
+
level1Signature: l2.level1Signature,
|
|
130
|
+
endOfValidityYear: l1.endOfValidityYear,
|
|
131
|
+
endOfValidityDay: l1.endOfValidityDay,
|
|
132
|
+
endOfValidityTime: l1.endOfValidityTime,
|
|
133
|
+
validityDuration: l1.validityDuration,
|
|
134
|
+
};
|
|
135
|
+
// Step 4: Decode data blocks
|
|
136
|
+
const railTickets = [];
|
|
137
|
+
const otherDataBlocks = [];
|
|
138
|
+
for (const block of l1.dataSequence) {
|
|
139
|
+
const fcbMatch = block.dataFormat.match(/^FCB(\d+)$/);
|
|
140
|
+
if (fcbMatch) {
|
|
141
|
+
const fcbVersion = parseInt(fcbMatch[1], 10);
|
|
142
|
+
try {
|
|
143
|
+
const codecs = getTicketCodecs(fcbVersion);
|
|
144
|
+
const buf = BitBuffer.from(block.data);
|
|
145
|
+
const raw = codecs.UicRailTicketData.decode(buf);
|
|
146
|
+
railTickets.push(decodeRailTicket(fcbVersion, raw));
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// If FCB decoding fails, add as raw block
|
|
150
|
+
otherDataBlocks.push({ dataFormat: block.dataFormat, data: block.data });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
otherDataBlocks.push({ dataFormat: block.dataFormat, data: block.data });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Step 5: Decode Level 2 dynamic data
|
|
158
|
+
let dynamicData;
|
|
159
|
+
let level2DataBlock;
|
|
160
|
+
if (l2.level2Data) {
|
|
161
|
+
level2DataBlock = { dataFormat: l2.level2Data.dataFormat, data: l2.level2Data.data };
|
|
162
|
+
if (isIntercodeDynamicData(l2.level2Data.dataFormat)) {
|
|
163
|
+
try {
|
|
164
|
+
dynamicData = getIntercodeDynamicCodec().decode(l2.level2Data.data);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// leave as undefined if decoding fails
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
format,
|
|
173
|
+
headerVersion,
|
|
174
|
+
level2Signature: header.level2Signature,
|
|
175
|
+
security,
|
|
176
|
+
railTickets,
|
|
177
|
+
otherDataBlocks,
|
|
178
|
+
dynamicData,
|
|
179
|
+
level2DataBlock,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Rail ticket decoding helpers
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
function decodeRailTicket(fcbVersion, raw) {
|
|
186
|
+
const issuingDetail = raw.issuingDetail ? decodeIssuingDetail(raw.issuingDetail) : undefined;
|
|
187
|
+
const travelerDetail = raw.travelerDetail ? decodeTravelerDetail(raw.travelerDetail) : undefined;
|
|
188
|
+
const transportDocument = raw.transportDocument
|
|
189
|
+
? decodeTransportDocuments(raw.transportDocument)
|
|
190
|
+
: undefined;
|
|
191
|
+
const controlDetail = raw.controlDetail ? raw.controlDetail : undefined;
|
|
192
|
+
return {
|
|
193
|
+
fcbVersion,
|
|
194
|
+
issuingDetail,
|
|
195
|
+
travelerDetail,
|
|
196
|
+
transportDocument,
|
|
197
|
+
controlDetail,
|
|
198
|
+
raw,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function decodeIssuingDetail(iss) {
|
|
202
|
+
const result = {
|
|
203
|
+
securityProviderNum: iss.securityProviderNum,
|
|
204
|
+
securityProviderIA5: iss.securityProviderIA5,
|
|
205
|
+
issuerNum: iss.issuerNum,
|
|
206
|
+
issuerIA5: iss.issuerIA5,
|
|
207
|
+
issuingYear: iss.issuingYear,
|
|
208
|
+
issuingDay: iss.issuingDay,
|
|
209
|
+
issuingTime: iss.issuingTime,
|
|
210
|
+
issuerName: iss.issuerName,
|
|
211
|
+
specimen: iss.specimen ?? false,
|
|
212
|
+
securePaperTicket: iss.securePaperTicket ?? false,
|
|
213
|
+
activated: iss.activated ?? false,
|
|
214
|
+
currency: iss.currency,
|
|
215
|
+
currencyFract: iss.currencyFract,
|
|
216
|
+
issuerPNR: iss.issuerPNR,
|
|
217
|
+
};
|
|
218
|
+
if (iss.extension) {
|
|
219
|
+
const ext = iss.extension;
|
|
220
|
+
if (isIntercodeIssuingExtension(ext.extensionId)) {
|
|
221
|
+
try {
|
|
222
|
+
result.intercodeIssuing = getIntercodeIssuingCodec().decode(ext.extensionData);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
result.extension = { extensionId: ext.extensionId, extensionData: ext.extensionData };
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
result.extension = { extensionId: ext.extensionId, extensionData: ext.extensionData };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
function decodeTravelerDetail(td) {
|
|
235
|
+
return {
|
|
236
|
+
traveler: td.traveler,
|
|
237
|
+
preferredLanguage: td.preferredLanguage,
|
|
238
|
+
groupName: td.groupName,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function decodeTransportDocuments(docs) {
|
|
242
|
+
return docs.map((doc) => {
|
|
243
|
+
const ticket = doc.ticket || {};
|
|
244
|
+
const entries = Object.entries(ticket);
|
|
245
|
+
if (entries.length === 2 && entries[0][0] === 'key' && entries[1][0] === 'value') {
|
|
246
|
+
// CHOICE decoded as { key: "variantName", value: {...} }
|
|
247
|
+
return {
|
|
248
|
+
ticketType: entries[0][1],
|
|
249
|
+
ticket: entries[1][1],
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
// Single-key CHOICE
|
|
253
|
+
if (entries.length === 1) {
|
|
254
|
+
return {
|
|
255
|
+
ticketType: entries[0][0],
|
|
256
|
+
ticket: entries[0][1],
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
ticketType: 'unknown',
|
|
261
|
+
ticket,
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=decoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../src/decoder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { UicBarcodeTicketInput } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Encode a UIC barcode ticket to a hex string.
|
|
4
|
+
*
|
|
5
|
+
* @param input - The ticket data to encode.
|
|
6
|
+
* @returns Hex string of the encoded barcode payload.
|
|
7
|
+
*/
|
|
8
|
+
export declare function encodeTicket(input: UicBarcodeTicketInput): string;
|
|
9
|
+
/**
|
|
10
|
+
* Encode a UIC barcode ticket to bytes.
|
|
11
|
+
*
|
|
12
|
+
* @param input - The ticket data to encode.
|
|
13
|
+
* @returns Uint8Array of the encoded barcode payload.
|
|
14
|
+
*/
|
|
15
|
+
export declare function encodeTicketToBytes(input: UicBarcodeTicketInput): Uint8Array;
|
|
16
|
+
//# sourceMappingURL=encoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../src/encoder.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,qBAAqB,EAKtB,MAAM,SAAS,CAAC;AAoDjB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAkDjE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,UAAU,CAG5E"}
|