Compare commits

...

2 Commits

Author SHA1 Message Date
Cayo Puigdefabregas 8eb0b70f0a add did web in README 2024-05-30 11:12:04 +02:00
Cayo Puigdefabregas 1c14e11d73 add did web 2024-05-30 11:11:37 +02:00
5 changed files with 171 additions and 8 deletions

View File

@ -20,7 +20,7 @@ For now the installation is from the repository:
pip install -e . pip install -e .
``` ```
#Cli # Cli
The mode of use under the command line would be the following: The mode of use under the command line would be the following:
## generate a key pair: ## generate a key pair:
@ -29,10 +29,17 @@ The mode of use under the command line would be the following:
``` ```
## generate a did identifier: ## generate a did identifier:
### did key
```sh ```sh
python did.py -n did -k keypair.json python did.py -n did -k keypair.json
``` ```
### did web
```sh
python did.py -n did -k keypair.json -u https://localhost/user1/dids/
```
## generate an example signed credential: ## generate an example signed credential:
An example of a credential is generated, which is the one that appears in the credential_tmpl template in the file [templates.py](templates.py) An example of a credential is generated, which is the one that appears in the credential_tmpl template in the file [templates.py](templates.py)
```sh ```sh
@ -54,7 +61,7 @@ An example of a credential is generated, which is the one that appears in the cr
python verify_vp.py presentation_signed.json python verify_vp.py presentation_signed.json
``` ```
# Use as a lib # Use as a library
In the tests you can find examples of use. Now I will explain the usual cases In the tests you can find examples of use. Now I will explain the usual cases
## generate a key pair: ## generate a key pair:
@ -64,12 +71,22 @@ In the tests you can find examples of use. Now I will explain the usual cases
``` ```
## generate a did identifier: ## generate a did identifier:
### did key
```python ```python
from pyvckit.did import generate_keys, generate_did from pyvckit.did import generate_keys, generate_did
key = generate_keys() key = generate_keys()
did = generate_did(key) did = generate_did(key)
``` ```
### did web
```python
from pyvckit.did import generate_keys, generate_did
key = generate_keys()
url = "https://localhost/user1/dids/"
did = generate_did(key, url)
```
## generate a signed credential: ## generate a signed credential:
Assuming **credential** is a valid credential. Assuming **credential** is a valid credential.
**credential** is a string variable **credential** is a string variable
@ -108,3 +125,15 @@ Assuming **vc** is a properly signed verifiable credential
from pyvckit.verify_vp import verify_vp from pyvckit.verify_vp import verify_vp
verified = verify_vp(json.dumps(vp)) verified = verify_vp(json.dumps(vp))
``` ```
## creation of did document:
This command will create a json document and a url path where to place this document. The did must be a web did.
This document is an example and in production it must be adapted to contain the revoked verifiable credentials.
```python
from pyvckit.did import generate_keys, generate_did, gen_did_document
key = generate_keys()
url = "https://localhost/did-registry"
did = generate_did(key, url)
definitive_url, document = gen_did_document(did, key)
```

View File

@ -29,10 +29,17 @@ El modo de uso bajo la linea de comandos seria el siguiente:
``` ```
## generar un identificador did: ## generar un identificador did:
### did key
```sh ```sh
python did.py -n did -k keypair.json python did.py -n did -k keypair.json
``` ```
### did web
```sh
python did.py -n did -k keypair.json -u https://localhost/user1/dids/
```
## generar una credencial firmada de ejemplo: ## generar una credencial firmada de ejemplo:
Se genera un ejemplo de credencial que es el que aparece en la plantilla credential_tmpl del fichero [templates.py](templates.py) Se genera un ejemplo de credencial que es el que aparece en la plantilla credential_tmpl del fichero [templates.py](templates.py)
```sh ```sh
@ -54,6 +61,12 @@ Se genera un ejemplo de credencial que es el que aparece en la plantilla credent
python verify_vp.py presentation_signed.json python verify_vp.py presentation_signed.json
``` ```
## creación del documento did:
Este comando creara un documento json y una ruta url donde colocar este documento. El did tiene que ser un did web.
```sh
python did.py -k keypair.json -g did:web:localhost:did-registry:z6MkiNc8xqJLcG7QR1wzD9HPs5oPQEaWNcVf92QsbppNiB7C
```
# Uso como librería # Uso como librería
En los test podras encontrar ejemplos de uso. Ahora explicare los casos habituales En los test podras encontrar ejemplos de uso. Ahora explicare los casos habituales
@ -64,12 +77,22 @@ En los test podras encontrar ejemplos de uso. Ahora explicare los casos habitual
``` ```
## generar un identificador did: ## generar un identificador did:
### did key
```python ```python
from pyvckit.did import generate_keys, generate_did from pyvckit.did import generate_keys, generate_did
key = generate_keys() key = generate_keys()
did = generate_did(key) did = generate_did(key)
``` ```
### did web
```python
from pyvckit.did import generate_keys, generate_did
key = generate_keys()
url = "https://localhost/user1/dids/"
did = generate_did(key, url)
```
## generar una credencial firmada: ## generar una credencial firmada:
Suponiendo que **credential** es una credencial válida. Suponiendo que **credential** es una credencial válida.
**credential** es una variable de tipo string **credential** es una variable de tipo string
@ -108,3 +131,15 @@ Suponiendo que **vc** es una credencial verificable correctamente firmada
from pyvckit.verify_vp import verify_vp from pyvckit.verify_vp import verify_vp
verified = verify_vp(json.dumps(vp)) verified = verify_vp(json.dumps(vp))
``` ```
## creación del documento did:
Este comando creara un documento json y una ruta url donde colocar este documento. El did tiene que ser un did web.
Este documento es un ejemplo y en producción hay que adaptarlo para contener las credenciales verificables revocadas.
```python
from pyvckit.did import generate_keys, generate_did, gen_did_document
key = generate_keys()
url = "https://localhost/did-registry"
did = generate_did(key, url)
definitive_url, document = gen_did_document(did, key)
```

