Skip to content

Added CommonPass QR code generation #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions decode_commonpass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import json
import argparse
import base64
import utils

def main():
parser = argparse.ArgumentParser(description='Decodes a CommonPass')
parser.add_argument('input', help='Input CommonPass URL')
args = parser.parse_args()

numeric_payload = args.input.split('#')[1]

input_jwt = utils.decode_from_numeric(numeric_payload)

payload_dict = utils.decode_vc(input_jwt, verify=False)

print(json.dumps(payload_dict, indent=4))

if __name__ == "__main__":
main()
40 changes: 40 additions & 0 deletions encode_commonpass_in_qr_code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import argparse
import json
import time
import secrets
import utils


def main():

parser = argparse.ArgumentParser(description='Encodes a vc')
parser.add_argument('private_keyset_file', help='Private keyset file')
parser.add_argument('issuer', help='Issuer')
parser.add_argument('url', help='URL')
parser.add_argument('input_file', help='Sample VC fixture file')
parser.add_argument('output_file', help='Output file')

args = parser.parse_args()
(kid, private_signing_key) = utils.load_private_key_from_file(
args.private_keyset_file,
'sig',
'ES256'
)

with open(args.input_file, 'r') as input_file:
payload = json.load(input_file)

##since we're using a static file to form the payload
## it needs to be modified a bit
now = int(time.time())
payload['iss'] = args.issuer
payload['iat'] = now
vc_jws = utils.encode_vc(payload, private_signing_key, kid)

numeric_encoded_payload = utils.encode_to_numeric(vc_jws)
qr_img = utils.create_cp_qr_code(args.url, numeric_encoded_payload)
with open(args.output_file, 'wb') as outfile:
qr_img.save(outfile)

if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion encode_resource_file_in_qr_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def main():
fhir_backed_vc = json.load(input_file).get('verifiableCredential')[0]

numeric_encoded_payload = utils.encode_to_numeric(fhir_backed_vc)
qr_img = utils.create_qr_code(numeric_encoded_payload)
qr_img = utils.create_shc_qr_code(numeric_encoded_payload)
with open(args.output_file, 'wb') as outfile:
qr_img.save(outfile)

Expand Down
2 changes: 1 addition & 1 deletion encode_resource_in_qr_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def main():
vc_jws = utils.encode_vc(payload, private_signing_key, kid)

numeric_encoded_payload = utils.encode_to_numeric(vc_jws)
qr_img = utils.create_qr_code(numeric_encoded_payload)
qr_img = utils.create_shc_qr_code(numeric_encoded_payload)
with open(args.output_file, 'wb') as outfile:
qr_img.save(outfile)

Expand Down
63 changes: 56 additions & 7 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,15 @@ def _decode_vc(jws_raw, key_resolver):
payload = json.loads(inflate(verified_jws))
return payload

def decode_vc(jws_raw):
resolver = resolve_key_from_issuer()
return _decode_vc(jws_raw, resolver)
def decode_vc(jws_raw, verify=True):
if verify:
resolver = resolve_key_from_issuer()
return _decode_vc(jws_raw, resolver)
else:
verified_jws = jws.verify(jws_raw, "", algorithms='None', verify=False)
payload = json.loads(inflate(verified_jws))
return payload


def decode_vc_from_local_issuer(jws_raw, jwks_file):
resolver = resolve_key_from_file(jwks_file)
Expand All @@ -153,8 +159,51 @@ def encode_char_to_numeric(ch):
def encode_to_numeric(payload):
return ''.join([encode_char_to_numeric(ch) for ch in payload])

def create_qr_code(numeric_encoded_payload):
qr = qrcode.QRCode()
qr.add_data(SMART_HEALTH_CARD_PREFIX)
qr.add_data(numeric_encoded_payload)
def decode_from_numeric(numeric):
if len(numeric) % 2 != 0:
raise Exception("uneven string")

pair_count = int(len(numeric) / 2)
chars = []
for i in range(pair_count):

offset = i * 2
pair = numeric[offset:offset+2]

try:
int_value = int(pair)
except BaseException as e:
print(i)
print(pair)
raise e

# print(int_value)
ch = chr(int_value + SMALLEST_B64_CHAR_CODE)
# print(ch)
chars.append(ch)

return ''.join(chars)


def create_shc_qr_code(numeric_encoded_payload):
qr = qrcode.QRCode(
error_correction=qrcode.constants.ERROR_CORRECT_L
)
qr.add_data(SMART_HEALTH_CARD_PREFIX, optimize=0)
qr.add_data(numeric_encoded_payload, optimize=0)
version = qr.best_fit()
print(f'The QR Version is {version}')
return qr.make_image(fill_color="black", back_color="white")

def create_cp_qr_code(url, numeric_encoded_payload):
print(numeric_encoded_payload)
qr = qrcode.QRCode(
error_correction=qrcode.constants.ERROR_CORRECT_L
)
qr.add_data(url.upper())
qr.add_data('#')
qr.add_data(numeric_encoded_payload, optimize=0)
version = qr.best_fit()
print(f'The QR Version is {version}')
# qr.make(fit=False)
return qr.make_image(fill_color="black", back_color="white")