Add to prototype

main
Malte 1 year ago
parent 8c9300e467
commit d9bdf9667a

@ -0,0 +1,24 @@
# Generated by Django 4.2.6 on 2023-10-24 16:16
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('abac', '0003_trustedauthority'),
]
operations = [
migrations.CreateModel(
name='EncryptedData',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('x_values', models.TextField()),
('token', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
('file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abac.file')),
],
),
]

@ -1,9 +1,13 @@
import pickle
from base64 import b64encode, b64decode
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
import pickle
from base64 import b64encode, b64decode
from random import randint
from phe import paillier
from uuid import uuid4
class User(AbstractUser): class User(AbstractUser):
pass pass
@ -52,7 +56,6 @@ class AttributeType(models.Model):
class Attribute(models.Model): class Attribute(models.Model):
attribute_type = models.ForeignKey(AttributeType, on_delete=models.CASCADE) attribute_type = models.ForeignKey(AttributeType, on_delete=models.CASCADE)
value = models.CharField(max_length=2048) value = models.CharField(max_length=2048)
@ -81,8 +84,17 @@ class Rule(models.Model):
write = models.BooleanField(default=False) write = models.BooleanField(default=False)
delete = models.BooleanField(default=False) delete = models.BooleanField(default=False)
def is_satisfied_by(self, user): def is_satisfied_by(self, user)->(bool, int, int):
x = randint(0,1000)
y = randint(0,1000)
try:
paillier_public_key = paillier.PaillierPublicKey(n=int(user.public_key))
except:
return False, 0, 0
encrypted_sum = paillier_public_key.encrypt(x)
for rule_attribute in self.ruleattribute_set.all(): for rule_attribute in self.ruleattribute_set.all():
if not rule_attribute.attribute_type.is_private:
try: try:
user_attribute = UserAttribute.objects.get( user_attribute = UserAttribute.objects.get(
user=user, user=user,
@ -90,12 +102,21 @@ class Rule(models.Model):
) )
except UserAttribute.DoesNotExist: except UserAttribute.DoesNotExist:
# The user does not have this attribute; the rule is not satisfied. # The user does not have this attribute; the rule is not satisfied.
return False return False, 0, 0
if not self.attribute_satisfies_rule(user_attribute, rule_attribute): if not self.attribute_satisfies_rule(user_attribute, rule_attribute):
return False return False, 0, 0
else:
return True try:
user_attribute = UserAttribute.objects.get(
user=user,
attribute_type=rule_attribute.attribute_type,
)
except UserAttribute.DoesNotExist:
# The user does not have this attribute; the rule is not satisfied.
return False, 0, 0
encrypted_attribute_value = paillier.EncryptedNumber(paillier_public_key, int(user_attribute.value))
encrypted_sum += (encrypted_attribute_value-int(rule_attribute.value))*y
return True, x, encrypted_sum.ciphertext()
def attribute_satisfies_rule(self, user_attribute, rule_attribute): def attribute_satisfies_rule(self, user_attribute, rule_attribute):
operator = rule_attribute.operator operator = rule_attribute.operator
@ -128,3 +149,9 @@ class RuleAttribute(Attribute):
class TrustedAuthority(models.Model): class TrustedAuthority(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
public_key = models.TextField() public_key = models.TextField()
class EncryptedData(models.Model):
file = models.ForeignKey(File, on_delete=models.CASCADE)
x_values = models.TextField() # Store the x values as comma-separated
token = models.UUIDField(default=uuid4, unique=True, editable=False)

@ -0,0 +1,77 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Decrypt and Forward</title>
<script src="{% static 'abac/jsbn.js' %}"></script>
<script src="{% static 'abac/jsbn2.js' %}"></script>
<script src="{% static 'abac/prng4.js' %}"></script>
<script src="{% static 'abac/rng.js' %}"></script>
<script src="{% static 'abac/paillier.js' %}"></script>
</head>
<body>
<script>
function getPrivateKeyFromWebStorage() {
// Retrieve and parse the stored private key
const storedPrivateKey = localStorage.getItem('privateKey');
if (!storedPrivateKey) return null;
const parsedKey = JSON.parse(storedPrivateKey);
// Construct the public key from the stored value
const n = new BigInteger(localStorage.getItem('publicKey'));
const publicKey = new paillier.publicKey(2048, n);
// Construct the private key
const lambda = new BigInteger(parsedKey.lambda);
const privateKey = new paillier.privateKey(lambda, publicKey);
// Attach the x value
privateKey.x = new BigInteger(parsedKey.x);
return privateKey;
}
// Assuming you have a method to get privateKey from local web storage
let privateKey = getPrivateKeyFromWebStorage();
let encryptions = {{ encryptions_as_strings|safe }};
let decryptedValues = [];
for(let enc of encryptions) {
let bigIntEnc = new BigInteger(enc.toString());
decryptedValues.push(privateKey.decrypt(bigIntEnc).toString(10));
}
// Forward the decrypted values with a POST request
let form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", "{% url 'abac:verify_decryption' %}");
let csrfField = document.createElement("input");
csrfField.setAttribute("type", "hidden");
csrfField.setAttribute("name", "csrfmiddlewaretoken");
csrfField.setAttribute("value", "{{ csrf_token }}");
form.appendChild(csrfField);
let tokenField = document.createElement("input");
tokenField.setAttribute("type", "hidden");
tokenField.setAttribute("name", "token");
tokenField.setAttribute("value", "{{ token }}");
form.appendChild(tokenField);
for(let dec of decryptedValues) {
let input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "decryptions");
input.setAttribute("value", dec);
form.appendChild(input);
}
document.body.appendChild(form);
form.submit();
</script>
</body>
</html>

