Module dexa_sdk.did_mydata.core
Expand source code
import binascii
import typing
from pyld import jsonld
import base64
from multibase import encode
from merklelib import MerkleTree
from aries_cloudagent.messaging.models.base import BaseModel
from ..utils import jcs_rfc8785
from ..jsonld.core import jsonld_context_fingerprint
class DIDMyDataBuilder:
"""Builder for did:mydata identifier"""
def __init__(
self,
*,
artefact: BaseModel,
did: str = None,
) -> None:
"""
Args:
artefact (BaseModel): MyData artefact for .e.g. DA, DDA
did (str, optional): did:mydata identifier. Defaults to None.
"""
self._artefact = artefact
self._mydata_did = did
self._merkle_tree = None
def nquads(self) -> typing.List[str]:
"""JSON-LD normalise document using URDNA2015.
For reference: https://json-ld.github.io/normalization/spec/
Returns:
typing.List[str]: n-quads statements
"""
# Config for JSONLD normalisation
config = {"algorithm": "URDNA2015", "format": "application/n-quads"}
# Obtains the dictionary representation of the document
doc = self._artefact.serialize()
# Convert the doc to nquads statements
normalized = jsonld.normalize(doc, config)
# Split normalised string into multiple statements
normalized = normalized.split("\n")
# Return the statements
return normalized[:-1]
def build_merkle_tree(self) -> MerkleTree:
"""Build merkle tree from nquads statements about the artefact
Returns:
MerkleTree: merkle tree
"""
# Normalise document to n-quads
data = self.nquads()
# Build merkle tree
mt = MerkleTree(data)
# Store the merkle tree in the instance
self._merkle_tree = mt
return mt
def jcs(self) -> bytes:
"""Canonicalise the agreement using JCS IETF RFC8785
Returns:
bytes: jcs bytes
"""
return jcs_rfc8785(self._artefact.serialize())
def base64(self) -> str:
"""Returns output string after performing base64 encoding
on JSON Canonicalisation Schema (JCS) on the document.
Returns:
str: base64 encoded string
"""
return base64.urlsafe_b64encode(self.jcs()).decode()
def generate_did(self, context_type="DataAgreement") -> str:
"""
Generate the did:mydata identifier for the agreement
Returns:
did (str): did:mydata identifier
"""
# Merkle tree
mt = self.build_merkle_tree()
# Merkle root (sha256 fingerprint)
mr = mt.merkle_root
# Obtain SHA2-256 fingerprint for agreement JSONLD context
at = jsonld_context_fingerprint(context_type=context_type)
# Create did:mydata v2 identifier
mydata_did = DidMyData(agreement_type=at, agreement_merkle_root=mr)
did = mydata_did.did
# Store the did:mydata identifier in the instance
self._mydata_did = did
return did
@property
def mydata_did(self) -> str:
"""Returns did:mydata identifier
Returns:
str: did:mydata identifier
"""
# If did:mydata identifier not generated.
if not self._mydata_did:
# Generate did:mydata identifier
return self.generate_did()
return self._mydata_did
@mydata_did.setter
def mydata_did(self, did: str) -> None:
"""Set did:mydata identifier
Args:
did (str): did:mydata identifier
"""
self._mydata_did = did
@property
def merkle_tree(self) -> MerkleTree:
"""Returns merkle tree
Returns:
MerkleTree: merkle tree
"""
# If merkle tree not available
if not self._merkle_tree:
# Build merkle tree and return it.
return self.build_merkle_tree()
return self._merkle_tree
@property
def merkle_root(self) -> str:
"""Returns merkle root
Returns:
str: merkle root
"""
return self.merkle_tree.merkle_root
@property
def artefact(self) -> BaseModel:
"""Returns MyData artefact
Returns:
BaseModel: MyData artefact
"""
return self._artefact
class DidMyData:
def __init__(self,
*,
agreement_type: str,
agreement_merkle_root: str) -> None:
"""
Initialise the DidMydata class
Args:
agreement_type (str):
SHA2-256 fingerprint of the agreement JSONLD context
agreement_merkle_root (str):
SHA2-256 merkle root for the agreement document
Returns:
None
"""
self._agreement_type = agreement_type
self._agreement_merkle_root = agreement_merkle_root
# Generate did:mydata v2 identifier
self._did = self.generate()
def generate(self) -> str:
"""Create did:mydata v2 identifier"""
# Agreement type sha256 fingerprint to bytes
agreement_type_bytes = binascii.unhexlify(self._agreement_type)
# Agreement merkle root sha256 fingerprint to bytes
agreement_merkle_root_bytes = binascii.unhexlify(
self._agreement_merkle_root)
# 16 + 38 bytes = 48 byte method specific identifier
identifier = agreement_type_bytes[:16] + agreement_merkle_root_bytes
# Multibase encode
identifier = encode('base58btc', identifier).decode()
return f"did:mydata:{identifier}"
@property
def did(self) -> str:
return self._did
Classes
class DIDMyDataBuilder (*, artefact: aries_cloudagent.messaging.models.base.BaseModel, did: str = None)
-
Builder for did:mydata identifier
Args
artefact
:BaseModel
- MyData artefact for .e.g. DA, DDA
did
:str
, optional- did:mydata identifier. Defaults to None.
Expand source code
class DIDMyDataBuilder: """Builder for did:mydata identifier""" def __init__( self, *, artefact: BaseModel, did: str = None, ) -> None: """ Args: artefact (BaseModel): MyData artefact for .e.g. DA, DDA did (str, optional): did:mydata identifier. Defaults to None. """ self._artefact = artefact self._mydata_did = did self._merkle_tree = None def nquads(self) -> typing.List[str]: """JSON-LD normalise document using URDNA2015. For reference: https://json-ld.github.io/normalization/spec/ Returns: typing.List[str]: n-quads statements """ # Config for JSONLD normalisation config = {"algorithm": "URDNA2015", "format": "application/n-quads"} # Obtains the dictionary representation of the document doc = self._artefact.serialize() # Convert the doc to nquads statements normalized = jsonld.normalize(doc, config) # Split normalised string into multiple statements normalized = normalized.split("\n") # Return the statements return normalized[:-1] def build_merkle_tree(self) -> MerkleTree: """Build merkle tree from nquads statements about the artefact Returns: MerkleTree: merkle tree """ # Normalise document to n-quads data = self.nquads() # Build merkle tree mt = MerkleTree(data) # Store the merkle tree in the instance self._merkle_tree = mt return mt def jcs(self) -> bytes: """Canonicalise the agreement using JCS IETF RFC8785 Returns: bytes: jcs bytes """ return jcs_rfc8785(self._artefact.serialize()) def base64(self) -> str: """Returns output string after performing base64 encoding on JSON Canonicalisation Schema (JCS) on the document. Returns: str: base64 encoded string """ return base64.urlsafe_b64encode(self.jcs()).decode() def generate_did(self, context_type="DataAgreement") -> str: """ Generate the did:mydata identifier for the agreement Returns: did (str): did:mydata identifier """ # Merkle tree mt = self.build_merkle_tree() # Merkle root (sha256 fingerprint) mr = mt.merkle_root # Obtain SHA2-256 fingerprint for agreement JSONLD context at = jsonld_context_fingerprint(context_type=context_type) # Create did:mydata v2 identifier mydata_did = DidMyData(agreement_type=at, agreement_merkle_root=mr) did = mydata_did.did # Store the did:mydata identifier in the instance self._mydata_did = did return did @property def mydata_did(self) -> str: """Returns did:mydata identifier Returns: str: did:mydata identifier """ # If did:mydata identifier not generated. if not self._mydata_did: # Generate did:mydata identifier return self.generate_did() return self._mydata_did @mydata_did.setter def mydata_did(self, did: str) -> None: """Set did:mydata identifier Args: did (str): did:mydata identifier """ self._mydata_did = did @property def merkle_tree(self) -> MerkleTree: """Returns merkle tree Returns: MerkleTree: merkle tree """ # If merkle tree not available if not self._merkle_tree: # Build merkle tree and return it. return self.build_merkle_tree() return self._merkle_tree @property def merkle_root(self) -> str: """Returns merkle root Returns: str: merkle root """ return self.merkle_tree.merkle_root @property def artefact(self) -> BaseModel: """Returns MyData artefact Returns: BaseModel: MyData artefact """ return self._artefact
Instance variables
var artefact : aries_cloudagent.messaging.models.base.BaseModel
-
Returns MyData artefact
Returns
BaseModel
- MyData artefact
Expand source code
@property def artefact(self) -> BaseModel: """Returns MyData artefact Returns: BaseModel: MyData artefact """ return self._artefact
var merkle_root : str
-
Returns merkle root
Returns
str
- merkle root
Expand source code
@property def merkle_root(self) -> str: """Returns merkle root Returns: str: merkle root """ return self.merkle_tree.merkle_root
var merkle_tree : merklelib.merkle.MerkleTree
-
Returns merkle tree
Returns
MerkleTree
- merkle tree
Expand source code
@property def merkle_tree(self) -> MerkleTree: """Returns merkle tree Returns: MerkleTree: merkle tree """ # If merkle tree not available if not self._merkle_tree: # Build merkle tree and return it. return self.build_merkle_tree() return self._merkle_tree
var mydata_did : str
-
Returns did:mydata identifier
Returns
str
- did:mydata identifier
Expand source code
@property def mydata_did(self) -> str: """Returns did:mydata identifier Returns: str: did:mydata identifier """ # If did:mydata identifier not generated. if not self._mydata_did: # Generate did:mydata identifier return self.generate_did() return self._mydata_did
Methods
def base64(self) ‑> str
-
Returns output string after performing base64 encoding on JSON Canonicalisation Schema (JCS) on the document.
Returns
str
- base64 encoded string
Expand source code
def base64(self) -> str: """Returns output string after performing base64 encoding on JSON Canonicalisation Schema (JCS) on the document. Returns: str: base64 encoded string """ return base64.urlsafe_b64encode(self.jcs()).decode()
def build_merkle_tree(self) ‑> merklelib.merkle.MerkleTree
-
Build merkle tree from nquads statements about the artefact
Returns
MerkleTree
- merkle tree
Expand source code
def build_merkle_tree(self) -> MerkleTree: """Build merkle tree from nquads statements about the artefact Returns: MerkleTree: merkle tree """ # Normalise document to n-quads data = self.nquads() # Build merkle tree mt = MerkleTree(data) # Store the merkle tree in the instance self._merkle_tree = mt return mt
def generate_did(self, context_type='DataAgreement') ‑> str
-
Generate the did:mydata identifier for the agreement
Returns
did (str): did:mydata identifier
Expand source code
def generate_did(self, context_type="DataAgreement") -> str: """ Generate the did:mydata identifier for the agreement Returns: did (str): did:mydata identifier """ # Merkle tree mt = self.build_merkle_tree() # Merkle root (sha256 fingerprint) mr = mt.merkle_root # Obtain SHA2-256 fingerprint for agreement JSONLD context at = jsonld_context_fingerprint(context_type=context_type) # Create did:mydata v2 identifier mydata_did = DidMyData(agreement_type=at, agreement_merkle_root=mr) did = mydata_did.did # Store the did:mydata identifier in the instance self._mydata_did = did return did
def jcs(self) ‑> bytes
-
Canonicalise the agreement using JCS IETF RFC8785
Returns
bytes
- jcs bytes
Expand source code
def jcs(self) -> bytes: """Canonicalise the agreement using JCS IETF RFC8785 Returns: bytes: jcs bytes """ return jcs_rfc8785(self._artefact.serialize())
def nquads(self) ‑> List[str]
-
JSON-LD normalise document using URDNA2015. For reference: https://json-ld.github.io/normalization/spec/
Returns
typing.List[str]
- n-quads statements
Expand source code
def nquads(self) -> typing.List[str]: """JSON-LD normalise document using URDNA2015. For reference: https://json-ld.github.io/normalization/spec/ Returns: typing.List[str]: n-quads statements """ # Config for JSONLD normalisation config = {"algorithm": "URDNA2015", "format": "application/n-quads"} # Obtains the dictionary representation of the document doc = self._artefact.serialize() # Convert the doc to nquads statements normalized = jsonld.normalize(doc, config) # Split normalised string into multiple statements normalized = normalized.split("\n") # Return the statements return normalized[:-1]
class DidMyData (*, agreement_type: str, agreement_merkle_root: str)
-
Initialise the DidMydata class
Args
agreement_type (str): SHA2-256 fingerprint of the agreement JSONLD context agreement_merkle_root (str): SHA2-256 merkle root for the agreement document
Returns
None
Expand source code
class DidMyData: def __init__(self, *, agreement_type: str, agreement_merkle_root: str) -> None: """ Initialise the DidMydata class Args: agreement_type (str): SHA2-256 fingerprint of the agreement JSONLD context agreement_merkle_root (str): SHA2-256 merkle root for the agreement document Returns: None """ self._agreement_type = agreement_type self._agreement_merkle_root = agreement_merkle_root # Generate did:mydata v2 identifier self._did = self.generate() def generate(self) -> str: """Create did:mydata v2 identifier""" # Agreement type sha256 fingerprint to bytes agreement_type_bytes = binascii.unhexlify(self._agreement_type) # Agreement merkle root sha256 fingerprint to bytes agreement_merkle_root_bytes = binascii.unhexlify( self._agreement_merkle_root) # 16 + 38 bytes = 48 byte method specific identifier identifier = agreement_type_bytes[:16] + agreement_merkle_root_bytes # Multibase encode identifier = encode('base58btc', identifier).decode() return f"did:mydata:{identifier}" @property def did(self) -> str: return self._did
Instance variables
var did : str
-
Expand source code
@property def did(self) -> str: return self._did
Methods
def generate(self) ‑> str
-
Create did:mydata v2 identifier
Expand source code
def generate(self) -> str: """Create did:mydata v2 identifier""" # Agreement type sha256 fingerprint to bytes agreement_type_bytes = binascii.unhexlify(self._agreement_type) # Agreement merkle root sha256 fingerprint to bytes agreement_merkle_root_bytes = binascii.unhexlify( self._agreement_merkle_root) # 16 + 38 bytes = 48 byte method specific identifier identifier = agreement_type_bytes[:16] + agreement_merkle_root_bytes # Multibase encode identifier = encode('base58btc', identifier).decode() return f"did:mydata:{identifier}"