From 361da8e734f63c1ce9391085399e258388ebd45e Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Fri, 31 Dec 2021 11:05:24 +0200 Subject: Initial structure refactoring --- verify.py | 166 -------------------------------------------------------------- 1 file changed, 166 deletions(-) delete mode 100644 verify.py (limited to 'verify.py') diff --git a/verify.py b/verify.py deleted file mode 100644 index 23823d2..0000000 --- a/verify.py +++ /dev/null @@ -1,166 +0,0 @@ -import base64 -import click -import fitz -import json - -from io import BytesIO -from pathlib import Path - -from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import padding, ec -from cryptography.exceptions import InvalidSignature -from PIL import Image -from pyzbar import pyzbar - - -class GreenPassVerifier(object): - def __init__(self, data_bytes): - self.validate_bytes(data_bytes) - - print(data_bytes) - sig, self.payload = data_bytes.split(b"#", maxsplit=1) - self.signature = base64.decodebytes(sig) - self.data = json.loads(self.payload) - - self.validate_data() - self.details = self.get_details() - self.digest = self.get_digest() - - self.ec_cert = self.get_cert_path("IL-NB-DSC-01.pem") - self.rsa_cert = self.get_cert_path("RamzorQRPubKey.pem") - - @classmethod - def from_payload(cls, path): - with open(path, "rb") as f: - return cls(f.read().strip()) - - @classmethod - def from_qr(cls, path): - return cls(pyzbar.decode(Image.open(path))[0].data) - - @classmethod - def from_pdf(cls, path): - doc = fitz.open(path) - for i in range(len(doc)): - for img in doc.get_page_images(i): - xref, width = img[0], img[2] - try: - img = fitz.Pixmap(doc, xref) - data = img.tobytes(output="png") - with open(f"/tmp/greenpass/{xref}.png", "wb") as f: - f.write(data) - return cls.from_qr(BytesIO(data)) - except: - pass - else: - raise Exception("No QR found") - - def validate_bytes(self, bs): - if bs.decode().startswith("GreenPass"): - click.secho( - "⚠️ Green pass QR code contains no signature to verify", - fg="yellow", - bold=True, - ) - click.get_current_context().exit() - - def validate_data(self): - ct = self.data["ct"] - if ct not in (1, 2): - click.secho(f"Unknown certificate type ct={ct}", fg="red", bold=True) - click.get_current_context().exit() - - def get_cert_path(self, name): - return Path(__file__).absolute().parent / "certs" / name - - def get_details(self): - details = [] - data = self.data - if data["ct"] == 1: - for i in range(len(data["p"])): - details.append( - { - "id_num": data["p"][i]["idl"], - "valid_by": data["p"][i]["e"], - "cert_id": data["id"], - } - ) - elif data["ct"] == 2: - details.append( - { - "id_num": data["idl"], - "valid_by": data["e"], - "cert_id": data["id"], - } - ) - return details - - def get_digest(self): - ct = self.data["ct"] - if ct == 1: - digest = self.payload.decode().encode("utf8") - elif ct == 2: - h = hashes.Hash(hashes.SHA256()) - h.update(self.payload) - digest = h.finalize() - return digest - - def verify(self): - for d in self.details: - click.echo(f"\tIsraeli ID Number {d['id_num']}") - click.echo(f"\tID valid by {d['valid_by']}") - click.echo(f"\tCert Unique ID {d['cert_id']}") - - certs = [ - [ - self.rsa_cert, - [ - padding.PKCS1v15(), - hashes.SHA256(), - ], - ], - [self.ec_cert, [ec.ECDSA(hashes.SHA256())]], - ] - for cert, method in certs: - with open(cert, "rb") as f: - k = serialization.load_pem_public_key(f.read()) - try: - k.verify(self.signature, self.digest, *method) - click.secho("✅ Valid signature!", fg="green", bold=True) - break - except InvalidSignature: - pass - else: - click.secho("❌ Invalid signature!", fg="red", bold=True) - - -@click.command() -@click.option("-p", "--pdf-path", type=click.Path(exists=True), help="Path to PDF file") -@click.option( - "-i", - "--image-path", - type=click.Path(exists=True), - help="Path to an image with the QR code", -) -@click.option( - "-t", - "--txt-path", - type=click.Path(exists=True), - help="Path to decoded QR code textual content", -) -def verify(pdf_path="", image_path="", txt_path=""): - if image_path: - verifier = GreenPassVerifier.from_qr(image_path) - elif pdf_path: - verifier = GreenPassVerifier.from_pdf(pdf_path) - elif txt_path: - verifier = GreenPassVerifier.from_payload(txt_path) - else: - ctx = click.get_current_context() - click.echo(ctx.get_help()) - ctx.exit() - verifier.verify() - - -if __name__ == "__main__": - verify() -- cgit v1.3.1