I'm working on an online event ticketing system, where users will be able to self print his tickets and show up at the event where it will be scanned (barcode) and ideally the person will get in. My problem is how to create a "ticket code" that fulfills the following requirements:
- each "ticket code" need to be sufficiently different from each other (ie not sequentially numbered)
- ideally the ticket will be checked against a central DB to prevent reuse, but it NEEDS to be able to work off line too, in which case the system has to check for a "valid" ticket code and that it has not been used in this gate.
- the "ticket code" has to be small enough to facilitate keying it if needed
- the ticket holder would only need the ticket to get in (ie no ID check)
The range of the data is very small, there will only be about 20 events over 4 days with about 5,000 tickets per event (about 100,000 different ticket codes)
Now I have several fields that are not printed on the ticket and not known to the user that I can use to encode part of the "ticket code", so I could use the EventId, OrderId, EventDate and some salt to create a small "hash" for part of the code (ideas?), but I'm still stuck with the ticket id that is sequential or a GUID (would be too long)
So any ideas or pointers on how to do this?
Here's a scheme that has the advantage of letting you calculate the next ticket hash from the previous (so you can verify whether one is missing), but doesn't let outsiders calculate the next one:
where
HASH
is any hashing function that distributes its entropy relatively evenly across the output stringSALT
is a constant you keep secret; it's a good idea to use a different one for each eventIV
is another constant you keep secretFor offline verification, I see only one easy solution..
Append to the ticket ID a hash of the ticket ID and a per-event salt. You can truncate any cryptographic hash to the size desired. I can't think of a particular reason to use anything but a random number for the base ticket ID itself.
This allows you to limit the size of the ticket ID and have a clearly proportional security in relation to the size of the ticket ID.
You could do a CRC calculation.
Basically, just start to add each character in the string, and limit the length to a long integer.
You may start with a known random number and store it in the first 4 bytes, and have the last four be a calculation as I described earlier.
This would be two ints, or eight bytes.
Why reinvent the wheel? Just do something like this (Python Code, ask me if you need clarification):
Example:
Event Number 1
Ticket Number 123
Mr ticketman comes around with his verifier and enters in the event/ticket number and the hash:
Two ways I can see:
Consider a very simple scheme based on a Feistel network to permute, say, the ticket ID number. This message (which happens to be on the PostgreSQL lists but doesn't really have much to do with PostgreSQL) describes a simple Feistel network. On each ticket you could print a ticket ID number (sequentially chosen), then a "ticket secret code" that's the result of putting the ID number through a Feistel network. Possible variations include appending a check digit to the secret code, and basing the input to the Feistel network on more than just the sequentially generated number (number + 10,000 * event ID number, et cetera).