epicqr/SPEC.md

3.5 KiB

Specification

Informal and unofficial specification. Please file an issue for any clarifications.

QR Generation

  1. Generate the input as {"epic_no":"[[EPIC_NO]]","unique_generated_id":ID}.

    ⚠️ Note that this is not parsed as JSON, so the string needs to be exactly 51 characters long.

  2. Encrypt the input using AES/CBC/PKCS5, with a static KEY and IV (See src/EpicQR.hx for values).

  3. Encode the output as standard base64.

  4. Generate a QR code with low error correction level.

See the recipe on CyberChef for a complete sample generation.

QR Decoding

  1. Scan the QR Code
  2. Decode using base64.
  3. Decrypt using AES/CBC/PKCS5, with a static KEY and IV (See src/EpicQR.hx for values).
  4. Parse as JSON.
  5. Extract epic_no and unique_generated_id keys inside the JSON object. Any additional keys may be discarded.

See the recipe on Cyberchef for a sample decoding.

EPIC ID Format

  • Length = 11 characters
  • First 3 characters are alphabets
  • Next 6 characters are digits
  • Last digit is a luhn checksum of the 6 numeric digits.

The following regex extracts the series, sequence identifier, and the checksum:

(?<series>[a-z]{3})(?<sequence_id>\d{6})(?<checksum>\d)

The following constraint holds:

LUHN(sequence_id) == checksum

Test Vectors

This is sample generated data.

Input Data

  • EPIC: "ABC1234566"
  • ID: 1234

JSON String

Valid
{"epic_no":"ABC1234566","unique_generated_id":1234}
Invalid
{"epic_no": "ABC1234566","unique_generated_id":1234}

Note the extra space.

Encoded Base64
dbhvecY6Roa4NF3gAzEbkTibZZzXAEYpMg8197BQWMS2+ID24FGDKWB5IEcuxjsA81ChprhSO3EsjKMRDbBWLg==

See the recipe on CyberChef.

QR Image

See image generation recipe Cyberchef.

QR Image for test