pyvckit/verify.py

71 lines
1.8 KiB
Python

import json
import nacl.encoding
import nacl.signing
import multicodec
import multiformats
from nacl.signing import VerifyKey
from sign import to_jws_payload
def get_signing_input(payload):
header = b'{"alg":"EdDSA","crit":["b64"],"b64":false}'
header_b64 = nacl.encoding.URLSafeBase64Encoder.encode(header)
signing_input = header_b64 + b"." + payload
return header_b64, signing_input
def get_message(vc):
document = vc.copy()
proof = document.pop("proof", {})
jws = proof.pop("jws", None)
proof['@context'] = 'https://w3id.org/security/v2'
if not jws:
return None, False
return jws+"==", to_jws_payload(document, proof)
def get_verify_key(vc):
did = vc["proof"]["verificationMethod"].split("#")[0]
pub = did.split(":")[-1]
mc = multiformats.multibase.decode(pub)
public_key_bytes = multicodec.remove_prefix(mc)
return VerifyKey(public_key_bytes)
def jws_split(jws):
header, sig_b64 = jws.split("..")
signature = nacl.encoding.URLSafeBase64Encoder.decode(sig_b64.encode())
return header.encode(), signature
def verify_vc(credential):
vc = json.loads(credential)
header = {"alg": "EdDSA", "crit": ["b64"], "b64": False}
jws, message = get_message(vc)
if not message:
return False
header_b64, signature = get_signing_input(message)
header_jws, signature_jws = jws_split(jws)
if header_jws != header_b64:
return False
header_jws_json = json.loads(
nacl.encoding.URLSafeBase64Encoder.decode(header_jws)
)
for k, v in header.items():
if header_jws_json.get(k) != v:
return False
verify_key = get_verify_key(vc)
try:
data_verified = verify_key.verify(signature_jws+signature)
except nacl.exceptions.BadSignatureError:
return False
return data_verified == signature