Created
September 10, 2021 04:37
-
-
Save safiire/46d4f76b2718102f3bf6bd386acbbd53 to your computer and use it in GitHub Desktop.
Decode a Vaccine Passport QR code and Display Contents
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'base64' | |
require 'json' | |
require 'zlib' | |
# Requirements: | |
# Debian: apt-get install zbar-tools | |
# OSX: brew install zbar | |
class DecodePassport | |
Result = Struct.new(:header, :passport, :signature) | |
def self.call(filename) | |
new.call(filename) | |
end | |
def call(filename) | |
header, payload, signature = decode_jws(decode_shc(decode_qr(filename))) | |
Result.new( | |
JSON.parse(header), | |
JSON.parse(deflate_payload(payload)), | |
signature.bytes.map { |b| '%02x' % b }.join | |
) | |
end | |
private | |
def decode_qr(filename) | |
`zbarimg --raw "#{filename}" 2>/dev/null`.tap do | |
fail('Failed to decode QR') unless $?.success? | |
end | |
end | |
def decode_shc(shc) | |
shc.scan(/\d{2}/).map { |digit| (digit.to_i + 45).chr }.join | |
end | |
def decode_jws(jws) | |
jws.split('.').map { |part| Base64.urlsafe_decode64(part) } | |
end | |
def deflate_payload(payload) | |
Zlib::Inflate.new(-15).inflate(payload) | |
end | |
end | |
if ARGV.size.zero? | |
STDERR.puts("Usage: #{$0} <imagefile>") | |
exit(1) | |
end | |
result = DecodePassport.call(ARGV.first) | |
puts 'Header:' | |
puts JSON.pretty_generate(result.header) | |
puts 'Signature:' | |
puts result.signature | |
puts 'Passport:' | |
puts JSON.pretty_generate(result.passport) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment