# pip3 install ecdsa # pip3 install dnspython import hashlib import base64 import dns.resolver from hashlib import sha256 from ecdsa import SigningKey, VerifyingKey from ecdsa.util import sigencode_der, sigdecode_der def pad(base32NoPad): base32 = base32NoPad if (len(base32NoPad) % 8 == 2): return base32NoPad + "======" if (len(base32NoPad) % 8 == 4): return base32NoPad + "====" if (len(base32NoPad) % 8 == 5): return base32NoPad + "===" if (len(base32NoPad) % 8 == 7): return base32NoPad + "=" return base32 def rmPad(base32text): return base32text.replace('=','') def parseQR(qr): return qr.split(':') def download(pubKeyLink): key = dns.resolver.resolve(pubKeyLink, 'TXT')[0].strings[0].decode("utf-8").replace("\\n","\n"); if ("-----BEGIN PUBLIC KEY-----" not in key): key = "-----BEGIN PUBLIC KEY-----" + "\n" + key + "\n" + "-----END PUBLIC KEY-----\n" return key def parseAndVerifyQR(qr): [schema, qrtype, version, signatureBase32NoPad, pubKeyLink, payload] = parseQR(qr) print ("Parsed QR\t", schema, qrtype, version, signatureBase32NoPad, pubKeyLink, payload) payloadBytes = payload.encode("utf-8") signatureDER = base64.b32decode(pad(signatureBase32NoPad)) print("Payload Bytes\t", *payloadBytes) print("Signature DER\t", *signatureDER) vk = VerifyingKey.from_pem(download(pubKeyLink)) verified = vk.verify(signatureDER, payloadBytes, hashfunc=sha256, sigdecode=sigdecode_der) print("\nVerify Payload\t", verified) return verified def signAndFormatQR(sk, schema, qrtype, version, pubKeyLink, payload): payloadBytes = payload.encode("utf-8") sig = sk.sign(payloadBytes, hashfunc=sha256, sigencode=sigencode_der) formattedSig = rmPad(base64.b32encode(sig).decode("ascii")) return ':'.join([schema, qrtype, version, formattedSig, pubKeyLink, payload]) qr = 'CRED:STATUS:2:GBCAEIAHV2J6PWDSYVLI67RN55WVHIMUTKLFF5GZ4NPHPZ7ZSIJE4MP5M4BCAU6QVDHUP4RQCPXW6XJDAM54VMZ7XURUN34WFT2RWL5ETTZDNHUF:KEYS.PATHCHECK.ORG:1/BUQHHANUB4Z5KHBZTYCWMNI4RQ6CP5WFVVQCUXYHCQVY5WLDDFPA/' print("") print("Loading hardcoded QR") print("") parseAndVerifyQR(qr) print("") print("Resigning same payload") print("") # Loading private key with open("keys/ecdsa_private_key") as f: sk = SigningKey.from_pem(f.read()) [schema, qrtype, version, _, pubKeyLink, payload] = parseQR(qr) newQR = signAndFormatQR(sk, schema, qrtype, version, pubKeyLink, payload) print("New QR Signed\t", newQR) print("") parseAndVerifyQR(newQR)