new encriptation system of sensible datas
This commit is contained in:
parent
93f2432edb
commit
0247c5007d
|
@ -1,23 +1,19 @@
|
|||
import csv
|
||||
import json
|
||||
import copy
|
||||
import base64
|
||||
import jsonschema
|
||||
import pandas as pd
|
||||
|
||||
from pyhanko.sign import signers
|
||||
|
||||
from nacl.exceptions import CryptoError
|
||||
from django import forms
|
||||
from django.core.cache import cache
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
from utils import credtools, certs
|
||||
from utils import certs
|
||||
from idhub.models import (
|
||||
DID,
|
||||
File_datas,
|
||||
Membership,
|
||||
Schemas,
|
||||
Service,
|
||||
UserRol,
|
||||
VerificableCredential,
|
||||
)
|
||||
|
@ -51,6 +47,37 @@ class TermsConditionsForm2(forms.Form):
|
|||
return
|
||||
|
||||
|
||||
class EncryptionKeyForm(forms.Form):
|
||||
key = forms.CharField(
|
||||
label=_("Key for encrypt the secrets of all system"),
|
||||
required=True
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
data = self.cleaned_data
|
||||
self._key = data["key"]
|
||||
if not DID.objects.exists():
|
||||
return data
|
||||
|
||||
did = DID.objects.first()
|
||||
cache.set("KEY_DIDS", self._key, None)
|
||||
try:
|
||||
did.get_key_material()
|
||||
except CryptoError:
|
||||
cache.set("KEY_DIDS", None)
|
||||
txt = _("Key no valid!")
|
||||
raise ValidationError(txt)
|
||||
|
||||
return data
|
||||
|
||||
def save(self, commit=True):
|
||||
|
||||
if commit:
|
||||
cache.set("KEY_DIDS", self._key, None)
|
||||
|
||||
return
|
||||
|
||||
|
||||
class TermsConditionsForm(forms.Form):
|
||||
accept_privacy = forms.BooleanField(
|
||||
widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
||||
|
@ -133,7 +160,7 @@ class ImportForm(forms.Form):
|
|||
self.fields['did'].choices = [
|
||||
(x.did, x.label) for x in dids.filter(eidas1=False)
|
||||
]
|
||||
self.fields['schema'].choices = [
|
||||
self.fields['schema'].choices = [(0, _('Select one'))] + [
|
||||
(x.id, x.name) for x in Schemas.objects.filter()
|
||||
]
|
||||
if dids.filter(eidas1=True).exists():
|
||||
|
@ -197,6 +224,9 @@ class ImportForm(forms.Form):
|
|||
if not data_pd:
|
||||
self.exception("This file is empty!")
|
||||
|
||||
if not self._schema:
|
||||
return data
|
||||
|
||||
for n in range(df.last_valid_index()+1):
|
||||
row = {}
|
||||
for k in data_pd.keys():
|
||||
|
@ -382,7 +412,6 @@ class ImportCertificateForm(forms.Form):
|
|||
return data
|
||||
|
||||
def new_did(self):
|
||||
cert = self.pfx_file
|
||||
keys = {
|
||||
"cert": base64.b64encode(self.pfx_file).decode('utf-8'),
|
||||
"passphrase": self._pss
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import os
|
||||
import json
|
||||
import logging
|
||||
import pandas as pd
|
||||
from pathlib import Path
|
||||
from jsonschema import validate
|
||||
from smtplib import SMTPException
|
||||
from django_tables2 import SingleTableView
|
||||
|
||||
|
@ -18,7 +15,6 @@ 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
|
||||
|
@ -28,12 +24,13 @@ from idhub_auth.forms import ProfileForm
|
|||
from idhub.mixins import AdminView, Http403
|
||||
from idhub.email.views import NotifyActivateUserByEmail
|
||||
from idhub.admin.forms import (
|
||||
EncryptionKeyForm,
|
||||
ImportCertificateForm,
|
||||
ImportForm,
|
||||
MembershipForm,
|
||||
TermsConditionsForm,
|
||||
SchemaForm,
|
||||
UserRolForm,
|
||||
ImportCertificateForm,
|
||||
UserRolForm
|
||||
)
|
||||
from idhub.admin.tables import (
|
||||
DashboardTable,
|
||||
|
@ -79,7 +76,27 @@ class TermsAndConditionsView(AdminView, FormView):
|
|||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
user = form.save()
|
||||
form.save()
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class EncryptionKeyView(AdminView, FormView):
|
||||
template_name = "idhub/admin/encryption_key.html"
|
||||
title = _('Encryption Key')
|
||||
section = ""
|
||||
subtitle = _('Encryption Key')
|
||||
icon = 'bi bi-key'
|
||||
form_class = EncryptionKeyForm
|
||||
success_url = reverse_lazy('idhub:admin_dashboard')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if self.admin_validated:
|
||||
return redirect(self.success_url)
|
||||
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.save()
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
|
@ -649,7 +666,7 @@ class CredentialJsonView(Credentials):
|
|||
VerificableCredential,
|
||||
pk=pk,
|
||||
)
|
||||
response = HttpResponse(self.object.data, content_type="application/json")
|
||||
response = HttpResponse(self.object.get_data(), content_type="application/json")
|
||||
response['Content-Disposition'] = 'attachment; filename={}'.format("credential.json")
|
||||
return response
|
||||
|
||||
|
@ -730,7 +747,7 @@ class DidRegisterView(Credentials, CreateView):
|
|||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
form.instance.set_did(cache.get("KEY_DIDS"))
|
||||
form.instance.set_did()
|
||||
form.save()
|
||||
messages.success(self.request, _('DID created successfully'))
|
||||
Event.set_EV_ORG_DID_CREATED_BY_ADMIN(form.instance)
|
||||
|
@ -752,7 +769,7 @@ class DidEditView(Credentials, UpdateView):
|
|||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
user = form.save()
|
||||
form.save()
|
||||
messages.success(self.request, _('DID updated successfully'))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ class Command(BaseCommand):
|
|||
def handle(self, *args, **kwargs):
|
||||
ADMIN_EMAIL = config('ADMIN_EMAIL', 'admin@example.org')
|
||||
ADMIN_PASSWORD = config('ADMIN_PASSWORD', '1234')
|
||||
KEY_DIDS = config('KEY_DIDS', '1234')
|
||||
cache.set("KEY_DIDS", KEY_DIDS, None)
|
||||
|
||||
self.create_admin_users(ADMIN_EMAIL, ADMIN_PASSWORD)
|
||||
if settings.CREATE_TEST_USERS:
|
||||
|
@ -43,21 +45,17 @@ class Command(BaseCommand):
|
|||
|
||||
def create_admin_users(self, email, password):
|
||||
su = User.objects.create_superuser(email=email, password=password)
|
||||
su.set_encrypted_sensitive_data(password)
|
||||
su.set_encrypted_sensitive_data()
|
||||
su.save()
|
||||
key = su.decrypt_sensitive_data(password)
|
||||
key_dids = {su.id: key}
|
||||
cache.set("KEY_DIDS", key_dids, None)
|
||||
self.create_defaults_dids(su, key)
|
||||
self.create_defaults_dids(su)
|
||||
|
||||
|
||||
def create_users(self, email, password):
|
||||
u = User.objects.create(email=email, password=password)
|
||||
u.set_password(password)
|
||||
u.set_encrypted_sensitive_data(password)
|
||||
u.set_encrypted_sensitive_data()
|
||||
u.save()
|
||||
key = u.decrypt_sensitive_data(password)
|
||||
self.create_defaults_dids(u, key)
|
||||
self.create_defaults_dids(u)
|
||||
|
||||
|
||||
def create_organizations(self, name, url):
|
||||
|
@ -72,9 +70,10 @@ class Command(BaseCommand):
|
|||
org1.my_client_secret = org2.client_secret
|
||||
org1.save()
|
||||
org2.save()
|
||||
def create_defaults_dids(self, u, password):
|
||||
|
||||
def create_defaults_dids(self, u):
|
||||
did = DID(label="Default", user=u, type=DID.Types.WEB)
|
||||
did.set_did(password)
|
||||
did.set_did()
|
||||
did.save()
|
||||
|
||||
def create_schemas(self):
|
||||
|
|
|
@ -12,8 +12,8 @@ class Http403(PermissionDenied):
|
|||
default_detail = _('Permission denied. User is not authenticated')
|
||||
default_code = 'forbidden'
|
||||
|
||||
def __init__(self, detail=None, code=None):
|
||||
if detail is not None:
|
||||
def __init__(self, details=None, code=None):
|
||||
if details is not None:
|
||||
self.detail = details or self.default_details
|
||||
if code is not None:
|
||||
self.code = code or self.default_code
|
||||
|
@ -22,15 +22,30 @@ class Http403(PermissionDenied):
|
|||
class UserView(LoginRequiredMixin):
|
||||
login_url = "/login/"
|
||||
wallet = False
|
||||
admin_validated = False
|
||||
path_terms = [
|
||||
'admin_terms_and_conditions',
|
||||
'user_terms_and_conditions',
|
||||
'user_gdpr',
|
||||
'user_waiting',
|
||||
'user_waiting',
|
||||
'encryption_key',
|
||||
]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.admin_validated = cache.get("KEY_DIDS")
|
||||
response = super().get(request, *args, **kwargs)
|
||||
|
||||
if not self.admin_validated:
|
||||
actual_path = resolve(self.request.path).url_name
|
||||
if not self.request.user.is_admin:
|
||||
if actual_path != 'user_waiting':
|
||||
return redirect(reverse_lazy("idhub:user_waiting"))
|
||||
|
||||
if self.request.user.is_admin:
|
||||
if actual_path != 'encryption_key':
|
||||
return redirect(reverse_lazy("idhub:encryption_key"))
|
||||
|
||||
url = self.check_gdpr()
|
||||
|
||||
return url or response
|
||||
|
|
|
@ -9,7 +9,6 @@ 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
|
||||
|
||||
from utils.idhub_ssikit import (
|
||||
generate_did_controller_key,
|
||||
|
@ -34,26 +33,27 @@ class Event(models.Model):
|
|||
EV_DID_CREATED = 9, "DID created"
|
||||
EV_DID_DELETED = 10, "DID deleted"
|
||||
EV_CREDENTIAL_DELETED_BY_USER = 11, "Credential deleted by user"
|
||||
EV_CREDENTIAL_DELETED = 12, "Credential deleted"
|
||||
EV_CREDENTIAL_ISSUED_FOR_USER = 13, "Credential issued for user"
|
||||
EV_CREDENTIAL_ISSUED = 14, "Credential issued"
|
||||
EV_CREDENTIAL_PRESENTED_BY_USER = 15, "Credential presented by user"
|
||||
EV_CREDENTIAL_PRESENTED = 16, "Credential presented"
|
||||
EV_CREDENTIAL_ENABLED = 17, "Credential enabled"
|
||||
EV_CREDENTIAL_CAN_BE_REQUESTED = 18, "Credential available"
|
||||
EV_CREDENTIAL_REVOKED_BY_ADMIN = 19, "Credential revoked by admin"
|
||||
EV_CREDENTIAL_REVOKED = 20, "Credential revoked"
|
||||
EV_ROLE_CREATED_BY_ADMIN = 21, "Role created by admin"
|
||||
EV_ROLE_MODIFIED_BY_ADMIN = 22, "Role modified by admin"
|
||||
EV_ROLE_DELETED_BY_ADMIN = 23, "Role deleted by admin"
|
||||
EV_SERVICE_CREATED_BY_ADMIN = 24, "Service created by admin"
|
||||
EV_SERVICE_MODIFIED_BY_ADMIN = 25, "Service modified by admin"
|
||||
EV_SERVICE_DELETED_BY_ADMIN = 26, "Service deleted by admin"
|
||||
EV_ORG_DID_CREATED_BY_ADMIN = 27, "Organisational DID created by admin"
|
||||
EV_ORG_DID_DELETED_BY_ADMIN = 28, "Organisational DID deleted by admin"
|
||||
EV_USR_DEACTIVATED_BY_ADMIN = 29, "User deactivated"
|
||||
EV_USR_ACTIVATED_BY_ADMIN = 30, "User activated"
|
||||
EV_USR_SEND_VP = 31, "User send Verificable Presentation"
|
||||
EV_CREDENTIAL_DELETED_BY_ADMIN = 12, "Credential deleted by admin"
|
||||
EV_CREDENTIAL_DELETED = 13, "Credential deleted"
|
||||
EV_CREDENTIAL_ISSUED_FOR_USER = 14, "Credential issued for user"
|
||||
EV_CREDENTIAL_ISSUED = 15, "Credential issued"
|
||||
EV_CREDENTIAL_PRESENTED_BY_USER = 16, "Credential presented by user"
|
||||
EV_CREDENTIAL_PRESENTED = 17, "Credential presented"
|
||||
EV_CREDENTIAL_ENABLED = 18, "Credential enabled"
|
||||
EV_CREDENTIAL_CAN_BE_REQUESTED = 19, "Credential available"
|
||||
EV_CREDENTIAL_REVOKED_BY_ADMIN = 20, "Credential revoked by admin"
|
||||
EV_CREDENTIAL_REVOKED = 21, "Credential revoked"
|
||||
EV_ROLE_CREATED_BY_ADMIN = 22, "Role created by admin"
|
||||
EV_ROLE_MODIFIED_BY_ADMIN = 23, "Role modified by admin"
|
||||
EV_ROLE_DELETED_BY_ADMIN = 24, "Role deleted by admin"
|
||||
EV_SERVICE_CREATED_BY_ADMIN = 25, "Service created by admin"
|
||||
EV_SERVICE_MODIFIED_BY_ADMIN = 26, "Service modified by admin"
|
||||
EV_SERVICE_DELETED_BY_ADMIN = 27, "Service deleted by admin"
|
||||
EV_ORG_DID_CREATED_BY_ADMIN = 28, "Organisational DID created by admin"
|
||||
EV_ORG_DID_DELETED_BY_ADMIN = 29, "Organisational DID deleted by admin"
|
||||
EV_USR_DEACTIVATED_BY_ADMIN = 30, "User deactivated"
|
||||
EV_USR_ACTIVATED_BY_ADMIN = 31, "User activated"
|
||||
EV_USR_SEND_VP = 32, "User send Verificable Presentation"
|
||||
|
||||
created = models.DateTimeField(_("Date"), auto_now=True)
|
||||
message = models.CharField(_("Description"), max_length=350)
|
||||
|
@ -99,9 +99,8 @@ class Event(models.Model):
|
|||
@classmethod
|
||||
def set_EV_DATA_UPDATE_REQUESTED_BY_USER(cls, user):
|
||||
msg = _("The user '{username}' has request the update of the following information: ")
|
||||
msg += "['field1':'value1', 'field2':'value2'>,...]".format(
|
||||
username=user.username,
|
||||
)
|
||||
msg += "['field1':'value1', 'field2':'value2'>,...]"
|
||||
msg = msg.format(username=user.username)
|
||||
cls.objects.create(
|
||||
type=cls.Types.EV_DATA_UPDATE_REQUESTED_BY_USER,
|
||||
message=msg,
|
||||
|
@ -444,11 +443,11 @@ class DID(models.Model):
|
|||
# JSON-serialized DID document
|
||||
didweb_document = models.TextField()
|
||||
|
||||
def get_key_material(self, password):
|
||||
return self.user.decrypt_data(self.key_material, password)
|
||||
def get_key_material(self):
|
||||
return self.user.decrypt_data(self.key_material)
|
||||
|
||||
def set_key_material(self, value, password):
|
||||
self.key_material = self.user.encrypt_data(value, password)
|
||||
def set_key_material(self, value):
|
||||
self.key_material = self.user.encrypt_data(value)
|
||||
|
||||
@property
|
||||
def is_organization_did(self):
|
||||
|
@ -456,9 +455,9 @@ class DID(models.Model):
|
|||
return True
|
||||
return False
|
||||
|
||||
def set_did(self, password):
|
||||
def set_did(self):
|
||||
new_key_material = generate_did_controller_key()
|
||||
self.set_key_material(new_key_material, password)
|
||||
self.set_key_material(new_key_material)
|
||||
|
||||
if self.type == self.Types.KEY:
|
||||
self.did = keydid_from_controller_key(new_key_material)
|
||||
|
@ -621,17 +620,14 @@ class VerificableCredential(models.Model):
|
|||
return True
|
||||
return False
|
||||
|
||||
def get_data(self, password):
|
||||
def get_data(self):
|
||||
if not self.data:
|
||||
return ""
|
||||
|
||||
if self.eidas1_did:
|
||||
return self.data
|
||||
|
||||
return self.user.decrypt_data(self.data, password)
|
||||
return self.user.decrypt_data(self.data)
|
||||
|
||||
def set_data(self, value, password):
|
||||
self.data = self.user.encrypt_data(value, password)
|
||||
def set_data(self, value):
|
||||
self.data = self.user.encrypt_data(value)
|
||||
|
||||
def get_description(self):
|
||||
return self.schema._description or ''
|
||||
|
@ -652,32 +648,24 @@ class VerificableCredential(models.Model):
|
|||
data = json.loads(self.csv_data).items()
|
||||
return data
|
||||
|
||||
def issue(self, did, password, domain=settings.DOMAIN.strip("/")):
|
||||
def issue(self, did, domain=settings.DOMAIN.strip("/")):
|
||||
if self.status == self.Status.ISSUED:
|
||||
return
|
||||
|
||||
self.subject_did = did
|
||||
self.issued_on = datetime.datetime.now().astimezone(pytz.utc)
|
||||
issuer_pass = cache.get("KEY_DIDS")
|
||||
# issuer_pass = self.user.decrypt_data(
|
||||
# cache.get("KEY_DIDS"),
|
||||
# settings.SECRET_KEY,
|
||||
# )
|
||||
|
||||
# hash of credential without sign
|
||||
self.hash = hashlib.sha3_256(self.render(domain).encode()).hexdigest()
|
||||
data = sign_credential(
|
||||
self.render(domain),
|
||||
self.issuer_did.get_key_material(issuer_pass)
|
||||
self.issuer_did.get_key_material()
|
||||
)
|
||||
valid, reason = verify_credential(data)
|
||||
if not valid:
|
||||
return
|
||||
|
||||
if self.eidas1_did:
|
||||
self.data = data
|
||||
else:
|
||||
self.data = self.user.encrypt_data(data, password)
|
||||
self.data = self.user.encrypt_data(data)
|
||||
|
||||
self.status = self.Status.ISSUED
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<strong>{% trans 'Issuance date' %}:</strong>
|
||||
</div>
|
||||
<div class="col bg-light text-secondary">
|
||||
{{ object.issuer_on|default_if_none:"" }}
|
||||
{{ object.issued_on|default_if_none:"" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<strong>{% trans 'Issuance date' %}:</strong>
|
||||
</div>
|
||||
<div class="col bg-light text-secondary">
|
||||
{{ object.issuer_on|default_if_none:"" }}
|
||||
{{ object.issued_on|default_if_none:"" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
|
|
|
@ -88,6 +88,9 @@ urlpatterns = [
|
|||
path('user/terms/', views_user.TermsAndConditionsView.as_view(),
|
||||
name='user_terms_and_conditions'),
|
||||
|
||||
path('waiting/', views_user.WaitingView.as_view(),
|
||||
name='user_waiting'),
|
||||
|
||||
# Admin
|
||||
path('admin/dashboard/', views_admin.DashboardView.as_view(),
|
||||
name='admin_dashboard'),
|
||||
|
@ -173,6 +176,7 @@ urlpatterns = [
|
|||
name='admin_terms_and_conditions'),
|
||||
path('admin/import/new', views_admin.ImportAddView.as_view(),
|
||||
name='admin_import_add'),
|
||||
path('admin/enc/', views_admin.EncryptionKeyView.as_view(), name='encryption_key'),
|
||||
path('admin/auth/<uuid:admin2fauth>', views_admin.DobleFactorAuthView.as_view(),
|
||||
name='admin_2fauth'),
|
||||
path('admin/auth/2f/', DobleFactorSendView.as_view(), name='confirm_send_2f'),
|
||||
|
|
|
@ -81,7 +81,6 @@ class RequestCredentialForm(forms.Form):
|
|||
self.user = kwargs.pop('user', None)
|
||||
self.lang = kwargs.pop('lang', None)
|
||||
self._domain = kwargs.pop('domain', 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)
|
||||
|
@ -109,8 +108,7 @@ class RequestCredentialForm(forms.Form):
|
|||
did = did[0]
|
||||
cred = cred[0]
|
||||
try:
|
||||
if self.password:
|
||||
cred.issue(did, self.password, domain=self._domain)
|
||||
cred.issue(did, domain=self._domain)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
|
|
@ -161,10 +161,25 @@ class TermsAndConditionsView(UserView, FormView):
|
|||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
user = form.save()
|
||||
form.save()
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class WaitingView(UserView, TemplateView):
|
||||
template_name = "idhub/user/waiting.html"
|
||||
title = _("Comunication with admin")
|
||||
subtitle = _('Service temporary close')
|
||||
section = ""
|
||||
icon = 'bi bi-file-earmark-medical'
|
||||
success_url = reverse_lazy('idhub:user_dashboard')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if cache.get("KEY_DIDS"):
|
||||
return redirect(self.success_url)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
|
||||
class CredentialView(MyWallet, TemplateView):
|
||||
template_name = "idhub/user/credential.html"
|
||||
subtitle = _('Credential')
|
||||
|
@ -194,7 +209,8 @@ class CredentialPdfView(MyWallet, TemplateView):
|
|||
file_name = "certificate.pdf"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.admin_validated = cache.get("KEY_DIDS")
|
||||
if not self.admin_validated:
|
||||
return redirect(reverse_lazy('idhub:user_dashboard'))
|
||||
pk = kwargs['pk']
|
||||
self.user = self.request.user
|
||||
self.object = get_object_or_404(
|
||||
|
@ -282,10 +298,9 @@ class CredentialPdfView(MyWallet, TemplateView):
|
|||
|
||||
def get_pfx_data(self):
|
||||
did = self.object.eidas1_did
|
||||
pw = self.admin_validated
|
||||
if not did or not pw:
|
||||
if not did:
|
||||
return None, None
|
||||
key_material = json.loads(did.get_key_material(pw))
|
||||
key_material = json.loads(did.get_key_material())
|
||||
cert = key_material.get("cert")
|
||||
passphrase = key_material.get("passphrase")
|
||||
if cert and passphrase:
|
||||
|
@ -337,14 +352,7 @@ class CredentialJsonView(MyWallet, TemplateView):
|
|||
pk=pk,
|
||||
user=self.request.user
|
||||
)
|
||||
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)
|
||||
data = self.object.get_data()
|
||||
response = HttpResponse(data, content_type="application/json")
|
||||
response['Content-Disposition'] = 'attachment; filename={}'.format("credential.json")
|
||||
return response
|
||||
|
@ -383,15 +391,6 @@ class CredentialsRequestView(MyWallet, FormView):
|
|||
kwargs['lang'] = self.request.LANGUAGE_CODE
|
||||
domain = "{}://{}".format(self.request.scheme, self.request.get_host())
|
||||
kwargs['domain'] = domain
|
||||
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):
|
||||
|
@ -468,11 +467,7 @@ class DidRegisterView(MyWallet, CreateView):
|
|||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
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.instance.set_did()
|
||||
form.save()
|
||||
messages.success(self.request, _('DID created successfully'))
|
||||
|
||||
|
@ -496,7 +491,7 @@ class DidEditView(MyWallet, UpdateView):
|
|||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
user = form.save()
|
||||
form.save()
|
||||
messages.success(self.request, _('DID updated successfully'))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ from django.http import HttpResponseRedirect, HttpResponse, Http404
|
|||
|
||||
from idhub.models import DID, VerificableCredential
|
||||
from idhub.email.views import NotifyActivateUserByEmail
|
||||
from trustchain_idhub import settings
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -46,30 +45,20 @@ class LoginView(auth_views.LoginView):
|
|||
|
||||
def form_valid(self, form):
|
||||
user = form.get_user()
|
||||
password = form.cleaned_data.get("password")
|
||||
auth_login(self.request, user)
|
||||
|
||||
sensitive_data_encryption_key = user.decrypt_sensitive_data(password)
|
||||
if user.is_anonymous:
|
||||
return redirect(reverse_lazy("idhub:login"))
|
||||
|
||||
if not user.is_anonymous and user.is_admin:
|
||||
admin_dashboard = reverse_lazy('idhub:admin_dashboard')
|
||||
self.extra_context['success_url'] = admin_dashboard
|
||||
# encryption_key = user.encrypt_data(
|
||||
# sensitive_data_encryption_key,
|
||||
# settings.SECRET_KEY
|
||||
# )
|
||||
# cache.set("KEY_DIDS", encryption_key, None)
|
||||
cache.set("KEY_DIDS", sensitive_data_encryption_key, None)
|
||||
if user.is_admin:
|
||||
if settings.ENABLE_2FACTOR_AUTH:
|
||||
self.request.session["2fauth"] = str(uuid.uuid4())
|
||||
return redirect(reverse_lazy('idhub:confirm_send_2f'))
|
||||
|
||||
self.request.session["key_did"] = user.encrypt_data(
|
||||
sensitive_data_encryption_key,
|
||||
user.password+self.request.session._session_key
|
||||
)
|
||||
admin_dashboard = reverse_lazy('idhub:admin_dashboard')
|
||||
self.extra_context['success_url'] = admin_dashboard
|
||||
|
||||
return HttpResponseRedirect(self.extra_context['success_url'])
|
||||
return redirect(self.extra_context['success_url'])
|
||||
|
||||
|
||||
class PasswordResetConfirmView(auth_views.PasswordResetConfirmView):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import nacl
|
||||
import base64
|
||||
|
||||
from nacl import pwhash
|
||||
from nacl import pwhash, secret
|
||||
from django.db import models
|
||||
from django.core.cache import cache
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
@ -95,21 +95,24 @@ class User(AbstractBaseUser):
|
|||
roles.append(r.name)
|
||||
return ", ".join(set(roles))
|
||||
|
||||
def derive_key_from_password(self, password):
|
||||
def derive_key_from_password(self, password=None):
|
||||
if not password:
|
||||
password = cache.get("KEY_DIDS").encode('utf-8')
|
||||
|
||||
kdf = pwhash.argon2i.kdf
|
||||
ops = pwhash.argon2i.OPSLIMIT_INTERACTIVE
|
||||
mem = pwhash.argon2i.MEMLIMIT_INTERACTIVE
|
||||
return kdf(
|
||||
nacl.secret.SecretBox.KEY_SIZE,
|
||||
secret.SecretBox.KEY_SIZE,
|
||||
password,
|
||||
self.get_salt(),
|
||||
opslimit=ops,
|
||||
memlimit=mem
|
||||
)
|
||||
|
||||
def decrypt_sensitive_data(self, password, data=None):
|
||||
sb_key = self.derive_key_from_password(password.encode('utf-8'))
|
||||
sb = nacl.secret.SecretBox(sb_key)
|
||||
def decrypt_sensitive_data(self, data=None):
|
||||
sb_key = self.derive_key_from_password()
|
||||
sb = secret.SecretBox(sb_key)
|
||||
if not data:
|
||||
data = self.get_encrypted_sensitive_data()
|
||||
if not isinstance(data, bytes):
|
||||
|
@ -117,9 +120,9 @@ class User(AbstractBaseUser):
|
|||
|
||||
return sb.decrypt(data).decode('utf-8')
|
||||
|
||||
def encrypt_sensitive_data(self, password, data):
|
||||
sb_key = self.derive_key_from_password(password.encode('utf-8'))
|
||||
sb = nacl.secret.SecretBox(sb_key)
|
||||
def encrypt_sensitive_data(self, data):
|
||||
sb_key = self.derive_key_from_password()
|
||||
sb = secret.SecretBox(sb_key)
|
||||
if not isinstance(data, bytes):
|
||||
data = data.encode('utf-8')
|
||||
|
||||
|
@ -134,32 +137,33 @@ class User(AbstractBaseUser):
|
|||
def get_encrypted_sensitive_data(self):
|
||||
return base64.b64decode(self.encrypted_sensitive_data.encode('utf-8'))
|
||||
|
||||
def set_encrypted_sensitive_data(self, password):
|
||||
def set_encrypted_sensitive_data(self):
|
||||
key = base64.b64encode(nacl.utils.random(64))
|
||||
self.set_salt()
|
||||
|
||||
key_crypted = self.encrypt_sensitive_data(password, key)
|
||||
key_crypted = self.encrypt_sensitive_data(key)
|
||||
self.encrypted_sensitive_data = key_crypted
|
||||
|
||||
def encrypt_data(self, data, password):
|
||||
sb = self.get_secret_box(password)
|
||||
def encrypt_data(self, data):
|
||||
sb = self.get_secret_box()
|
||||
value_enc = sb.encrypt(data.encode('utf-8'))
|
||||
return base64.b64encode(value_enc).decode('utf-8')
|
||||
|
||||
def decrypt_data(self, data, password):
|
||||
sb = self.get_secret_box(password)
|
||||
def decrypt_data(self, data):
|
||||
sb = self.get_secret_box()
|
||||
value = base64.b64decode(data.encode('utf-8'))
|
||||
return sb.decrypt(value).decode('utf-8')
|
||||
|
||||
def get_secret_box(self, password):
|
||||
pw = base64.b64decode(password.encode('utf-8')*4)
|
||||
sb_key = self.derive_key_from_password(pw)
|
||||
return nacl.secret.SecretBox(sb_key)
|
||||
def get_secret_box(self):
|
||||
sb_key = self.derive_key_from_password()
|
||||
return secret.SecretBox(sb_key)
|
||||
|
||||
def change_password(self, old_password, new_password):
|
||||
sensitive_data = self.decrypt_sensitive_data(old_password)
|
||||
self.encrypted_sensitive_data = self.encrypt_sensitive_data(
|
||||
new_password,
|
||||
sensitive_data
|
||||
)
|
||||
self.set_password(new_password)
|
||||
def change_password_key(self, new_password):
|
||||
data = self.decrypt_sensitive_data()
|
||||
sb_key = self.derive_key_from_password(new_password)
|
||||
sb = secret.SecretBox(sb_key)
|
||||
if not isinstance(data, bytes):
|
||||
data = data.encode('utf-8')
|
||||
|
||||
encrypted_data = base64.b64encode(sb.encrypt(data)).decode('utf-8')
|
||||
self.encrypted_sensitive_data = encrypted_data
|
||||
|
|
Loading…
Reference in New Issue