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.db import models
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):
pass
@ -52,7 +56,6 @@ class AttributeType(models.Model):
class Attribute(models.Model):
attribute_type = models.ForeignKey(AttributeType, on_delete=models.CASCADE)
value = models.CharField(max_length=2048)
@ -81,21 +84,39 @@ class Rule(models.Model):
write = models.BooleanField(default=False)
delete = models.BooleanField(default=False)
def is_satisfied_by(self, user):
for rule_attribute in self.ruleattribute_set.all():
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
if not self.attribute_satisfies_rule(user_attribute, rule_attribute):
return False
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)
return True
for rule_attribute in self.ruleattribute_set.all():
if not rule_attribute.attribute_type.is_private:
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
if not self.attribute_satisfies_rule(user_attribute, rule_attribute):
return False, 0, 0
else:
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):
operator = rule_attribute.operator
@ -128,3 +149,9 @@ class RuleAttribute(Attribute):
class TrustedAuthority(models.Model):
name = models.CharField(max_length=255)
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,
hierarchy_view,
trusted_authorities,
delete_authority
delete_authority,
verify_decryption
)
app_name = 'abac'
@ -42,4 +43,5 @@ urlpatterns = [
path('visualization/hierarchical', hierarchy_view, name='hierarchy_vis'),
path('trusted-authorities', trusted_authorities, name="trusted_authorities"),
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.core.exceptions import ValidationError
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
import hashlib
import json
@ -17,7 +18,7 @@ from cryptography.hazmat.backends import default_backend
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
@ -209,31 +210,67 @@ def get_or_create_attribute_type(name, value, private=False):
@login_required
def download_file(request, file_id):
file = get_object_or_404(File, id=file_id)
user = request.user
allowed, x, enc = check_permission(user, file)
if allowed and not x and not enc:
return serve_file(file)
elif not allowed:
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)
for rule in file.rule_set.all():
if rule.is_satisfied_by(user):
return serve_file(file)
#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'])
return HttpResponseForbidden('You do not have permission to download this file.')
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:
pass
else:
# a) Check if the user is the owner of the file.
if user == file.owner:
return True
return True, [], []
# b) Check if the user is a superuser.
if user.is_superuser:
return True
return True, [], []
# c) Check the user's attributes against the file's rules.
x = []
enc = []
for rule in file.rule_set.all():
if rule.is_satisfied_by(user):
return True
result, x_i, enc_i = rule.is_satisfied_by(user)
if result:
x.append(x_i)
enc.append(enc_i)
else:
return False, [], []
return True, x, enc
def serve_file(file):
# Serve the file using FileResponse.

Loading…
Cancel
Save