KDE PIM/KItinerary/MAV Barcode: Difference between revisions
< KDE PIM | KItinerary
Line 39: | Line 39: | ||
| 0 || 17 || string || ticket number || printed as "CIV" in the PDF | | 0 || 17 || string || ticket number || printed as "CIV" in the PDF | ||
|- | |- | ||
| 17 || 1 || null || ? || | | 17 || 1 || null || ? || null in all samples | ||
|- | |- | ||
| 18 || 2 || uint16 || UIC company code || issuer?, 0x0483 (1155) for MAV | | 18 || 2 || uint16 || UIC company code || issuer?, 0x0483 (1155) for MAV | ||
Line 45: | Line 45: | ||
| 20 || 4 || time || issuing time || | | 20 || 4 || time || issuing time || | ||
|- | |- | ||
| 24 || 1 || ? || ticket type?? || 'C' for bike addon tickets, 'D' for regular tickets (with or without seat reservation, 'E' for tickets with | | 24 || 1 || ? || ticket type?? || 'C' for bike addon tickets, 'B' or 'D' for regular tickets (with or without seat reservation, 'E' for tickets with surcharge (and with or without seat reservation), null for "connecting ticket to season ticket" | ||
|- | |- | ||
| 25 || | | 25 || 2 || ? || ? || | ||
|- | |- | ||
| | | 27 || 1 || null || ? || null in all samples | ||
|- | |- | ||
| | | 28 || 1 || ? || ticket type?? || 0x01 for bike addon block, 0x81 for passenger block | ||
|- | |- | ||
| 30 || 1 || uint8 || number of | | 29 || 1 || null || ? || null in all samples | ||
|- | |||
| 30 || 1 || uint8 || number of reservation/surcharge blocks || | |||
|- | |- | ||
| 31 || 4 || null || ? || null in all samples | | 31 || 4 || null || ? || null in all samples | ||
Line 85: | Line 87: | ||
* 57 bytes long. | * 57 bytes long. | ||
* Also used for | * Also used for surcharge ("Pótjegy") blocks, in which case the fields for coach and seat numbers are all null. | ||
* Order of | * Order of surcharge and reservation blocks seems undefined if both are present. | ||
{| class="wikitable" | {| class="wikitable" |
Revision as of 15:25, 24 August 2021
Current Version (>= 2020?)
General Observation
- Uses PDF417 barcode format, same content on PDF and in the official app.
- Variable length.
- For domestic tickets only.
- No similarities with a known ERA format.
Outer Structure
- Two byte header, fixed 0x0403.
- Gzip-compressed payload using deflate compression, starting with the standard Gzip header 0x1f8b0800000000000000.
- 256 remaining bytes, high entropy and length suggest a cryptographic signature.
Payload Structure
Note: this is based on very few samples so far and thus isn't very reliable yet!
- Seems byte- rather than bit-aligned.
- String encoding is UTF-8.
- Number encoding seems big endian.
- Content has a high amount of null bytes.
- Date/time values are encoded as seconds since Jan 1st 2017. Times are local but do not account for DST. (Exception: traveler birth date).
- At least three observed variants, so maybe some kind of (fixed-length?) block structure (
but no signs of TLVbyte 24/25/(26) might suggest some kind of TLV?):- 217 bytes, personalized train ticket without seat reservation
- 274 bytes, personalized train ticket with seat reservation
- 153 bytes, bike addon ticket
- 331 bytes, personailed train ticket with seat reservation and "Pótjegy"
- seems to correlate to the type of light blue boxes on the PDF, but so far it's unclear how to determine which blocks are present
Header/Ticket Block
(for the 217 or 274 byte variants)
Offset | Size | Data Type | Meaning | Notes |
---|---|---|---|---|
0 | 17 | string | ticket number | printed as "CIV" in the PDF |
17 | 1 | null | ? | null in all samples |
18 | 2 | uint16 | UIC company code | issuer?, 0x0483 (1155) for MAV |
20 | 4 | time | issuing time | |
24 | 1 | ? | ticket type?? | 'C' for bike addon tickets, 'B' or 'D' for regular tickets (with or without seat reservation, 'E' for tickets with surcharge (and with or without seat reservation), null for "connecting ticket to season ticket" |
25 | 2 | ? | ? | |
27 | 1 | null | ? | null in all samples |
28 | 1 | ? | ticket type?? | 0x01 for bike addon block, 0x81 for passenger block |
29 | 1 | null | ? | null in all samples |
30 | 1 | uint8 | number of reservation/surcharge blocks | |
31 | 4 | null | ? | null in all samples |
35 | 4 | ? | ? | |
39 | 45 | string | passenger name | null terminated |
84 | 4 | uint32 | passenger birth date | year * 10000 + month * 100 + day |
88 | 15 | null | ? | null in all samples |
103 | 4 | ? | ? | |
107 | 3 | uint24 | UIC departure station code | including the national prefix ('55' for HU) |
110 | 3 | uint24 | UIC arrival station code | |
113 | 90 | null | ? | null in all samples |
203 | 1 | text | class | "1" or "2" |
204 | 1 | ? | ? | 0x01 in all samples |
205 | 4 | time | time of validity/travel | |
209 | 8 | ? | ? |
Seat Reservation Block
- 57 bytes long.
- Also used for surcharge ("Pótjegy") blocks, in which case the fields for coach and seat numbers are all null.
- Order of surcharge and reservation blocks seems undefined if both are present.
Offset | Size | Data Type | Meaning | Notes |
---|---|---|---|---|
0 | 3 | uint24 | UIC departure station code | |
3 | 3 | uint24 | UIC arrival station code | |
6 | 4 | ? | ? | |
10 | 4 | time | time of validity/travel | |
14 | 2 | uint16 | UIC company code | operator?, 0x0483 (1155) for MAV |
16 | 5 | string | train number | null-terminated |
21 | 1 | ? | ? | 0x01 in all samples |
22 | 3 | string | coach number | null terminated |
25 | 2 | uint16 | seat number | |
27 | 2 | uint16 | seat number | repeated from byte 25/26? |
29 | 28 | null | ? | null bytes in all samples |
Missing/Suspected Information
Station names are not included, but station codes might be. UIC station numbers (possibly without the country prefix) would be the obvious suspect, given the MÁV website uses those as well.If the train number is included, one would expect at least the day of travel to be included as well.Class: several candidate locations exist, but given it's small footprint we need a lot more samples to confirm one of those.
Old Format (<2020?)
General Structure
- QR code containing a hex string
- content of the hex string is zlib-compressed, no header bytes
- result of decompression is a UTF-8 encoded string
- the first 512 bytes appear to be a hex string again, length and entropy suggest a cryptographic signature
- the second part looks like a '!' delimited list
Content
Index | Format | Meaning | Notes |
---|---|---|---|
0 | ~<number> | ticket number | printed as "CIV" in the PDF |
1 | passenger name | ||
2 | yyyy.MM.dd | passenger birth date | |
3 | total price | in HUF | |
4 | ? | ? | "P05" |
5 | yyyy.MM.dd hh:mm | begin of validity | |
6 | yyyy.MM.dd hh:mm~v | end of validity | no idea what the literal '~v' means there |
7 | MÁV <number> | travel distance | |
8 | '-' separated string | vias | |
9 | departure station name | ||
10 | arrival station name | ||
11 | empty? | ||
12 | empty? | ||
13 | empty? | ||
14 | empty? | ||
15 | train number | number only, not product/category prefix | |
16 | class | ||
17 | yyyy.MM.dd~m | day of travel? | |
18 | string | discount_type | e.g. "Teljesárú" (full price) |
19 | <number>~h | ticket price | in HUF |
20 | departure station name | possibly for the seat reservation | |
21 | arrival station name | possibly for the seat reservation | |
22 | yyyy.DD.mm | day of travel? | |
23 | hh:mm | time of departure | |
24 | empty? | ||
25 | empty? | ||
26 | train number | incl. product/category prefix | |
27 | coach number | ||
28 | seat number | ||
29 | number | price of reservation | in HUF |
30 | extension-ticket | "Helyjegy", "Pót- és helyjegy" | |
31 | MÁV <number> | ? | same as entry 7, not always present |