verify revocation credential

This commit is contained in:
Cayo Puigdefabregas 2024-06-06 10:36:06 +02:00
parent d3e8580d00
commit 84a41385d0
3 changed files with 45 additions and 3 deletions

View file

@ -32,7 +32,7 @@ def main():
signing_key = get_signing_key(key) signing_key = get_signing_key(key)
credential = json.loads(credential_tmpl) credential = json.loads(credential_tmpl)
credential["issuer"] = did credential["issuer"]["id"] = did
credential["issuanceDate"] = now() credential["issuanceDate"] = now()
cred = json.dumps(credential) cred = json.dumps(credential)

View file

@ -10,7 +10,9 @@ credential_tmpl = """{
"credentialSubject": { "credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M" "id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M"
}, },
"issuer": "", "issuer": {
"id": ""
},
"issuanceDate": "" "issuanceDate": ""
}""" }"""

View file

@ -1,12 +1,16 @@
import json import json
import zlib
import base64
import nacl.encoding import nacl.encoding
import nacl.signing import nacl.signing
import multicodec import multicodec
import multiformats import multiformats
from nacl.signing import VerifyKey from nacl.signing import VerifyKey
from pyroaring import BitMap
from pyvckit.sign import to_jws_payload from pyvckit.sign import to_jws_payload
from pyvckit.did import resolve_did
def get_signing_input(payload): def get_signing_input(payload):
@ -48,6 +52,14 @@ def verify_vc(credential):
if not message: if not message:
return False return False
did_issuer = vc.get("issuer", {}) or vc.get("holder", {})
if isinstance(did_issuer, dict):
did_issuer = did_issuer.get("id")
did_issuer_method = vc["proof"]["verificationMethod"].split("#")[0]
if did_issuer != did_issuer_method:
return False
header_b64, signature = get_signing_input(message) header_b64, signature = get_signing_input(message)
header_jws, signature_jws = jws_split(jws) header_jws, signature_jws = jws_split(jws)
@ -57,14 +69,42 @@ def verify_vc(credential):
header_jws_json = json.loads( header_jws_json = json.loads(
nacl.encoding.URLSafeBase64Encoder.decode(header_jws) nacl.encoding.URLSafeBase64Encoder.decode(header_jws)
) )
for k, v in header.items(): for k, v in header.items():
if header_jws_json.get(k) != v: if header_jws_json.get(k) != v:
return False return False
verify_key = get_verify_key(vc) verify_key = get_verify_key(vc)
try: try:
data_verified = verify_key.verify(signature_jws+signature) data_verified = verify_key.verify(signature_jws+signature)
except nacl.exceptions.BadSignatureError: except nacl.exceptions.BadSignatureError:
return False return False
return data_verified == signature
if data_verified != signature:
return False
if "credentialStatus" in vc:
# NOTE: THIS FIELD SHOULD BE SERIALIZED AS AN INTEGER,
# BUT IOTA DOCUMENTAITON SERIALIZES IT AS A STRING.
# DEFENSIVE CAST ADDED JUST IN CASE.
revocation_index = int(vc["credentialStatus"]["revocationBitmapIndex"])
if did_issuer[:7] == "did:web": # Only DID:WEB can revoke
issuer_did_document = resolve_did(did_issuer)
issuer_revocation_list = issuer_did_document["service"][0]
assert issuer_revocation_list["type"] == "RevocationBitmap2022"
revocation_bitmap = BitMap.deserialize(
zlib.decompress(
base64.b64decode(
issuer_revocation_list["serviceEndpoint"].rsplit(",")[1].encode('utf-8')
)
)
)
if revocation_index in revocation_bitmap:
# Credential has been revoked by the issuer
return False
return True