Compare commits
3 Commits
d3e8580d00
...
1ec9b9ce9e
Author | SHA1 | Date |
---|---|---|
Cayo Puigdefabregas | 1ec9b9ce9e | |
Cayo Puigdefabregas | 49bff70ed5 | |
Cayo Puigdefabregas | 84a41385d0 |
|
@ -144,3 +144,11 @@ This document is an example and in production it must be adapted to contain the
|
||||||
did = generate_did(key, url)
|
did = generate_did(key, url)
|
||||||
definitive_url, document = gen_did_document(did, key)
|
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.
|
||||||
|
|
|
@ -144,3 +144,12 @@ Este documento es un ejemplo y en producción hay que adaptarlo para contener la
|
||||||
did = generate_did(key, url)
|
did = generate_did(key, url)
|
||||||
definitive_url, document = gen_did_document(did, key)
|
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.
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,9 @@ credential_tmpl = """{
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M"
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M"
|
||||||
},
|
},
|
||||||
"issuer": "",
|
"issuer": {
|
||||||
|
"id": ""
|
||||||
|
},
|
||||||
"issuanceDate": ""
|
"issuanceDate": ""
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,10 @@ def test_credential():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did,
|
||||||
|
"name": ""
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +108,10 @@ def test_presentation():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did,
|
||||||
|
"name": ""
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +142,10 @@ def test_verifiable_credential():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did,
|
||||||
|
"name": ""
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +168,10 @@ def test_verifiable_presentation():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did,
|
||||||
|
"name": ""
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +201,10 @@ def test_verifiable_credential_fail():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did,
|
||||||
|
"name": ""
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +228,10 @@ def test_verifiable_presentation_fail1():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did,
|
||||||
|
"name": ""
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +261,10 @@ def test_verifiable_presentation_fail2():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did,
|
||||||
|
"name": ""
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,9 @@ def test_pyvckit_credential_validated_from_didkit():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +129,9 @@ def test_didkit_credential_validated_from_pyvckit():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +153,9 @@ def test_pyvckit_presentation_validated_from_didkit():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +185,9 @@ def test_fail_pyvckit_presentation_validated_from_didkit():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +221,9 @@ def test_didkit_presentation_validated_from_pyvckit():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
cred_signed = render_and_sign_credential(credential, key)
|
cred_signed = render_and_sign_credential(credential, key)
|
||||||
|
@ -239,7 +249,9 @@ def test_fail_didkit_presentation_validated_from_pyvckit():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
cred_signed = render_and_sign_credential(credential, key)
|
cred_signed = render_and_sign_credential(credential, key)
|
||||||
|
@ -268,7 +280,9 @@ def test_fail2_didkit_presentation_validated_from_pyvckit():
|
||||||
"credentialSubject": {
|
"credentialSubject": {
|
||||||
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
"id": "did:key:z6MkgGXSJoacuuNdwU1rGfPpFH72GACnzykKTxzCCTZs6Z2M",
|
||||||
},
|
},
|
||||||
"issuer": did,
|
"issuer": {
|
||||||
|
"id": did
|
||||||
|
},
|
||||||
"issuanceDate": now()
|
"issuanceDate": now()
|
||||||
}
|
}
|
||||||
cred_signed = render_and_sign_credential(credential, key)
|
cred_signed = render_and_sign_credential(credential, key)
|
||||||
|
|
Loading…
Reference in New Issue