@ -1,18 +0,0 @@
{% extends 'base.html' %}
{% block content %}
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6">
<h2>Upload Public Key</h2>
<form method="post" class="mt-3">
{% csrf_token %}
<div class="form-group">
<label for="public_key">Paste your public key here:</label>
<textarea id="public_key" name="public_key" class="form-control" rows="6" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Upload Public Key</button>
</form>
</div>
</div>
</div>
{% endblock %}

@ -19,7 +19,8 @@ from .views import (
upload_public_key, upload_public_key,
hierarchy_view, hierarchy_view,
trusted_authorities, trusted_authorities,
delete_authority delete_authority,
verify_decryption
) )
app_name = 'abac' app_name = 'abac'
@ -42,4 +43,5 @@ urlpatterns = [
path('visualization/hierarchical', hierarchy_view, name='hierarchy_vis'), path('visualization/hierarchical', hierarchy_view, name='hierarchy_vis'),
path('trusted-authorities', trusted_authorities, name="trusted_authorities"), path('trusted-authorities', trusted_authorities, name="trusted_authorities"),
path('trusted-authorities/delete/<int:authority_id>/', delete_authority, name='delete_authority'), path('trusted-authorities/delete/<int:authority_id>/', delete_authority, name='delete_authority'),
path('verify_decryption', verify_decryption, name='verify_decryption')
] ]

@ -7,6 +7,7 @@ from django.urls import reverse
from django.contrib import messages from django.contrib import messages
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils import timezone from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
import hashlib import hashlib
import json import json
@ -17,7 +18,7 @@ from cryptography.hazmat.backends import default_backend
from .forms import FileUploadForm, UploadCertificateForm, RuleAttributeForm, TrustedAuthorityForm from .forms import FileUploadForm, UploadCertificateForm, RuleAttributeForm, TrustedAuthorityForm
from .models import File, Rule, UserAttribute, RuleAttribute, AttributeType, User, TrustedAuthority from .models import File, Rule, UserAttribute, RuleAttribute, AttributeType, User, TrustedAuthority, EncryptedData
@login_required @login_required
@ -209,31 +210,67 @@ def get_or_create_attribute_type(name, value, private=False):
@login_required @login_required
def download_file(request, file_id): def download_file(request, file_id):
file = get_object_or_404(File, id=file_id) file = get_object_or_404(File, id=file_id)
user = request.user user = request.user
allowed, x, enc = check_permission(user, file)
for rule in file.rule_set.all(): if allowed and not x and not enc:
if rule.is_satisfied_by(user):
return serve_file(file) return serve_file(file)
elif not allowed:
return HttpResponseForbidden('You do not have permission to download this file.') return HttpResponseForbidden('You do not have permission to download this file.')
elif enc:
encrypted_data = EncryptedData(file=file, x_values=','.join(map(str, x)))
encrypted_data.save()
context = {
'encryptions_as_strings': [str(e) for e in enc],
'token': str(encrypted_data.token)
}
return render(request, 'decrypt_and_forward.html', context)
@login_required
def verify_decryption(request):
if request.method == 'POST':
token = request.POST.get('token')
decryptions = request.POST.getlist('decryptions')
encrypted_data = get_object_or_404(EncryptedData, token=token)
#Compare decryptions with stored x values TODO: for some reason this didn't work when I tried to make sure the order was preserved
x_values = list(map(int, encrypted_data.x_values.split(',')))
for decrypted in decryptions:
if int(decrypted) in x_values:
return serve_file(encrypted_data.file)
return HttpResponseForbidden("You don't have the permission to access this file!")
return HttpResponseNotAllowed(['POST'])
def check_permission(user, file, mode = None): def check_permission(user, file, mode = None):
"""
Method that checks if a user is allowed to perform the operation specified in mode with the file
TODO: Implement mode
"""
if mode: if mode:
pass pass
else: else:
# a) Check if the user is the owner of the file. # a) Check if the user is the owner of the file.
if user == file.owner: if user == file.owner:
return True return True, [], []
# b) Check if the user is a superuser. # b) Check if the user is a superuser.
if user.is_superuser: if user.is_superuser:
return True return True, [], []
# c) Check the user's attributes against the file's rules. # c) Check the user's attributes against the file's rules.
x = []
enc = []
for rule in file.rule_set.all(): for rule in file.rule_set.all():
if rule.is_satisfied_by(user): result, x_i, enc_i = rule.is_satisfied_by(user)
return True if result:
x.append(x_i)
enc.append(enc_i)
else:
return False, [], []
return True, x, enc
def serve_file(file): def serve_file(file):
# Serve the file using FileResponse. # Serve the file using FileResponse.

Loading…
Cancel
Save