Skip to content

Commit

Permalink
Fix #16: Support custom cryptographic seed while creating/updating or…
Browse files Browse the repository at this point in the history
…ganisation for creating did:key identifier
  • Loading branch information
albinpa authored and georgepadayatti committed May 9, 2024
1 parent 054d707 commit 449acff
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 14 deletions.
30 changes: 30 additions & 0 deletions alembic/versions/9d0d8756d0e3_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""empty message
Revision ID: 9d0d8756d0e3
Revises: 3be60cbb77ee
Create Date: 2024-05-09 11:51:16.326563
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '9d0d8756d0e3'
down_revision: Union[str, None] = '3be60cbb77ee'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('organisation', sa.Column('cryptographic_salt', sa.String(length=500), nullable=True))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('organisation', 'cryptographic_salt')
# ### end Alembic commands ###
3 changes: 2 additions & 1 deletion eudi_wallet/ebsi/entry_points/server/decorators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import dataclasses
from functools import wraps
from typing import Optional, Tuple
import uuid

from aiohttp import web

Expand Down Expand Up @@ -191,7 +192,7 @@ async def wrapper(request):
raise web.HTTPBadRequest(text="Legal entity not found")
else:
await legal_entity_service.set_cryptographic_seed(
crypto_seed=legal_entity_entity.cryptographic_seed # type: ignore
crypto_seed=legal_entity_entity.cryptographic_seed, salt = legal_entity_entity.cryptographic_salt # type: ignore
)
await legal_entity_service.set_entity(
legal_entity_entity=legal_entity_entity
Expand Down
31 changes: 26 additions & 5 deletions eudi_wallet/ebsi/entry_points/server/routes/v2/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from typing import Optional, cast
import uuid

from aiohttp import web
from aiohttp.web_request import Request
Expand Down Expand Up @@ -58,7 +59,7 @@
CreateCredentialOfferError,
UpdateCredentialOfferError,
)
from eudi_wallet.ebsi.services.domain.utils.did import generate_and_store_did
from eudi_wallet.ebsi.services.domain.utils.did import generate_and_store_did_v2
from eudi_wallet.ebsi.utils.common import (
validate_data_attribute_schema_against_data_attribute_values,
)
Expand All @@ -68,11 +69,11 @@
)
from eudi_wallet.ebsi.usecases.v2.organisation.read_verification_request_usecase import (
ReadVerificationRequestUsecase,
ReadVerificationRequestUsecaseError
ReadVerificationRequestUsecaseError,
)
from eudi_wallet.ebsi.usecases.v2.organisation.delete_verification_request_usecase import (
DeleteVerificationRequestUsecase,
DeleteVerificationRequestUsecaseError
DeleteVerificationRequestUsecaseError,
)

