From cb9ef0b608c1067a89b0c5a70342f5b74adbbecf Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Sat, 6 Jan 2024 19:18:59 +0100 Subject: [PATCH] fix issue dids and credentials --- idhub/admin/views.py | 4 +- idhub/management/commands/initial_datas.py | 15 +++----- idhub/models.py | 44 +++++++++------------- idhub/user/forms.py | 4 +- idhub/user/views.py | 25 +++++++++++- idhub/views.py | 16 ++++---- idhub_auth/models.py | 18 +++------ trustchain_idhub/settings.py | 1 + 8 files changed, 68 insertions(+), 59 deletions(-) diff --git a/idhub/admin/views.py b/idhub/admin/views.py index b6dcbc8..634ec0b 100644 --- a/idhub/admin/views.py +++ b/idhub/admin/views.py @@ -17,6 +17,7 @@ from django.views.generic.edit import ( UpdateView, ) from django.shortcuts import get_object_or_404, redirect +from django.core.cache import cache from django.urls import reverse_lazy from django.http import HttpResponse from django.contrib import messages @@ -645,13 +646,14 @@ class DidRegisterView(Credentials, CreateView): def form_valid(self, form): form.instance.user = self.request.user - form.instance.set_did() + form.instance.set_did(cache.get("KEY_DIDS")) form.save() messages.success(self.request, _('DID created successfully')) Event.set_EV_ORG_DID_CREATED_BY_ADMIN(form.instance) return super().form_valid(form) + class DidEditView(Credentials, UpdateView): template_name = "idhub/admin/did_register.html" subtitle = _('Organization Identities (DID)') diff --git a/idhub/management/commands/initial_datas.py b/idhub/management/commands/initial_datas.py index 8481a81..0d8e0a2 100644 --- a/idhub/management/commands/initial_datas.py +++ b/idhub/management/commands/initial_datas.py @@ -37,7 +37,6 @@ class Command(BaseCommand): self.create_organizations(r[0].strip(), r[1].strip()) self.sync_credentials_organizations("pangea.org", "somconnexio.coop") self.sync_credentials_organizations("local 8000", "local 9000") - self.create_defaults_dids() self.create_schemas() def create_admin_users(self, email, password): @@ -47,6 +46,7 @@ class Command(BaseCommand): key = su.decrypt_sensitive_data(password) key_dids = {su.id: key} cache.set("KEY_DIDS", key_dids, None) + self.create_defaults_dids(su, key) def create_users(self, email, password): @@ -54,10 +54,8 @@ class Command(BaseCommand): u.set_password(password) u.set_encrypted_sensitive_data(password) u.save() - key_dids = cache.get("KEY_DIDS", {}) key = u.decrypt_sensitive_data(password) - key_dids.update({u.id: key}) - cache.set("KEY_DIDS", key_dids) + self.create_defaults_dids(u, key) def create_organizations(self, name, url): @@ -73,11 +71,10 @@ class Command(BaseCommand): org1.save() org2.save() - def create_defaults_dids(self): - for u in User.objects.all(): - did = DID(label="Default", user=u) - did.set_did() - did.save() + def create_defaults_dids(self, u, password): + did = DID(label="Default", user=u) + did.set_did(password) + did.save() def create_schemas(self): schemas_files = os.listdir(settings.SCHEMAS_DIR) diff --git a/idhub/models.py b/idhub/models.py index c0e237a..dee615f 100644 --- a/idhub/models.py +++ b/idhub/models.py @@ -3,6 +3,7 @@ import pytz import datetime from django.db import models from django.conf import settings +from django.core.cache import cache from django.template.loader import get_template from django.utils.translation import gettext_lazy as _ from nacl import secret @@ -419,25 +420,19 @@ class DID(models.Model): null=True, ) - def get_key_material(self): - return self.user.decrypt_data(self.key_material) + def get_key_material(self, password): + return self.user.decrypt_data(self.key_material, password) - def set_key_material(self, value): - self.key_material = self.user.encrypt_data(value) + def set_key_material(self, value, password): + self.key_material = self.user.encrypt_data(value, password) - def get_data(self): - return self.user.decrypt_data(self.data) - - def set_data(self, value): - self.data = self.user.encrypt_data(value) - @property def is_organization_did(self): if not self.user: return True return False - def set_did(self): + def set_did(self, password): """ Generates a new DID Controller Key and derives a DID from it. Because DID Controller Keys are stored encrypted using a User's Sensitive Data Encryption Key, @@ -445,12 +440,7 @@ class DID(models.Model): """ new_key_material = generate_did_controller_key() self.did = keydid_from_controller_key(new_key_material) - self.set_key_material(new_key_material) - - - # TODO: darmengo: esta funcion solo se llama desde un fichero que sube cosas a s3 (??) Preguntar a ver que hace. - def get_key_deprecated(self): - return json.loads(self.key_material) + self.set_key_material(new_key_material, password) class Schemas(models.Model): @@ -514,11 +504,13 @@ class VerificableCredential(models.Model): related_name='vcredentials', ) - def get_data(self): - return self.user.decrypt_data(self.data) + def get_data(self, password): + if not self.data: + return "" + return self.user.decrypt_data(self.data, password) - def set_data(self, value): - self.data = self.user.encrypt_data(value) + def set_data(self, value, password): + self.data = self.user.encrypt_data(value, password) def type(self): return self.schema.type @@ -536,19 +528,19 @@ class VerificableCredential(models.Model): data = json.loads(self.csv_data).items() return data - def issue(self, did): + def issue(self, did, password): if self.status == self.Status.ISSUED: return - # self.status = self.Status.ISSUED - import pdb; pdb.set_trace() + self.status = self.Status.ISSUED self.subject_did = did self.issued_on = datetime.datetime.now().astimezone(pytz.utc) + issuer_pass = cache.get("KEY_DIDS") data = sign_credential( self.render(), - self.issuer_did.get_key_material() + self.issuer_did.get_key_material(issuer_pass) ) - self.data = self.user.encrypt_data(data) + self.data = self.user.encrypt_data(data, password) def get_context(self): d = json.loads(self.csv_data) diff --git a/idhub/user/forms.py b/idhub/user/forms.py index 5ac04ad..efe9ad4 100644 --- a/idhub/user/forms.py +++ b/idhub/user/forms.py @@ -22,6 +22,7 @@ class RequestCredentialForm(forms.Form): def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', None) + self.password = kwargs.pop('password', None) super().__init__(*args, **kwargs) self.fields['did'].choices = [ (x.did, x.label) for x in DID.objects.filter(user=self.user) @@ -49,7 +50,8 @@ class RequestCredentialForm(forms.Form): did = did[0] cred = cred[0] try: - cred.issue(did) + if self.password: + cred.issue(did, self.password) except Exception: return diff --git a/idhub/user/views.py b/idhub/user/views.py index 0a273ec..dc83377 100644 --- a/idhub/user/views.py +++ b/idhub/user/views.py @@ -120,7 +120,15 @@ class CredentialJsonView(MyWallet, TemplateView): pk=pk, user=self.request.user ) - response = HttpResponse(self.object.get_data(), content_type="application/json") + pass_enc = self.request.session.get("key_did") + data = "" + if pass_enc: + user_pass = self.request.user.decrypt_data( + pass_enc, + self.request.user.password+self.request.session._session_key + ) + data = self.object.get_data(user_pass) + response = HttpResponse(data, content_type="application/json") response['Content-Disposition'] = 'attachment; filename={}'.format("credential.json") return response @@ -135,6 +143,15 @@ class CredentialsRequestView(MyWallet, FormView): def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['user'] = self.request.user + pass_enc = self.request.session.get("key_did") + if pass_enc: + user_pass = self.request.user.decrypt_data( + pass_enc, + self.request.user.password+self.request.session._session_key + ) + else: + pass_enc = None + kwargs['password'] = user_pass return kwargs def form_valid(self, form): @@ -205,7 +222,11 @@ class DidRegisterView(MyWallet, CreateView): def form_valid(self, form): form.instance.user = self.request.user - form.instance.set_did() + pw = self.request.user.decrypt_data( + self.request.session.get("key_did"), + self.request.user.password+self.request.session._session_key + ) + form.instance.set_did(pw) form.save() messages.success(self.request, _('DID created successfully')) diff --git a/idhub/views.py b/idhub/views.py index 8e7f542..176449b 100644 --- a/idhub/views.py +++ b/idhub/views.py @@ -20,23 +20,23 @@ class LoginView(auth_views.LoginView): def form_valid(self, form): user = form.get_user() - # Decrypt the user's sensitive data encryption key and store it in the session. password = form.cleaned_data.get("password") + auth_login(self.request, user) + sensitive_data_encryption_key = user.decrypt_sensitive_data(password) - key_dids = cache.get("KEY_DIDS", {}) + if not user.is_anonymous and user.is_admin: user_dashboard = reverse_lazy('idhub:user_dashboard') admin_dashboard = reverse_lazy('idhub:admin_dashboard') if self.extra_context['success_url'] == user_dashboard: self.extra_context['success_url'] = admin_dashboard - key_dids[user.id] = sensitive_data_encryption_key - cache.set("KEY_DIDS", key_dids, None) - else: - key_dids[user.id] = sensitive_data_encryption_key - cache.set("KEY_DIDS", key_dids) + cache.set("KEY_DIDS", sensitive_data_encryption_key, None) - auth_login(self.request, user) + self.request.session["key_did"] = user.encrypt_data( + sensitive_data_encryption_key, + user.password+self.request.session._session_key + ) return HttpResponseRedirect(self.extra_context['success_url']) diff --git a/idhub_auth/models.py b/idhub_auth/models.py index 86da431..189b421 100644 --- a/idhub_auth/models.py +++ b/idhub_auth/models.py @@ -145,24 +145,18 @@ class User(AbstractBaseUser): key_crypted = self.encrypt_sensitive_data(password, key) self.encrypted_sensitive_data = key_crypted - def encrypt_data(self, data): - sb = self.get_secret_box() + def encrypt_data(self, data, password): + sb = self.get_secret_box(password) value = base64.b64encode(data.encode('utf-8')) value_enc = sb.encrypt(data.encode('utf-8')) return base64.b64encode(value_enc).decode('utf-8') - def decrypt_data(self, data): - sb = self.get_secret_box() + def decrypt_data(self, data, password): + sb = self.get_secret_box(password) value = base64.b64decode(data.encode('utf-8')) return sb.decrypt(value).decode('utf-8') - def get_secret_box(self): - key_dids = cache.get("KEY_DIDS", {}) - if not key_dids.get(self.id): - err = "An attempt is made to access encrypted " - err += "data without having the key." - raise Exception(_(err)) - - pw = base64.b64decode(key_dids[self.id].encode('utf-8')) + def get_secret_box(self, password): + pw = base64.b64decode(password.encode('utf-8')) sb_key = self.derive_key_from_password(pw) return nacl.secret.SecretBox(sb_key) diff --git a/trustchain_idhub/settings.py b/trustchain_idhub/settings.py index b9eecc5..01567c6 100644 --- a/trustchain_idhub/settings.py +++ b/trustchain_idhub/settings.py @@ -149,6 +149,7 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] +SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # Internationalization # https://docs.djangoproject.com/en/4.2/topics/i18n/