QR Code Encryption Specification
Purpose
This specification defines the process for encrypting and encoding personal contact details within QR codes. The encryption provides obfuscation to prevent casual QR code readers from accessing the plaintext data. QR codes do not grant authentication, authorisation, or the ability to perform actions within the application.
Encryption Method
- Algorithm: AES-256-GCM
- Key: 256-bit (32-byte) shared key distributed within the application
- IV/N-once: 96-bit (12-byte) randomly generated per encryption operation
- Authentication: GCM mode provides built-in authentication via a 128-bit (16-byte) authentication tag
Data Structure
Input Data (JSON):
json
json
{
"fullName": "string",
"mobileNumber": "string",
"companyName": "string",
"workId": "string"
}
```
**Encrypted QR Code Structure:**
```
[12-byte IV][Ciphertext][16-byte Auth Tag]Encryption Process
- Serialise JSON to UTF-8 string
- Convert the JSON object to a UTF-8 encoded string
- Generate random IV
- Generate a cryptographically secure random 96-bit (12-byte) IV for this encryption operation
- The IV must be unique for each QR code generated
- Encrypt using AES-256-GCM
- Encrypt the UTF-8 string using AES-256-GCM with the shared key and generated IV
- GCM automatically appends the 128-bit authentication tag to the ciphertext
- Construct binary payload
- Concatenate:
[IV (12 bytes)][Ciphertext (variable)][Auth Tag (16 bytes)]
- Concatenate:
- Encode to Base64
- Encode the complete binary payload to Base64 string
- Remove padding characters
- Strip all trailing
=characters from the Base64 string - This ensures compatibility with QR code AlphaNumeric mode
- Strip all trailing
- Generate QR code
- Create QR code from the modified Base64 string using AlphaNumeric mode
Decryption Process
- Read QR code
- Extract the AlphaNumeric encoded string from the QR code
- Restore Base64 padding
- Append
=characters until the string length is a multiple of 4 - Example: if length mod 4 = 2, append
==; if length mod 4 = 3, append=
- Append
- Decode from Base64
- Decode the Base64 string to binary data
- Extract components
- First 12 bytes: IV
- Last 16 bytes: Authentication tag
- Remaining middle bytes: Ciphertext
- Decrypt using AES-256-GCM
- Decrypt using the shared key, extracted IV, ciphertext, and authentication tag
- GCM will automatically verify the authentication tag
- Handle authentication failure
- If GCM authentication fails, reject the QR code as invalid
- Do not return partial or unauthenticated data
- Deserialise UTF-8 to JSON
- Convert the decrypted UTF-8 string back to JSON object
- Validate JSON structure matches expected schema
Security Considerations
- Obfuscation, not security: This approach provides obfuscation against casual observation. It is not designed to protect against determined attackers with access to the application binary.
- Key: The shared key could potentially be extracted from the application through reverse engineering. Security relies on obscurity rather than cryptographic strength.
- No authorisation: QR codes do not grant access, authentication, or authorisation to perform actions within the application. They are data carriers only.
- Future improvements: In the future, integrating with a worker-facing app should be considered. A digital QR code would provide for easier QR distribution, key rotation mechanisms, and version control.
Error Handling
Application must handle the following error cases:
- Invalid Base64: QR code contains characters incompatible with Base64 after padding restoration
- Authentication failure: GCM authentication tag verification fails (indicates tampering or corruption)
- Malformed JSON: Decrypted data is not valid JSON or missing required fields
- Incorrect data length: Payload is too short to contain IV and authentication tag
All errors should result in rejection of the QR code with appropriate user feedback.
QR Code Generation Parameters
- Mode: AlphaNumeric (achieves better density than binary mode for Base64 character set)
- Error correction: Medium (15%) or High (30%) recommended to handle physical damage
- Character set: Base64 alphabet without padding (
A-Z,0-9,+,/)