Skip to content

Commit

Permalink
Merge pull request #9 from decentralized-identity/feature/jwk-keyspec
Browse files Browse the repository at this point in the history
feat: add input doc helpers for jwk
  • Loading branch information
Frostyfrog authored Jan 31, 2024
2 parents e46fc5b + 64314a3 commit a4a26de
Show file tree
Hide file tree
Showing 9 changed files with 390 additions and 197 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/code-quality-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: psf/black@stable
- uses: psf/black@24.1.1
- uses: chartboost/ruff-action@v1
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ repos:
args: ["--config", ".commitlint.config.js"]
additional_dependencies: ['@commitlint/config-conventional']
- repo: https://github.com/psf/black
rev: 23.7.0
rev: 24.1.1
hooks:
- id: black
stages: [commit]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.284
rev: v0.1.2
hooks:
- id: ruff
stages: [commit]
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ did:peer:4zQmb7xLdVY9TXx8oov5XgpGUmGELgqiAV2699s43i6Qdm3M:zQSJgiFTYiCHjQ9MktwNTh
```python
>>> import json
>>> from did_peer_4 import encode, resolve
>>> from did_peer_4.input_doc import input_doc_from_keys_and_services, KeySpec
>>> key1 = KeySpec(
>>> from did_peer_4.input_doc import input_doc_from_keys_and_services, Multikey
>>> key1 = Multikey(
... multikey="z6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V",
... relationships=["authentication", "capabilityDelegation"],
... )
>>> key2 = KeySpec(
>>> key2 = Multikey(
... multikey="z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc",
... relationships=["keyAgreement"],
... )
Expand Down
86 changes: 72 additions & 14 deletions did_peer_4/input_doc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Helpers for creating input documents for the DID method."""
from dataclasses import dataclass
from typing import Any, Dict, Literal, Optional, Sequence

import warnings
from dataclasses import dataclass, field
from typing import Any, Dict, Literal, Optional, Protocol, Sequence

RELATIONSHIPS = (
"authentication",
Expand All @@ -21,33 +23,89 @@

@dataclass
class KeySpec:
"""Key specification."""
"""DEPRECATED: Key specification.
Use Multikey or JsonWebKey2020 instead.
"""

multikey: str
relationships: Optional[Sequence[Relationship]] = None
ident: Optional[str] = None
type: str = "Multikey"
context: str = "https://w3id.org/security/multikey/v1"


@dataclass
class Multikey:
"""Multikey specification."""

type: str = field(init=False, default="Multikey")
context: str = field(init=False, default="https://w3id.org/security/multikey/v1")

multikey: str
relationships: Optional[Sequence[Relationship]] = None
ident: Optional[str] = None
type: Optional[str] = None


@dataclass
class JsonWebKey2020:
"""JsonWebKey2020 specification."""

type: str = field(init=False, default="JsonWebKey2020")
context: str = field(
init=False, default="https://w3id.org/security/suites/jws-2020/v1"
)

jwk: dict
relationships: Optional[Sequence[Relationship]] = None
ident: Optional[str] = None


class KeyProtocol(Protocol):
"""Key protocol for keys that can be used in input documents."""

type: str
context: str
relationships: Optional[Sequence[Relationship]]
ident: Optional[str]


def input_doc_from_keys_and_services(
keys: Sequence[KeySpec], services: Optional[Sequence[dict]] = None
keys: Sequence[KeyProtocol], services: Optional[Sequence[dict]] = None
) -> dict:
"""Create an input document for a set of keys and services."""
input_doc: Dict[str, Any] = {
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1",
]
}
for index, key in enumerate(keys):
ident = f"#key-{index}"
input_doc.setdefault("verificationMethod", []).append(
{
"id": key.ident or ident,
"type": key.type or "Multikey",
"publicKeyMultibase": key.multikey,
}
)
if isinstance(key, KeySpec):
warnings.warn(
"KeySpec is deprecated and will be removed in a future version; "
"use Multikey or JsonWebKey2020 instead",
DeprecationWarning,
)
prop, material = "publicKeyMultibase", key.multikey
elif isinstance(key, Multikey):
prop, material = "publicKeyMultibase", key.multikey
elif isinstance(key, JsonWebKey2020):
prop, material = "publicKeyJwk", key.jwk
else:
raise TypeError(f"Unknown key type: {key}")

ident = key.ident or f"#key-{index}"
vm: Dict[str, Any] = {
"id": ident,
"type": key.type,
prop: material,
}

input_doc.setdefault("verificationMethod", []).append(vm)

if key.context not in input_doc["@context"]:
input_doc["@context"].append(key.context)

for relationship in key.relationships or []:
if relationship not in RELATIONSHIPS:
raise ValueError(f"Invalid relationship: {relationship}")
Expand Down
1 change: 1 addition & 0 deletions did_peer_4/valid.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Validate input documents."""

from typing import Any, Mapping


Expand Down
Loading

0 comments on commit a4a26de

Please sign in to comment.