Changed model definitions and added logic to decrypt and set user key in session storage
This commit is contained in:
parent
5eb606c4a4
commit
37dc8335a7
|
@ -6,6 +6,8 @@ from django.db import models
|
|||
from django.conf import settings
|
||||
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,
|
||||
keydid_from_controller_key,
|
||||
|
@ -409,7 +411,9 @@ class DID(models.Model):
|
|||
# In JWK format. Must be stored as-is and passed whole to library functions.
|
||||
# Example key material:
|
||||
# '{"kty":"OKP","crv":"Ed25519","x":"oB2cPGFx5FX4dtS1Rtep8ac6B__61HAP_RtSzJdPxqs","d":"OJw80T1CtcqV0hUcZdcI-vYNBN1dlubrLaJa0_se_gU"}'
|
||||
key_material = models.CharField(max_length=250)
|
||||
# CHANGED: `key_material` to `_key_material`, datatype from CharField to BinaryField and the key is now stored encrypted.
|
||||
key_material = None
|
||||
_key_material = models.BinaryField(max_length=250)
|
||||
user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
|
@ -417,6 +421,18 @@ class DID(models.Model):
|
|||
null=True,
|
||||
)
|
||||
|
||||
def get_key_material(self, session):
|
||||
if "sensitive_data_encryption_key" not in session:
|
||||
raise Exception("Ojo! Se intenta acceder a datos cifrados sin tener la clave de usuario.")
|
||||
sb = secret.SecretBox(session["sensitive_data_encryption_key"])
|
||||
return sb.decrypt(self._key_material)
|
||||
|
||||
def set_key_material(self, value, session):
|
||||
if "sensitive_data_encryption_key" not in session:
|
||||
raise Exception("Ojo! Se intenta acceder a datos cifrados sin tener la clave de usuario.")
|
||||
sb = secret.SecretBox(session["sensitive_data_encryption_key"])
|
||||
self._key_material = sb.encrypt(value)
|
||||
|
||||
@property
|
||||
def is_organization_did(self):
|
||||
if not self.user:
|
||||
|
@ -427,7 +443,8 @@ class DID(models.Model):
|
|||
self.key_material = generate_did_controller_key()
|
||||
self.did = keydid_from_controller_key(self.key_material)
|
||||
|
||||
def get_key(self):
|
||||
# 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)
|
||||
|
||||
|
||||
|
@ -464,7 +481,10 @@ class VerificableCredential(models.Model):
|
|||
created_on = models.DateTimeField(auto_now=True)
|
||||
issued_on = models.DateTimeField(null=True)
|
||||
subject_did = models.CharField(max_length=250)
|
||||
data = models.TextField()
|
||||
# CHANGED: `data` to `_data`, datatype from TextField to BinaryField and the rendered VC is now stored encrypted.
|
||||
# TODO: verify that BinaryField can hold arbitrary amounts of data (max_length = ???)
|
||||
data = None
|
||||
_data = models.BinaryField()
|
||||
csv_data = models.TextField()
|
||||
status = models.PositiveSmallIntegerField(
|
||||
choices=Status.choices,
|
||||
|
@ -486,6 +506,18 @@ class VerificableCredential(models.Model):
|
|||
related_name='vcredentials',
|
||||
)
|
||||
|
||||
def get_data(self, session):
|
||||
if "sensitive_data_encryption_key" not in session:
|
||||
raise Exception("Ojo! Se intenta acceder a datos cifrados sin tener la clave de usuario.")
|
||||
sb = secret.SecretBox(session["sensitive_data_encryption_key"])
|
||||
return sb.decrypt(self._data)
|
||||
|
||||
def set_data(self, value, session):
|
||||
if "sensitive_data_encryption_key" not in session:
|
||||
raise Exception("Ojo! Se intenta acceder a datos cifrados sin tener la clave de usuario.")
|
||||
sb = secret.SecretBox(session["sensitive_data_encryption_key"])
|
||||
self._data = sb.encrypt(value)
|
||||
|
||||
@property
|
||||
def get_schema(self):
|
||||
if not self.data:
|
||||
|
|
|
@ -25,4 +25,8 @@ class LoginView(auth_views.LoginView):
|
|||
if self.extra_context['success_url'] == user_dashboard:
|
||||
self.extra_context['success_url'] = admin_dashboard
|
||||
auth_login(self.request, user)
|
||||
# Decrypt the user's sensitive data encryption key and store it in the session.
|
||||
password = form.cleaned_data.get("password") # TODO: Is this right????????
|
||||
sensitive_data_encryption_key = user.decrypt_sensitive_data_encryption_key(password)
|
||||
self.request.session["sensitive_data_encryption_key"] = sensitive_data_encryption_key
|
||||
return HttpResponseRedirect(self.extra_context['success_url'])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.db import models
|
||||
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
|
||||
from nacl import secret, pwhash
|
||||
|
||||
|
||||
class UserManager(BaseUserManager):
|
||||
|
@ -43,6 +44,10 @@ class User(AbstractBaseUser):
|
|||
is_admin = models.BooleanField(default=False)
|
||||
first_name = models.CharField(max_length=255, blank=True, null=True)
|
||||
last_name = models.CharField(max_length=255, blank=True, null=True)
|
||||
# TODO: Hay que generar una clave aleatoria para cada usuario cuando se le da de alta en el sistema.
|
||||
encrypted_sensitive_data_encryption_key = models.BinaryField(max_length=255)
|
||||
# TODO: Hay que generar un salt aleatorio para cada usuario cuando se le da de alta en el sistema.
|
||||
salt_of_sensitive_data_encryption_key = models.BinaryField(max_length=255)
|
||||
|
||||
objects = UserManager()
|
||||
|
||||
|
@ -85,3 +90,16 @@ class User(AbstractBaseUser):
|
|||
for r in s.service.rol.all():
|
||||
roles.append(r.name)
|
||||
return ", ".join(set(roles))
|
||||
|
||||
def derive_key_from_password(self, password):
|
||||
kdf = pwhash.argon2i.kdf # TODO: Move the KDF choice to SETTINGS.PY
|
||||
ops = pwhash.argon2i.OPSLIMIT_INTERACTIVE # TODO: Move the KDF choice to SETTINGS.PY
|
||||
mem = pwhash.argon2i.MEMLIMIT_INTERACTIVE # TODO: Move the KDF choice to SETTINGS.PY
|
||||
salt = self.salt_of_sensitive_data_encryption_key
|
||||
return kdf(secret.SecretBox.KEY_SIZE, password, salt, opslimit=ops, memlimit=mem)
|
||||
|
||||
def decrypt_sensitive_data_encryption_key(self, password):
|
||||
sb_key = self.derive_key_from_password(password)
|
||||
sb = secret.SecretBox(sb_key)
|
||||
return sb.decrypt(self.encrypted_sensitive_data_encryption_key)
|
||||
|
||||
|
|
|
@ -11,3 +11,4 @@ didkit==0.3.2
|
|||
jinja2==3.1.2
|
||||
jsonref==1.1.0
|
||||
pyld==2.0.3
|
||||
pynacl==1.5.0
|
||||
|
|
Loading…
Reference in a new issue