from eudi_wallet.ebsi.usecases.v2.organisation.list_verification_request_usecase import (
Expand All @@ -90,8 +91,23 @@
async def handle_config_get_organisation_identifier(
request: Request, context: V2RequestContext
):
_, ebsi_did, key_did = await generate_and_store_did(
context.legal_entity_service.legal_entity_entity.cryptographic_seed
organisation_id = request.match_info.get("organisationId")
if organisation_id is None:
raise web.HTTPBadRequest(reason="Invalid organisation id")

if context.legal_entity_service.legal_entity_entity.cryptographic_salt is None:
usecase = UpdateOrganisationUsecase(
organisation_repository=context.organisation_repository,
logger=context.app_context.logger,
)
organisation = usecase.execute(
organisation_id=organisation_id,
name=context.legal_entity_service.legal_entity_entity.name,
cryptographic_salt=uuid.uuid4().hex,
)
_, ebsi_did, key_did = await generate_and_store_did_v2(
context.legal_entity_service.legal_entity_entity.cryptographic_seed,
salt=context.legal_entity_service.legal_entity_entity.cryptographic_salt,
)

resp = {
Expand All @@ -113,6 +129,7 @@ class RegisterOrganisationReq(BaseModel):
constr(min_length=1, max_length=500, strip_whitespace=True) # type: ignore
] = None
webhookUrl: Optional[HttpUrl] = None
cryptographicSeed: Optional[str] = None


@config_routes.post(
Expand Down Expand Up @@ -146,6 +163,7 @@ async def handle_config_post_register_organisation(
cover_image_url=cover_image_url,
webhook_url=webhook_url,
location=register_organisation_req.location,
cryptographic_seed=register_organisation_req.cryptographicSeed,
)

return web.json_response(organisation.to_dict())
Expand Down Expand Up @@ -199,6 +217,7 @@ class UpdateOrganisationReq(BaseModel):
constr(min_length=1, max_length=500, strip_whitespace=True) # type: ignore
] = None
webhookUrl: Optional[HttpUrl] = None
cryptographicSeed: Optional[str] = None


@config_routes.put(
Expand Down Expand Up @@ -226,6 +245,7 @@ async def handle_config_put_update_organisation(
logo_url = str(update_organisation_req.logoUrl)
cover_image_url = str(update_organisation_req.coverImageUrl)
webhook_url = str(update_organisation_req.webhookUrl)
cryptographic_seed = update_organisation_req.cryptographicSeed
organisation = usecase.execute(
organisation_id=organisation_id,
name=update_organisation_req.name,
Expand All @@ -234,6 +254,7 @@ async def handle_config_put_update_organisation(
cover_image_url=cover_image_url,
webhook_url=webhook_url,
location=update_organisation_req.location,
cryptographic_seed=cryptographic_seed,
)
if not organisation:
raise web.HTTPBadRequest(reason="Organisation not found")
Expand Down
1 change: 1 addition & 0 deletions eudi_wallet/ebsi/models/organisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class OrganisationModel(Base):
description = Column(String(length=500), nullable=True)
logo_url = Column(Text, nullable=True)
cryptographic_seed = Column(String(length=500), nullable=False)
cryptographic_salt = Column(String(length=500), nullable=True,default=uuid.uuid4().hex)
role = Column(String(length=200), nullable=False)
location = Column(String(length=100), nullable=True)
cover_image_url = Column(Text, nullable=True)
Expand Down
17 changes: 10 additions & 7 deletions eudi_wallet/ebsi/services/application/v2_organisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
from eudi_wallet.ebsi.services.domain.utils.credential import (
create_credential_token,
)
from eudi_wallet.ebsi.services.domain.utils.did import generate_and_store_did
from eudi_wallet.ebsi.services.domain.utils.did import generate_and_store_did_v2
from eudi_wallet.ebsi.utils.date_time import generate_ISO8601_UTC
from eudi_wallet.ebsi.utils.jwt import decode_header_and_claims_in_jwt
from eudi_wallet.ebsi.value_objects.application.organisation import (
Expand Down Expand Up @@ -125,10 +125,11 @@ async def get_legal_entity(
with self.legal_entity_repository as repo:
return repo.get_by_id(id=organisation_id)

async def set_cryptographic_seed(self, crypto_seed: str) -> None:
async def set_cryptographic_seed(self, crypto_seed: str, salt: str) -> None:
self.crypto_seed = crypto_seed
self.eth, self.ebsi_did, self.key_did = await generate_and_store_did(
crypto_seed

self.eth, self.ebsi_did, self.key_did = await generate_and_store_did_v2(
crypto_seed=self.crypto_seed, salt=salt
)

async def set_entity(
Expand Down Expand Up @@ -399,9 +400,11 @@ async def get_credential_offer_without_data_agreement(
"credentials": [
{
"format": format,
"types": credential.get("type")
if credential.get("type")
else ["VerifiableCredential"],
"types": (
credential.get("type")
if credential.get("type")
else ["VerifiableCredential"]
),
"trust_framework": {
"name": "ebsi",
"type": "Accreditation",
Expand Down
29 changes: 29 additions & 0 deletions eudi_wallet/ebsi/services/domain/utils/did.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import typing
import hashlib

from eudi_wallet.did_key import KeyDid, PublicKeyJWK
from eudi_wallet.ebsi_did import EbsiDid
Expand Down Expand Up @@ -27,3 +28,31 @@ async def generate_and_store_did(
key_did.generate_did(public_key_jwk)

return eth, ebsi_did, key_did


async def generate_and_store_did_v2(
crypto_seed: str,
salt: str = None,
) -> typing.Tuple[Ethereum, EbsiDid, KeyDid]:
if salt is not None:
crypto_seed = hashlib.sha256((crypto_seed + salt).encode("utf-8")).digest()
else:
crypto_seed = crypto_seed.encode("utf-8")

# Generate EBSI DID for legal entity
eth = Ethereum(seed=crypto_seed)
ebsi_did = EbsiDid(seed=crypto_seed)
ebsi_did.generate_did(eth=eth)

# Generate EBSI DID for natural person
key_did = KeyDid(seed=crypto_seed)
key_did.create_keypair()
public_key_jwk = PublicKeyJWK(
kty=key_did.public_key_jwk["kty"],
crv=key_did.public_key_jwk["crv"],
x=key_did.public_key_jwk["x"],
y=key_did.public_key_jwk["y"],
)
key_did.generate_did(public_key_jwk)

return eth, ebsi_did, key_did
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ def execute(
cover_image_url: Optional[str] = None,
webhook_url: Optional[str] = None,
location: Optional[str] = None,
cryptographic_seed: Optional[str] = None,
) -> OrganisationModel:
# Create an organistion in db
with self.organisation_repository as repo:
# mnemo = Mnemonic("english")
# seed_phrase = mnemo.generate(strength=256)
cryptographic_seed = str(time.time())
if cryptographic_seed is None:
cryptographic_seed = str(time.time())
return repo.create(
name=name,
cryptographic_seed=cryptographic_seed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ def execute(
cover_image_url: Optional[str] = None,
webhook_url: Optional[str] = None,
location: Optional[str] = None,
cryptographic_seed: Optional[str] = None,
cryptographic_salt: Optional[str] = None,
) -> OrganisationModel:
# Update an organisation
with self.organisation_repository as repo:
Expand All @@ -32,4 +34,6 @@ def execute(
cover_image_url=cover_image_url,
webhook_url=webhook_url,
location=location,
cryptographic_seed=cryptographic_seed,
cryptographic_salt=cryptographic_salt,
)

0 comments on commit 449acff

Please sign in to comment.