Skip to content

Commit

Permalink
feat: add resolve_peer3 method
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Bluhm <[email protected]>
  • Loading branch information
dbluhm committed Oct 23, 2023
1 parent 5220b60 commit a2ee5c4
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 18 deletions.
76 changes: 59 additions & 17 deletions did_peer_2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
from enum import Enum
import json
import re
from typing import Any, Dict, List, Sequence
from typing import Any, Dict, List, Optional, Sequence, Tuple
from hashlib import sha256


# Regex
B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
PATTERN = re.compile(rf"^did:peer:2(\.[AEVIDS]z[{B58}]{46}|\.+[A-Za-z0-9_-]+)+$")
PATTERN = re.compile(rf"^did:peer:2(\.[AEVID]z[{B58}]+|\.S[A-Za-z0-9_-]+)+$")
PEER3_PATTERN = re.compile(rf"^did:peer:3zQm[{B58}]{{44}}$")

# Multiformats
MULTIBASE_BASE58_BTC = "z"
Expand Down Expand Up @@ -204,29 +205,36 @@ def generate(keys: Sequence[KeySpec], services: Sequence[Dict[str, Any]]):
return f"did:peer:2{enocded_keys}{encoded_services}"


def resolve(did: str) -> Dict[str, Any]:
"""Resolve a did:peer:2 DID."""
if not PATTERN.match(did):
raise ValueError(f"Invalid did:peer:2: {did}")

document = {}
document["@context"] = [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1",
]
document["id"] = did

def _get_elements(did: str) -> Tuple[List[KeySpec], List[Dict[str, Any]]]:
"""Get the elements of a did:peer:2 DID."""
elements = did.split(".")[1:]

keys: List[KeySpec] = []
services: List[Dict[str, Any]] = []
service_encoder = ServiceEncoder()
services: List[Dict[str, Any]] = []

for element in elements:
purpose = PurposeCode(element[0])
value = element[1:]
if purpose in PurposeCode.key_purposes():
keys.append(KeySpec(purpose, element[1:]))
keys.append(KeySpec(purpose, value))
else:
assert purpose == PurposeCode.service
services.append(service_encoder.decode_service(element[1:]))
services.append(service_encoder.decode_service(value))

return keys, services


def _elements_to_document(
did: str, keys: List[KeySpec], services: List[Dict[str, Any]]
):
"""Construct a DID Document from the given did, keys, and services."""
document = {}
document["@context"] = [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1",
]
document["id"] = did

for index, key in enumerate(keys, start=1):
verification_method = {
Expand All @@ -250,6 +258,16 @@ def resolve(did: str) -> Dict[str, Any]:
unidentified_index += 1
document.setdefault("service", []).append(service)

return document


def resolve(did: str) -> Dict[str, Any]:
"""Resolve a did:peer:2 DID."""
if not PATTERN.match(did):
raise ValueError(f"Invalid did:peer:2: {did}")

keys, services = _get_elements(did)
document = _elements_to_document(did, keys, services)
document["alsoKnownAs"] = [peer2to3(did)]

return document
Expand All @@ -262,3 +280,27 @@ def peer2to3(did: str) -> str:

raw = MULTIHASH_SHA256 + sha256(did[10:].encode()).digest()
return "did:peer:3" + MULTIBASE_BASE58_BTC + b58encode(raw).decode()


def resolve_peer3(peer2: str, peer3: Optional[str] = None) -> Dict[str, Any]:
"""Resolve a did:peer:3 document from a did:peer:2 DID."""
if not PATTERN.match(peer2):
raise ValueError(f"Invalid did:peer:2: {peer2}")

if peer3 is None:
peer3 = peer2to3(peer2)
else:
if not PEER3_PATTERN.match(peer3):
raise ValueError(f"Invalid did:peer:3: {peer3}")

computed = peer2to3(peer2)
if computed != peer3:
raise ValueError(
f"did:peer:3 did does not match computed did: {peer3} != {computed}"
)

keys, services = _get_elements(peer2)
document = _elements_to_document(peer3, keys, services)
document["alsoKnownAs"] = [peer2]

return document
9 changes: 8 additions & 1 deletion tests/test_did_peer_2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from did_peer_2 import generate, peer2to3, resolve, KeySpec
from did_peer_2 import generate, peer2to3, resolve, KeySpec, resolve_peer3

# ruff: noqa: E501

Expand Down Expand Up @@ -84,3 +84,10 @@ def test_2_to_3():
did = "did:peer:2.Ez6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc.Vz6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V.Vz6MkgoLTnTypo3tDRwCkZXSccTPHRLhF4ZnjhueYAFpEX6vg.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9lbmRwb2ludCIsInIiOlsiZGlkOmV4YW1wbGU6c29tZW1lZGlhdG9yI3NvbWVrZXkiXSwiYSI6WyJkaWRjb21tL3YyIiwiZGlkY29tbS9haXAyO2Vudj1yZmM1ODciXX0"
as3 = peer2to3(did)
assert as3 == "did:peer:3zQmS19jtYDvGtKVrJhQnRFpBQAx3pJ9omx2HpNrcXFuRCz9"


def test_resolve_3():
did = "did:peer:2.Ez6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc.Vz6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V.Vz6MkgoLTnTypo3tDRwCkZXSccTPHRLhF4ZnjhueYAFpEX6vg.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9lbmRwb2ludCIsInIiOlsiZGlkOmV4YW1wbGU6c29tZW1lZGlhdG9yI3NvbWVrZXkiXSwiYSI6WyJkaWRjb21tL3YyIiwiZGlkY29tbS9haXAyO2Vudj1yZmM1ODciXX0"
as3 = peer2to3(did)
doc = resolve_peer3(did, as3)
assert doc

0 comments on commit a2ee5c4

Please sign in to comment.