Skip to content

Commit

Permalink
Add anoncreds issuance and presentation support [DEV-4592] (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaevMithran authored Nov 29, 2024
2 parents dd52607 + af93961 commit ebf67a6
Show file tree
Hide file tree
Showing 106 changed files with 4,503 additions and 1,170 deletions.
6 changes: 3 additions & 3 deletions acapy_agent/anoncreds/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
from ..config.injection_context import InjectionContext
from ..core.error import BaseError
from ..core.profile import Profile
from .models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult
from .models.anoncreds_revocation import (
from .models.credential_definition import CredDef, CredDefResult, GetCredDefResult
from .models.revocation import (
GetRevListResult,
GetRevRegDefResult,
RevList,
RevListResult,
RevRegDef,
RevRegDefResult,
)
from .models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult
from .models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult

T = TypeVar("T")

Expand Down
33 changes: 11 additions & 22 deletions acapy_agent/anoncreds/default/did_cheqd/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,33 @@
BaseAnonCredsResolver,
AnonCredsRegistrationError,
)
from ...models.anoncreds_cred_def import (
from ...models.credential_definition import (
CredDef,
CredDefResult,
GetCredDefResult,
CredDefState,
CredDefValue,
)
from ...models.anoncreds_revocation import (
from ...models.revocation import (
GetRevListResult,
GetRevRegDefResult,
RevList,
RevListResult,
RevRegDef,
RevRegDefResult,
)
from ...models.anoncreds_schema import (
from ...models.schema import (
AnonCredsSchema,
GetSchemaResult,
SchemaResult,
SchemaState,
)
from ....did.cheqd.cheqd_manager import DidCheqdManager
from ....did.cheqd.manager import DidCheqdManager
from ....did.cheqd.registrar import DidCheqdRegistrar
from ....resolver.default.cheqd import CheqdDIDResolver
from ....messaging.valid import CheqdDID
from ....wallet.base import BaseWallet
from ....wallet.jwt import dict_to_b64
from ....wallet.util import b64_to_bytes, bytes_to_b64

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -310,30 +309,20 @@ async def _create_and_publish_resource(

LOGGER.debug("JOBID %s", job_id)
if resource_state.get("state") == "action":
sign_req: dict = resource_state.get("signingRequest")[0]
kid: str = sign_req.get("kid")
payload_to_sign: str = sign_req.get("serializedPayload")
key = await wallet.get_key_by_kid(kid)
verkey = key.verkey

# sign payload
signature_bytes = await wallet.sign_message(
b64_to_bytes(payload_to_sign), verkey
signing_requests: dict = resource_state.get("signingRequest")
if not signing_requests:
raise Exception("No signing requests available for update.")
# sign all requests
signed_responses = await DidCheqdManager.sign_requests(
wallet, signing_requests
)

# publish resource
publish_resource_res = await cheqd_manager.registrar.create_resource(
did,
{
"jobId": job_id,
"secret": {
"signingResponse": [
{
"kid": kid,
"signature": bytes_to_b64(signature_bytes),
}
],
},
"secret": {"signingResponse": signed_responses},
},
)
resource_state = publish_resource_res.get("resourceState")
Expand Down
Empty file.
33 changes: 33 additions & 0 deletions acapy_agent/anoncreds/default/did_cheqd/tests/test_registry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from unittest.async_case import IsolatedAsyncioTestCase

import pytest
from acapy_agent.utils.testing import create_test_profile
from .....messaging.valid import CHEQD_DID_VALIDATE
from .....anoncreds.default.did_cheqd import registry as test_module

TEST_CHEQD_DID = "did:cheqd:testnet:1686a962-6e82-46f3-bde7-e6711d63958c"
TEST_CHEQD_SCHEMA_ID = "did:cheqd:testnet:1686a962-6e82-46f3-bde7-e6711d63958c/resources/e788d345-dd0c-427a-a74b-27faf1e608cd"
TEST_CHEQD_CRED_DEF_ID = "did:cheqd:testnet:1686a962-6e82-46f3-bde7-e6711d63958c/resources/02229804-b46a-4be9-a6f1-13869109c7ea"
TEST_CHEQD_REV_REG_ENTRY = "did:cheqd:testnet:1686a962-6e82-46f3-bde7-e6711d63958c?resourceName=test&resourceType=anoncredsRevRegEntry"


@pytest.mark.anoncreds
class TestCheqdRegistry(IsolatedAsyncioTestCase):
async def asyncSetUp(self):
self.profile = await create_test_profile(
settings={"wallet.type": "askar-anoncreds"},
)
self.registry = test_module.DIDCheqdRegistry()

async def test_supported_did_regex(self):
"""Test the supported_did_regex."""

assert self.registry.supported_identifiers_regex == CHEQD_DID_VALIDATE.PATTERN
assert bool(self.registry.supported_identifiers_regex.match(TEST_CHEQD_DID))
assert bool(self.registry.supported_identifiers_regex.match(TEST_CHEQD_SCHEMA_ID))
assert bool(
self.registry.supported_identifiers_regex.match(TEST_CHEQD_CRED_DEF_ID)
)
assert bool(
self.registry.supported_identifiers_regex.match(TEST_CHEQD_REV_REG_ENTRY)
)
6 changes: 3 additions & 3 deletions acapy_agent/anoncreds/default/did_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
from ....config.injection_context import InjectionContext
from ....core.profile import Profile
from ...base import BaseAnonCredsRegistrar, BaseAnonCredsResolver
from ...models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult
from ...models.anoncreds_revocation import (
from ...models.credential_definition import CredDef, CredDefResult, GetCredDefResult
from ...models.revocation import (
GetRevListResult,
GetRevRegDefResult,
RevList,
RevListResult,
RevRegDef,
RevRegDefResult,
)
from ...models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult
from ...models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult

LOGGER = logging.getLogger(__name__)

Expand Down
6 changes: 3 additions & 3 deletions acapy_agent/anoncreds/default/did_web/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
from ....config.injection_context import InjectionContext
from ....core.profile import Profile
from ...base import BaseAnonCredsRegistrar, BaseAnonCredsResolver
from ...models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult
from ...models.anoncreds_revocation import (
from ...models.credential_definition import CredDef, CredDefResult, GetCredDefResult
from ...models.revocation import (
GetRevListResult,
GetRevRegDefResult,
RevList,
RevListResult,
RevRegDef,
RevRegDefResult,
)
from ...models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult
from ...models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult


class DIDWebRegistry(BaseAnonCredsResolver, BaseAnonCredsRegistrar):
Expand Down
2 changes: 1 addition & 1 deletion acapy_agent/anoncreds/default/legacy_indy/recover.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import indy_vdr
from anoncreds import RevocationRegistry, RevocationRegistryDefinition

from ...models.anoncreds_revocation import RevList
from ...models.revocation import RevList

LOGGER = logging.getLogger(__name__)

Expand Down
6 changes: 3 additions & 3 deletions acapy_agent/anoncreds/default/legacy_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@
)
from ...events import RevListFinishedEvent
from ...issuer import CATEGORY_CRED_DEF, AnonCredsIssuer, AnonCredsIssuerError
from ...models.anoncreds_cred_def import (
from ...models.credential_definition import (
CredDef,
CredDefResult,
CredDefState,
CredDefValue,
GetCredDefResult,
)
from ...models.anoncreds_revocation import (
from ...models.revocation import (
GetRevListResult,
GetRevRegDefResult,
RevList,
Expand All @@ -74,7 +74,7 @@
RevRegDefState,
RevRegDefValue,
)
from ...models.anoncreds_schema import (
from ...models.schema import (
AnonCredsSchema,
GetSchemaResult,
SchemaResult,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
import pytest
from anoncreds import RevocationRegistryDefinition

from acapy_agent.tests import mock

from ....models.anoncreds_revocation import RevList, RevRegDef, RevRegDefValue
from .....tests import mock
from ....models.revocation import RevList, RevRegDef, RevRegDefValue
from ..recover import (
RevocRecoveryException,
_check_tails_hash_for_inconsistency,
Expand Down
34 changes: 15 additions & 19 deletions acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,6 @@
from .....anoncreds.base import AnonCredsSchemaAlreadyExists
from .....anoncreds.default.legacy_indy import registry as test_module
from .....anoncreds.issuer import AnonCredsIssuer
from .....anoncreds.models.anoncreds_cred_def import (
CredDef,
CredDefResult,
CredDefValue,
CredDefValuePrimary,
)
from .....anoncreds.models.anoncreds_revocation import (
RevList,
RevListResult,
RevRegDef,
RevRegDefResult,
RevRegDefState,
RevRegDefValue,
)
from .....anoncreds.models.anoncreds_schema import (
AnonCredsSchema,
GetSchemaResult,
SchemaResult,
)
from .....askar.profile_anon import (
AskarAnoncredsProfileSession,
)
Expand All @@ -55,6 +36,21 @@
)
from .....tests import mock
from .....utils.testing import create_test_profile
from ....models.credential_definition import (
CredDef,
CredDefResult,
CredDefValue,
CredDefValuePrimary,
)
from ....models.revocation import (
RevList,
RevListResult,
RevRegDef,
RevRegDefResult,
RevRegDefState,
RevRegDefValue,
)
from ....models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult

B58 = alphabet if isinstance(alphabet, str) else alphabet.decode("ascii")
INDY_DID = rf"^(did:sov:)?[{B58}]{{21,22}}$"
Expand Down
2 changes: 1 addition & 1 deletion acapy_agent/anoncreds/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import NamedTuple, Optional

from ..core.event_bus import Event
from .models.anoncreds_revocation import RevRegDef
from .models.revocation import RevRegDef

CRED_DEF_FINISHED_EVENT = "anoncreds::credential-definition::finished"
REV_REG_DEF_FINISHED_EVENT = "anoncreds::revocation-registry-definition::finished"
Expand Down
27 changes: 6 additions & 21 deletions acapy_agent/anoncreds/holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import asyncio
import json
import logging
import re
from typing import Dict, Optional, Sequence, Tuple, Union

from anoncreds import (
Expand All @@ -23,7 +22,6 @@
from pyld.jsonld import JsonLdProcessor
from uuid_utils import uuid4

from ..anoncreds.models.anoncreds_schema import AnonCredsSchema
from ..askar.profile_anon import AskarAnoncredsProfile
from ..core.error import BaseError
from ..core.profile import Profile
Expand All @@ -33,7 +31,8 @@
from ..vc.vc_ld import VerifiableCredential
from ..wallet.error import WalletNotFoundError
from .error_messages import ANONCREDS_PROFILE_REQUIRED_MSG
from .models.anoncreds_cred_def import CredDef
from .models.credential_definition import CredDef
from .models.schema import AnonCredsSchema
from .registry import AnonCredsRegistry

LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -150,8 +149,8 @@ async def create_credential_request(
) = await asyncio.get_event_loop().run_in_executor(
None,
CredentialRequest.create,
None,
holder_did,
None,
credential_definition.to_native(),
secret,
AnonCredsHolder.MASTER_SECRET_ID,
Expand Down Expand Up @@ -231,25 +230,11 @@ async def _finish_store_credential(
rev_reg_def: Optional[dict] = None,
) -> str:
credential_data = cred_recvd.to_dict()
schema_id = cred_recvd.schema_id
schema_id_parts = re.match(r"^(\w+):2:([^:]+):([^:]+)$", schema_id)
if not schema_id_parts:
raise AnonCredsHolderError(f"Error parsing credential schema ID: {schema_id}")
cred_def_id = cred_recvd.cred_def_id
cdef_id_parts = re.match(r"^(\w+):3:CL:([^:]+):([^:]+)$", cred_def_id)
if not cdef_id_parts:
raise AnonCredsHolderError(
f"Error parsing credential definition ID: {cred_def_id}"
)

credential_id = credential_id or str(uuid4())
tags = {
"schema_id": schema_id,
"schema_issuer_did": schema_id_parts[1],
"schema_name": schema_id_parts[2],
"schema_version": schema_id_parts[3],
"issuer_did": cdef_id_parts[1],
"cred_def_id": cred_def_id,
"schema_id": cred_recvd.schema_id,
"issuer_did": credential_definition["issuerId"],
"cred_def_id": cred_recvd.cred_def_id,
"rev_reg_id": cred_recvd.rev_reg_id or "None",
}

Expand Down
4 changes: 2 additions & 2 deletions acapy_agent/anoncreds/issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
from .base import AnonCredsSchemaAlreadyExists, BaseAnonCredsError
from .error_messages import ANONCREDS_PROFILE_REQUIRED_MSG
from .events import CredDefFinishedEvent
from .models.anoncreds_cred_def import CredDef, CredDefResult
from .models.anoncreds_schema import AnonCredsSchema, SchemaResult, SchemaState
from .models.credential_definition import CredDef, CredDefResult
from .models.schema import AnonCredsSchema, SchemaResult, SchemaState
from .registry import AnonCredsRegistry

LOGGER = logging.getLogger(__name__)
Expand Down
Loading

0 comments on commit ebf67a6

Please sign in to comment.