70
did.py
View File

@ -1,16 +1,19 @@
import json import json
import argparse import argparse
import requests
import multicodec import multicodec
import multiformats import multiformats
import nacl.signing import nacl.signing
import nacl.encoding import nacl.encoding
from jwcrypto import jwk from jwcrypto import jwk
from urllib.parse import urlparse
from nacl.signing import SigningKey from nacl.signing import SigningKey
from nacl.encoding import RawEncoder from nacl.encoding import RawEncoder
from templates import did_document_tmpl
def key_to_did(public_key_bytes, type_did): def key_to_did(public_key_bytes, url):
"""did-key-format := """did-key-format :=
did:key:MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes))""" did:key:MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes))"""
@ -19,8 +22,11 @@ def key_to_did(public_key_bytes, type_did):
# Multibase encode the hashed bytes # Multibase encode the hashed bytes
did = multiformats.multibase.encode(mc, 'base58btc') did = multiformats.multibase.encode(mc, 'base58btc')
if type_did == "web": if url:
return f"did:web:{did}" u = urlparse(url)
domain = u.netloc
path = u.path.strip("/").replace("/", ":")
return f"did:web:{domain}:{path}:{did}"
return f"did:key:{did}" return f"did:key:{did}"
@ -45,13 +51,13 @@ def get_signing_key(jwk_pr):
return signing_key return signing_key
def generate_did(jwk_pr, type_did=None): def generate_did(jwk_pr, url=None):
signing_key = get_signing_key(jwk_pr) signing_key = get_signing_key(jwk_pr)
verify_key = signing_key.verify_key verify_key = signing_key.verify_key
public_key_bytes = verify_key.encode() public_key_bytes = verify_key.encode()
# Generate the DID # Generate the DID
did = key_to_did(public_key_bytes, type_did) did = key_to_did(public_key_bytes, url)
return did return did
def generate_keys(): def generate_keys():
@ -62,10 +68,44 @@ def generate_keys():
return json.dumps(key_json) return json.dumps(key_json)
def gen_did_document(did, keys):
if did[:8] != "did:web:":
return "", ""
document = did_document_tmpl.copy()
webdid_owner = did+"#owner"
webdid_revocation = did+"#revocation"
document["id"] = did
document["verificationMethod"][0]["id"] = webdid_owner
document["verificationMethod"][0]["controller"] = did
document["verificationMethod"][0]["publicKeyJwk"]["x"] = keys["x"]
document["authentication"].append(webdid_owner)
document["assertionMethod"].append(webdid_owner)
document["service"][0]["id"] = webdid_revocation
document_fixed_serialized = json.dumps(document)
url = "https://" + "/".join(did.split(":")[2:]) + "/did.json"
return url, document_fixed_serialized
def resolve_did(did):
if did[:8] != "did:web:":
return
try:
url = "https://" + "/".join(did.split(":")[2:]) + "/did.json"
response = requests.get(url)
except Exception:
url = "http://" + "/".join(did.split(":")[2:]) + "/did.json"
response = requests.get(url)
if 200 <= response.status_code < 300:
return response.json()
def main(): def main():
parser=argparse.ArgumentParser(description='Generates a new did or key pair') parser=argparse.ArgumentParser(description='Generates a new did or key pair')
parser.add_argument("-k", "--key-path", required=False) parser.add_argument("-k", "--key-path", required=False)
parser.add_argument("-n", "--new", choices=['keys', 'did']) parser.add_argument("-n", "--new", choices=['keys', 'did'])
parser.add_argument("-u", "--url")
parser.add_argument("-g", "--gen-doc")
args=parser.parse_args() args=parser.parse_args()
if args.new == 'keys': if args.new == 'keys':
@ -77,12 +117,32 @@ def main():
print("error: argument --key-path: expected one argument") print("error: argument --key-path: expected one argument")
return return
if args.new == 'did' and args.url:
key = key_read(args.key_path)
did = generate_did(key, args.url)
print(did)
return
if args.new == 'did': if args.new == 'did':
key = key_read(args.key_path) key = key_read(args.key_path)
did = generate_did(key) did = generate_did(key)
print(did) print(did)
return return
if args.gen_doc and not args.key_path:
print("error: argument --key-path: expected one argument")
return
if args.gen_doc:
keys = json.loads(key_read(args.key_path))
if not keys.get("x"):
print("error: argument --key-path: not is valid")
return
url, doc = gen_did_document(args.gen_doc, keys)
# print(url)
print(doc)
return
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -25,3 +25,4 @@ Pillow
multiformats multiformats
PyNaCl PyNaCl
py-multicodec py-multicodec
pyroaring

View File

@ -27,3 +27,41 @@ presentation_tmpl = {
"holder": "", "holder": "",
"verifiableCredential": [] "verifiableCredential": []
} }
did_document_tmpl = {
"@context": [
"https://www.w3.org/ns/did/v1",
{
"Ed25519VerificationKey2018": "https://w3id.org/security#Ed25519VerificationKey2018",
"publicKeyJwk": {
"@id": "https://w3id.org/security#publicKeyJwk",
"@type": "@json"
}
}
],
"id": "",
"verificationMethod": [
{
"id": "",
"type": "Ed25519VerificationKey2018",
"controller": "",
"publicKeyJwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": ""
}
}
],
"authentication": [
],
"assertionMethod": [
],
"service": [
{
"id": "",
"type": "RevocationBitmap2022",
"serviceEndpoint": "data:application/octet-stream;base64,eJyzMmAAAwADKABr"
}
]
}