5 ms·
The workflow is generally reversed in South Korea: the visitor shows a generated QR code to the merchant's camera for the check-in. (There are also multiple fal
by lifthrasiir 5y ago
The workflow is generally reversed in South Korea: the visitor shows a generated QR code to the merchant's camera for the check-in. (There are also multiple fallbacks available.) The QR code is, to my knowledge, a very short living JWT credential and looks like this: (I've redacted pretty much every nonce for the obvious reason)
003|eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZiIsImVucCI6Imh0dHBzOi8vd3NzLmNvb3YuaW8vMDEyMzQ1Njc4OUFiQ2RFZkdoSWoiLCJpc3MiOiJBQ01FIiwiZXhwIjoxNjAwMDAwMDAwLCJ2ZXJzaW9uIjoiMDAzIn0.AEwfg3OC34g07x_xVWekdUumxPTqbrRFvQkOVV_TQT4
That got encoded into a fairly large QR code---61 by 61 modules (version 11, error correction level L)---and it is always painful to get it recognized, mainly because every merchant's device is different and some devices and/or apps are particularly less responsive.
It is very noticable that there is a lot of redundancy here: the format of JWT payload will be very regular, always having `sub`, `enp`, `iss`, `exp` and `version` (fixed to `003`) fields in a verbose base64 format for example. It makes a fun challenge to optimize this into something much smaller.
- PeterisP 5y agoThe EU vaccination certificate (which is shown as a QR code in e.g. restaurants or public events) is twice longer than your example (572 characters for me), but it includes all the data and a digital signature to allow offline verification of whether that certificate is valid.
- paranoidrobot 5y agoTo be clear, this is not merchant-customer relationship for payment, or for any interaction at all. It's something that stores post on all their entrances so that visitors can record their visit in the appropriate check-in application. The merchant has no access to the data, it's sent to a state government datastore. (Although questions over it's security still remain). It's also supposed to be able to operate in offline mode - where cellular and wifi signals are unavailable. For instance, a shopping centre's entrance in the middle of an underground carpark.
- sbierwagen 5y ago>To be clear, this I haven't read the submission, so the subject of "this" is unclear. Are you referring to Vietnam, South Korea or Australia?
- yen223 5y ago"This" appears to be about Australia, as that's how things work here in NSW
- lifthrasiir 5y agoAh, that makes sense. In fact I was not sure why replies try to say about the offline usability of certificates as I just used a SK approach as another example of inefficient QR code uses. I don't think the SK approach is better than others or vice versa as long as proper fallbacks are provided and it seems it's the case for either NSW, SK or EU anyway.
- jimmydorry 5y agoImportant to note that offline mode (for QLD at least), was only introduced a few weeks ago, and only after a major service outage. QLD went almost the entire pandemic without something I would have thought was a critical feature (I am sure that I am not the only person walking around with a smartphone without a mobile data plan).
- toomanybeersies 5y agoGiven my experience with government IT, none of that surprises me at all. I'm sure offline check-in was mentioned at some point, but then promptly dismissed, likely by a product manager saying "they can just check in using pen and paper". As for outages, even as a (paying) commercial customer, the closest you'll get to an SLA from any government agency is: "apart from scheduled maintenance and subject to unexpected outages, the service should be available 24x7"
- Phemist 5y agoJust thought this would be interesting to share. The base64 encoding in JWT's forces the QR-code to use segments in byte-mode. This will encode individual JWT characters in 8 bits of data. The size of the characterset of a base64-encoded JWT is 65 (64-characters in base64 + '.'). Actually, in this spec, it is 66, including the `|`. An optimal encoding would use Log2(66) amount of bits per character. Alphanumeric mode at 5.5 bits per character is too small, but encoding individual JWT chars as 2 numeric characters (at 3 1/3 bits each) results in a more optimal encoding (~20% space savings). The mapping from the JWT char to 2 numeric coding is also quite trivial: take the ascii value of the char and subtract by 43. ``` def enc(c): return "%02d"%(ord(c) - 43) ``` The fantastic website https://www.nayuki.io/page/creating-a-qr-code-step-by-step https://www.nayuki.io/page/creating-a-qr-code-step-by-step shows, for the JWT you posted, a size of 2164 bits needed to encode the data inside the QR-code at low error-correction (resulting in a version 10 QR-code). If we run every char through the numeric encoding process, we get the following result: ``` 05050881587831055845226236623132430638623324316155285662366231304279300635623114035878317957443062366230763441307935254207357960104644316347284366342526783479380635635609364427624607396547623072306643745624301130666105572923793662137557083579336635755508467454441375342526783479380635635609364227623807392747645768404468623324316956083462366231233805062730627662474561763063687735632276342522763425227633243107474531795444147430636862342522793067050322267659600836240809600512775277434458645742746677374170557139277538643643435241384109``` Longer in terms of characters, but if we run it through the QR-encoder, we get a bitstream of length 1801. Which is possible to fit in a Version 9 (err corr L) QR-code. I thought this was pretty cool :)