Compare commits

..

3 Commits

Author SHA1 Message Date
Cayo Puigdefabregas 1ec9b9ce9e update READMES 2024-06-06 10:36:42 +02:00
Cayo Puigdefabregas 49bff70ed5 fix tests 2024-06-06 10:36:23 +02:00
Cayo Puigdefabregas 84a41385d0 verify revocation credential 2024-06-06 10:36:06 +02:00
7 changed files with 111 additions and 17 deletions

View File

@ -144,3 +144,11 @@ This document is an example and in production it must be adapted to contain the
did = generate_did(key, url)
definitive_url, document = gen_did_document(did, key)
```
# Differences with didkit from spruceId:
Although there is didkit support, there are some small differences in behavior.
## Namespaces:
In didkit it is necessary to define in the context every name, (key) used in the credential or else both the signature and the verification will fail.
In pyvckit if a name, (key) is used but is not defined in the context, then that signature or verification will filter out that part of the credential and ignore it as if it did not exist.
The signature will be made by deleting that undefined part.

View File

@ -144,3 +144,12 @@ Este documento es un ejemplo y en producción hay que adaptarlo para contener la
did = generate_did(key, url)
definitive_url, document = gen_did_document(did, key)
```
# Diferencias con didkit de spruceId:
Aunque hay compatibilidad con didkit, hay algunas pequeñas diferencias en el comportamiento.
## Espacios de nombres:
En didkit es necesario definir en el contexto todo nombre, (clave) usada en la credencial o si no fallará tanto la firma como la verificación.
En pyvckit si un nombre, (clave) se usa pero no esta definido en el contexto, entonces esa firma o verificación filtrará esa parte de la credencial y la omitirá como si no existiera.
La firma se hará borrando esa parte no definida.

View File

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

View File

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

View File

@ -1,12 +1,16 @@
import json
import zlib
import base64
import nacl.encoding
import nacl.signing
import multicodec
import multiformats
from nacl.signing import VerifyKey
from pyroaring import BitMap
from pyvckit.sign import to_jws_payload
from pyvckit.did import resolve_did
def get_signing_input(payload):
@ -48,6 +52,14 @@ def verify_vc(credential):
if not message:
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_jws, signature_jws = jws_split(jws)
@ -57,14 +69,42 @@ def verify_vc(credential):
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
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

View File

@ -80,7 +80,10 @@ def test_credential():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did,
"name": ""
},
"issuanceDate": now()
}
@ -105,7 +108,10 @@ def test_presentation():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did,
"name": ""
},
"issuanceDate": now()
}
@ -136,7 +142,10 @@ def test_verifiable_credential():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did,
"name": ""
},
"issuanceDate": now()
}
@ -159,7 +168,10 @@ def test_verifiable_presentation():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did,
"name": ""
},
"issuanceDate": now()
}
@ -189,7 +201,10 @@ def test_verifiable_credential_fail():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did,
"name": ""
},
"issuanceDate": now()
}
@ -213,7 +228,10 @@ def test_verifiable_presentation_fail1():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did,
"name": ""
},
"issuanceDate": now()
}
@ -243,7 +261,10 @@ def test_verifiable_presentation_fail2():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did,
"name": ""
},
"issuanceDate": now()
}

View File

@ -105,7 +105,9 @@ def test_pyvckit_credential_validated_from_didkit():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did
},
"issuanceDate": now()
}
@ -127,7 +129,9 @@ def test_didkit_credential_validated_from_pyvckit():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did
},
"issuanceDate": now()
}
@ -149,7 +153,9 @@ def test_pyvckit_presentation_validated_from_didkit():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did
},
"issuanceDate": now()
}
@ -179,7 +185,9 @@ def test_fail_pyvckit_presentation_validated_from_didkit():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did
},
"issuanceDate": now()
}
@ -213,7 +221,9 @@ def test_didkit_presentation_validated_from_pyvckit():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did
},
"issuanceDate": now()
}
cred_signed = render_and_sign_credential(credential, key)
@ -239,7 +249,9 @@ def test_fail_didkit_presentation_validated_from_pyvckit():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did
},
"issuanceDate": now()
}
cred_signed = render_and_sign_credential(credential, key)
@ -268,7 +280,9 @@ def test_fail2_didkit_presentation_validated_from_pyvckit():
"credentialSubject": {
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
},
"issuer": did,
"issuer": {
"id": did
},
"issuanceDate": now()
}
cred_signed = render_and_sign_credential(credential, key)