Compare commits
6 Commits
8049bf2194
...
120e04ce2a
Author | SHA1 | Date | |
---|---|---|---|
120e04ce2a | |||
42cea0b61f | |||
b60da93e95 | |||
0be96fc105 | |||
8758bd2d7f | |||
9cffee90fd |
BIN
Bachelorarbeit_DRM_für_EPA_Gabriel_Kaufmann.pdf
Normal file
BIN
Bachelorarbeit_DRM_für_EPA_Gabriel_Kaufmann.pdf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,16 +0,0 @@
|
|||||||
"""
|
|
||||||
ASGI config for Contentserver project.
|
|
||||||
|
|
||||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Contentserver.settings')
|
|
||||||
|
|
||||||
application = get_asgi_application()
|
|
@ -1,138 +0,0 @@
|
|||||||
"""
|
|
||||||
Django settings for Contentserver project.
|
|
||||||
|
|
||||||
Generated by 'django-admin startproject' using Django 3.1.4.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/3.1/topics/settings/
|
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
|
||||||
https://docs.djangoproject.com/en/3.1/ref/settings/
|
|
||||||
"""
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
import os
|
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
|
||||||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
|
||||||
SECRET_KEY = '#^9h3-tg+(r__c)5m9@51#iq+f!e+ifr2&(q3y_3w=-9h2aizr'
|
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['192.168.192.75', '188.195.130.70', '0.0.0.0', 'localhost', '127.0.0.1']
|
|
||||||
|
|
||||||
CORS_ORIGIN_ALLOW_ALL=True
|
|
||||||
# Application definition
|
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
|
||||||
'corsheaders',
|
|
||||||
'django.contrib.admin',
|
|
||||||
'django.contrib.auth',
|
|
||||||
'django.contrib.contenttypes',
|
|
||||||
'django.contrib.sessions',
|
|
||||||
'django.contrib.messages',
|
|
||||||
'django.contrib.staticfiles',
|
|
||||||
'rest_framework',
|
|
||||||
'health_view'
|
|
||||||
]
|
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
|
||||||
# Use Django's standard `django.contrib.auth` permissions,
|
|
||||||
# or allow read-only access for unauthenticated users.
|
|
||||||
'DEFAULT_PERMISSION_CLASSES': [
|
|
||||||
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
|
|
||||||
],
|
|
||||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
|
||||||
'PAGE_SIZE': 10
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MIDDLEWARE = [
|
|
||||||
'corsheaders.middleware.CorsMiddleware',
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.middleware.security.SecurityMiddleware',
|
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
||||||
]
|
|
||||||
|
|
||||||
ROOT_URLCONF = 'Contentserver.urls'
|
|
||||||
|
|
||||||
TEMPLATES = [
|
|
||||||
{
|
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
||||||
'DIRS': [os.path.join(BASE_DIR, 'templates')],
|
|
||||||
'APP_DIRS': True,
|
|
||||||
'OPTIONS': {
|
|
||||||
'context_processors': [
|
|
||||||
'django.template.context_processors.debug',
|
|
||||||
'django.template.context_processors.request',
|
|
||||||
'django.contrib.auth.context_processors.auth',
|
|
||||||
'django.contrib.messages.context_processors.messages',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
WSGI_APPLICATION = 'Contentserver.wsgi.application'
|
|
||||||
|
|
||||||
|
|
||||||
# Database
|
|
||||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
|
||||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
|
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
|
||||||
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
|
||||||
|
|
||||||
TIME_ZONE = 'Europe/Berlin'
|
|
||||||
|
|
||||||
USE_I18N = True
|
|
||||||
|
|
||||||
USE_L10N = True
|
|
||||||
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
|
||||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
LOGIN_REDIRECT_URL = '/'
|
|
@ -1,18 +0,0 @@
|
|||||||
from django.urls import include, path
|
|
||||||
from rest_framework import routers
|
|
||||||
from health_view import views
|
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
router = routers.DefaultRouter()
|
|
||||||
router.register(r'users', views.UserViewSet)
|
|
||||||
router.register(r'groups', views.GroupViewSet)
|
|
||||||
router.register(r'folderpartnames', views.GetFolderPartNames)
|
|
||||||
|
|
||||||
# Wire up our API using automatic URL routing.
|
|
||||||
# Additionally, we include login URLs for the browsable API.
|
|
||||||
urlpatterns = [
|
|
||||||
path('admin/', admin.site.urls),
|
|
||||||
path('', include(router.urls)),
|
|
||||||
path('', include('health_view.urls')),
|
|
||||||
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
|
|
||||||
]
|
|
@ -1,16 +0,0 @@
|
|||||||
"""
|
|
||||||
WSGI config for Contentserver project.
|
|
||||||
|
|
||||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Contentserver.settings')
|
|
||||||
|
|
||||||
application = get_wsgi_application()
|
|
@ -1,22 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
from .models import FolderInfo, FolderPart, JustifiedKey, FolderPart_Name
|
|
||||||
|
|
||||||
admin.site.register(FolderInfo)
|
|
||||||
admin.site.register(FolderPart)
|
|
||||||
admin.site.register(FolderPart_Name)
|
|
||||||
admin.site.register(JustifiedKey)
|
|
||||||
|
|
||||||
#@admin.register(BookInstance)
|
|
||||||
#class BookInstanceAdmin(admin.ModelAdmin):
|
|
||||||
# list_display = ('book', 'status', 'borrower', 'due_back', 'id')
|
|
||||||
# list_filter = ('status', 'due_back')#
|
|
||||||
#
|
|
||||||
# fieldsets = (
|
|
||||||
# (None, {
|
|
||||||
# 'fields': ('book','imprint', 'id')
|
|
||||||
# }),
|
|
||||||
# ('Availability', {
|
|
||||||
# 'fields': ('status', 'due_back','borrower')
|
|
||||||
# }),
|
|
||||||
# )
|
|
@ -1,5 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class HealthViewConfig(AppConfig):
|
|
||||||
name = 'health_view'
|
|
@ -1,103 +0,0 @@
|
|||||||
import os
|
|
||||||
import codecs
|
|
||||||
from Crypto.PublicKey import RSA
|
|
||||||
from Crypto.Cipher import PKCS1_OAEP, AES
|
|
||||||
from Crypto.Hash import SHA256
|
|
||||||
from Crypto.Signature import PKCS1_v1_5
|
|
||||||
from Crypto import Random
|
|
||||||
from base64 import b64decode, b64encode
|
|
||||||
|
|
||||||
|
|
||||||
BS = 16
|
|
||||||
|
|
||||||
|
|
||||||
pub_key_contentserver = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYI/jGk6f0LAT2Z6AAQUR7izbi\na5O4Zzaz4WtK00jr3AqbZMVeVZAs+As5RS35PY2BlCuEEza/J5XX1tlbUhGk/Nzu\nyYqlID6ILEk9kUqh1A6EAuNVrcCL174BRLy620pU5m+E61za0tIr1lU+Jhy4ikVK\niGQ+na5a5g0kuzZTHwIDAQAB\n-----END PUBLIC KEY-----'
|
|
||||||
private_key_contentserver = '-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDYI/jGk6f0LAT2Z6AAQUR7izbia5O4Zzaz4WtK00jr3AqbZMVe\nVZAs+As5RS35PY2BlCuEEza/J5XX1tlbUhGk/NzuyYqlID6ILEk9kUqh1A6EAuNV\nrcCL174BRLy620pU5m+E61za0tIr1lU+Jhy4ikVKiGQ+na5a5g0kuzZTHwIDAQAB\nAoGAFuf9CgKFBrYRkpGZ3d0M5nDzEJzpC1546ChoKAZrUH/B6gUMe7pirLle6yNf\nQ25YDFcJI5arsyd9VGITJ//zGZC1CC9MBL1v4Ey5Vm3OAwcn7aoiPYoZhtNUDGhE\nCKzIrKWlq5wQDfYCjL2zQnCIAq+nZWACI/X+k/bPd37FZpUCQQDdQNQ3Azaq0owx\nd2crResCW4OryvhTPipLNz8AaW2IMuDfxLUKEaTTkU3NOFRRhIddRRA9/vfcHbrw\nlgZ3Vo5NAkEA+hWX0tItz4lL4pSJTc38Tzjb9WyGQPuAINlntnDwOhtvvRYPfTLi\nLb/22btAfgQWSBICxFdO5Ze0A5Dx140VGwJARwVhWYtZh/nv8I0Ae/6EkowntwR/\nM9FXqC9CtPIiq76ROqMc7e999j/FNqPnRQeCoCjkLtJiY7DTahjuWG5bXQJBAIAD\nS5scAV0pz5FlLT+JgGzhEx729WYQF085WjB2cVGdN75Xq4gP4t0+VVKw2ltnJiyw\nI4BznKxD0l689D69Nh8CQQDLkom4Fhkl8CZQLB1cIX9PjNw+KCBkTV92dJmzdmR5\nGE+p7jO849HPS83W21AV6/eyL8VMqDyE6CBzHNr2ITJT\n-----END RSA PRIVATE KEY-----'
|
|
||||||
|
|
||||||
pub_key_licenseserver= "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCG54kIgf8wi+WLrmg0OLXTsMF7BsYjJ8+mmx1/Ml1Hts2oVoisf8iKbfcC0jWBc1aEibi7EIZK9AWEmgpIHPZpf2Ezt36KX7pjA7CDgZBye/bw+G1CaDGxrN8a18db8c16hNxHMTMiqPm7WAgoyekOzlCT6/rqF+3w2oYuGx1tmQIDAQAB-----END PUBLIC KEY-----"
|
|
||||||
|
|
||||||
|
|
||||||
def make_key_pair_rsa(username):
|
|
||||||
random_generator = Random.new().read
|
|
||||||
priv_key = RSA.generate(1024, random_generator)
|
|
||||||
pub_key = priv_key.publickey()
|
|
||||||
print("new key pair")
|
|
||||||
print(priv_key.exportKey())
|
|
||||||
print(pub_key.exportKey())
|
|
||||||
user_smartcard_path = "/tmp/smartcards/" + str(username) + ".txt"
|
|
||||||
file_object = open(user_smartcard_path, "w+")
|
|
||||||
file_object.write(priv_key.exportKey().decode('utf-8'))
|
|
||||||
file_object.write("\n")
|
|
||||||
file_object.write(pub_key.exportKey().decode('utf-8'))
|
|
||||||
file_object.close()
|
|
||||||
return pub_key.exportKey().decode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
def make_rand_key_aes():
|
|
||||||
return os.urandom(32)
|
|
||||||
|
|
||||||
|
|
||||||
def pad(s):
|
|
||||||
return s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode()
|
|
||||||
|
|
||||||
|
|
||||||
def unpad(s):
|
|
||||||
return s[:-ord(s[len(s)-1:])]
|
|
||||||
|
|
||||||
|
|
||||||
def encrypt_aes(message, key):
|
|
||||||
message = message.encode()
|
|
||||||
raw = pad(message)
|
|
||||||
cipher = AES.new(key, AES.MODE_ECB)
|
|
||||||
enc = cipher.encrypt(raw)
|
|
||||||
return b64encode(enc).decode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
def decrypt_aes(enc, key):
|
|
||||||
enc = b64decode(enc)
|
|
||||||
cipher = AES.new(key, AES.MODE_ECB)
|
|
||||||
dec = cipher.decrypt(enc)
|
|
||||||
return dec.decode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
def make_encrypted_key_content_server():
|
|
||||||
random_key = make_rand_key_aes()
|
|
||||||
key = RSA.importKey(pub_key_contentserver)
|
|
||||||
pub_key = key.publickey()
|
|
||||||
encrypted_key = encrypt(random_key, pub_key)
|
|
||||||
return encrypted_key.hex()
|
|
||||||
|
|
||||||
|
|
||||||
def decrypt(ciphertext):
|
|
||||||
key = RSA.importKey(private_key_contentserver)
|
|
||||||
cipher = PKCS1_OAEP.new(key)
|
|
||||||
ciphertext = codecs.decode(ciphertext, 'hex')
|
|
||||||
return cipher.decrypt(ciphertext)
|
|
||||||
|
|
||||||
|
|
||||||
def encrypt(message):
|
|
||||||
cipher = PKCS1_OAEP.new(pub_key_contentserver)
|
|
||||||
return cipher.encrypt(message)
|
|
||||||
|
|
||||||
|
|
||||||
def sign(message, priv_key):
|
|
||||||
priv_key = RSA.importKey(priv_key)
|
|
||||||
signer = PKCS1_v1_5.new(priv_key)
|
|
||||||
hash_gen = SHA256.new()
|
|
||||||
hash_gen.update(message.encode())
|
|
||||||
return b64encode(signer.sign(hash_gen)).decode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
def verify(message, signature, pub_key):
|
|
||||||
pub_key = pub_key.replace("-----BEGIN PUBLIC KEY-----", "")
|
|
||||||
pub_key = pub_key.replace("-----END PUBLIC KEY-----", "")
|
|
||||||
pub_key = pub_key.replace(" ", "")
|
|
||||||
pub_key = ('\n'.join(pub_key[i:i + 64] for i in range(0, len(pub_key), 64)))
|
|
||||||
pub_key = "-----BEGIN PUBLIC KEY-----\n" + pub_key + "\n-----END PUBLIC KEY-----"
|
|
||||||
signature = b64decode(signature)
|
|
||||||
pub_key = RSA.importKey(pub_key)
|
|
||||||
verifier = PKCS1_v1_5.new(pub_key)
|
|
||||||
hash_gen = SHA256.new(message.encode())
|
|
||||||
return verifier.verify(hash_gen, signature)
|
|
||||||
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.dispatch import receiver
|
|
||||||
from django.db.models.signals import post_save
|
|
||||||
|
|
||||||
|
|
||||||
class FolderInfo(models.Model):
|
|
||||||
"""Adding attributes to default model user"""
|
|
||||||
patient = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, default="")
|
|
||||||
pub_key = models.CharField(max_length=300, blank=True, default="")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""String for representing the Model object."""
|
|
||||||
return str(self.id)
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=User)
|
|
||||||
def create_folderinfo(sender, instance, created, **kwargs):
|
|
||||||
"""Creates Folderinfo for user when he is created"""
|
|
||||||
if created:
|
|
||||||
FolderInfo.objects.create(patient=instance)
|
|
||||||
|
|
||||||
|
|
||||||
class FolderPart_Name(models.Model):
|
|
||||||
shortcut = models.CharField(max_length=3, default="x")
|
|
||||||
part_name = models.CharField(max_length=40, primary_key=True, default="x")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""String for representing the Model object."""
|
|
||||||
return str(self.part_name)
|
|
||||||
|
|
||||||
|
|
||||||
class FolderPart(models.Model):
|
|
||||||
part_class = models.ForeignKey(FolderPart_Name, on_delete=models.CASCADE, default="")
|
|
||||||
folder_id = models.ForeignKey(FolderInfo, on_delete=models.CASCADE, default="")
|
|
||||||
part_context = models.CharField(max_length=500, default="nothing for you")
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
unique_together = ('part_class', 'folder_id')
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""String for representing the Model object."""
|
|
||||||
return self.part_class.part_name
|
|
||||||
|
|
||||||
|
|
||||||
class JustifiedKey(models.Model):
|
|
||||||
part = models.ForeignKey(FolderPart, on_delete=models.CASCADE, null=True, default="")
|
|
||||||
justified_name = models.ForeignKey(User, on_delete=models.CASCADE, default="")
|
|
||||||
key = models.CharField(max_length=260, default="")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
|||||||
from abc import ABC
|
|
||||||
|
|
||||||
from django.contrib.auth.models import User, Group
|
|
||||||
from rest_framework import serializers
|
|
||||||
from health_view.models import FolderPart, JustifiedKey, FolderPart_Name, FolderInfo
|
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = User
|
|
||||||
fields = ['url', 'username', 'email', 'groups']
|
|
||||||
|
|
||||||
|
|
||||||
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Group
|
|
||||||
fields = ['url', 'name']
|
|
||||||
|
|
||||||
|
|
||||||
class KeySerializer(serializers.Serializer):
|
|
||||||
part = serializers.CharField()
|
|
||||||
justified_name = serializers.CharField(max_length=100)
|
|
||||||
key = serializers.CharField(max_length=260)
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
part = FolderPart.objects.get(pk=validated_data.get("part_class"))
|
|
||||||
justified_name = FolderPart.objects.get(pk=validated_data.get("part_class"))
|
|
||||||
key = validated_data.get("part_key")
|
|
||||||
JustifiedKey(part=part, justified_name=justified_name, key=key)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
instance.part = FolderPart.objects.get(pk=validated_data.get("part_class"))
|
|
||||||
instance.justified_name = FolderPart.objects.get(pk=validated_data.get("part_class"))
|
|
||||||
instance.key = instance.part_context = validated_data.get("part_key")
|
|
||||||
instance.save()
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class ContentSerializer(serializers.Serializer):
|
|
||||||
part_class = serializers.CharField()
|
|
||||||
folder_id = serializers.CharField()
|
|
||||||
part_context = serializers.CharField()
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
instance.part_class = FolderPart_Name.objects.get(pk=validated_data.get("part_class"))
|
|
||||||
instance.folder_id = FolderInfo.objects.get(pk=validated_data.get("folder_id"))
|
|
||||||
instance.part_context = validated_data.get("part_context")
|
|
||||||
instance.save()
|
|
||||||
return instance
|
|
||||||
|
|
||||||
|
|
||||||
class FolderPartSerializer(serializers.Serializer):
|
|
||||||
part = serializers.CharField()
|
|
||||||
justified_name = serializers.CharField()
|
|
||||||
key = serializers.CharField()
|
|
||||||
|
|
||||||
|
|
||||||
class FolderPartNameSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = FolderPart_Name()
|
|
||||||
fields = ['part_name']
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
@ -1,12 +0,0 @@
|
|||||||
from django.urls import path
|
|
||||||
from . import views
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path('key/<name>/<justified>', views.get_key),
|
|
||||||
path('content/<name>/', views.get_content),
|
|
||||||
path('folder/create/', views.create_new_folder),
|
|
||||||
path('create/key/', views.create_key),
|
|
||||||
path('folder/read/', views.read_folder),
|
|
||||||
path('folder/write/', views.write_folder),
|
|
||||||
path('manage/delete/', views.delete_justified_key),
|
|
||||||
]
|
|
@ -1,270 +0,0 @@
|
|||||||
from rest_framework import viewsets, permissions
|
|
||||||
from django.http import HttpResponse, JsonResponse
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
|
||||||
from rest_framework.parsers import JSONParser
|
|
||||||
from health_view.serializers import *
|
|
||||||
from health_view.crypto_functions import *
|
|
||||||
from datetime import datetime
|
|
||||||
from rest_framework.decorators import api_view, permission_classes
|
|
||||||
from rest_framework.permissions import IsAdminUser
|
|
||||||
from rest_framework.response import Response
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def get_key(request, name, part_name="", justified=""):
|
|
||||||
user_obj = User.objects.get(username=name)
|
|
||||||
justified_obj = User.objects.get(username=justified)
|
|
||||||
folderinfo = user_obj.folderinfo
|
|
||||||
folderpart_obj = FolderPart.objects.get(part_class=part_name, folder_id=folderinfo)
|
|
||||||
key = JustifiedKey.objects.filter(justified_name=justified_obj, part=folderpart_obj).first()
|
|
||||||
if request.method == 'GET':
|
|
||||||
serializer = KeySerializer(key)
|
|
||||||
return JsonResponse(serializer.data)
|
|
||||||
elif request.method == 'POST':
|
|
||||||
data = JSONParser().parse(request)
|
|
||||||
serializer = KeySerializer(key, data=data)
|
|
||||||
if serializer.is_valid():
|
|
||||||
serializer.save()
|
|
||||||
return JsonResponse(serializer.data, status=201)
|
|
||||||
return JsonResponse(serializer.errors, status=400)
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def get_content(request, name, part_name=""):
|
|
||||||
user_obj = User.objects.get(username=name)
|
|
||||||
folderinfo = user_obj.folderinfo
|
|
||||||
folderpart_obj = FolderPart.objects.get(part_class=part_name, folder_id=folderinfo)
|
|
||||||
if request.method == 'GET':
|
|
||||||
serializer = ContentSerializer(folderpart_obj)
|
|
||||||
return JsonResponse(serializer.data)
|
|
||||||
elif request.method == 'POST':
|
|
||||||
data = json.loads(request.body)
|
|
||||||
serializer = ContentSerializer(folderpart_obj, data=data)
|
|
||||||
if serializer.is_valid():
|
|
||||||
serializer.save()
|
|
||||||
return JsonResponse(serializer.data, status=201)
|
|
||||||
return JsonResponse(serializer.errors, status=400)
|
|
||||||
|
|
||||||
|
|
||||||
def create_signature_string(license):
|
|
||||||
signature_string = license["patient"] + "&" + license["justified"] + "&" + license["creator"] + "&" + license["expdate"].replace(" ", ",") + "&" + license["permissions"] + "&" + license["folderparts"]
|
|
||||||
signature_string = signature_string.replace(" ", "")
|
|
||||||
return signature_string
|
|
||||||
|
|
||||||
|
|
||||||
def create_signature_string_certificate(license):
|
|
||||||
signature_string = license["patient"] + "&" + license["justified"] + "&" + license["creator"] + "&" + license["expdate"].replace(" ", ",") + "&" + license["permissions"] + "&" + license["folderparts"] + "&" + license["signature"] + "&" + license['content_key']
|
|
||||||
signature_string = signature_string.replace(" ", "")
|
|
||||||
return signature_string
|
|
||||||
|
|
||||||
|
|
||||||
def get_creator(license):
|
|
||||||
creator = User.objects.get(username=license["creator"])
|
|
||||||
return creator
|
|
||||||
|
|
||||||
|
|
||||||
def get_pubkey(user):
|
|
||||||
pubkey = user.folderinfo.pub_key
|
|
||||||
return pubkey
|
|
||||||
|
|
||||||
|
|
||||||
def check_expiration_date(license):
|
|
||||||
exp_date = license["expdate"]
|
|
||||||
print(exp_date)
|
|
||||||
for fmt in ('%d-%m-%Y %H:%M', '%d/%m/%Y %H:%M', '%d/%m/%Y', '%d-%m-%Y'):
|
|
||||||
try:
|
|
||||||
datetime_object = datetime.strptime(exp_date, fmt)
|
|
||||||
break
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
return datetime.now() < datetime_object
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def check_permissions(license, part, permission):
|
|
||||||
if part == "":
|
|
||||||
return True
|
|
||||||
if permission not in license["permissions"]:
|
|
||||||
return False
|
|
||||||
if part not in license["folderparts"]:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def check_change_siganture(pubkey, user_sign, datetime_given, content):
|
|
||||||
message = datetime_given + "|" + content
|
|
||||||
if verify(message, user_sign, pubkey):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def check_license(license, folderpart="", permission=""):
|
|
||||||
creator = get_creator(license)
|
|
||||||
if not verify(create_signature_string(license), license['signature'], get_pubkey(creator)):
|
|
||||||
return False
|
|
||||||
if not verify(create_signature_string_certificate(license), license['serversign'], pub_key_licenseserver):
|
|
||||||
return False
|
|
||||||
if not check_expiration_date(license):
|
|
||||||
return False
|
|
||||||
if not check_permissions(license, folderpart, permission):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def read_folder(request):
|
|
||||||
if request.method == 'POST':
|
|
||||||
data = json.loads(request.body)
|
|
||||||
license = data[0]
|
|
||||||
folderpart = data[1]
|
|
||||||
if not check_license(license, folderpart, "Read"):
|
|
||||||
return HttpResponse(status=404)
|
|
||||||
content_key = license['content_key']
|
|
||||||
content_key_decrypted = decrypt(content_key)
|
|
||||||
patient = User.objects.get(username=license["patient"])
|
|
||||||
part_class = FolderPart_Name.objects.get(part_name=folderpart)
|
|
||||||
part = FolderPart.objects.get(folder_id=patient.folderinfo, part_class=part_class)
|
|
||||||
justified = User.objects.get(username=license["justified"])
|
|
||||||
pubkey_justified = justified.folderinfo.pub_key
|
|
||||||
if len(data) == 3:
|
|
||||||
justified = User.objects.get(username=license["creator"])
|
|
||||||
key_obj = JustifiedKey.objects.get(part=part, justified_name=justified)
|
|
||||||
content = part.part_context
|
|
||||||
decrypt_content = decrypt_aes(content, content_key_decrypted)
|
|
||||||
response_obj = {'content': decrypt_content,
|
|
||||||
'key': key_obj.key,
|
|
||||||
'pubkey': pubkey_justified}
|
|
||||||
return JsonResponse(response_obj, status=201)
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def write_folder(request):
|
|
||||||
if request.method == 'POST':
|
|
||||||
data = json.loads(request.body)
|
|
||||||
license = data[0]
|
|
||||||
folderpart = data[1]
|
|
||||||
content = data[2]
|
|
||||||
datetime_given = data[3]
|
|
||||||
user_sign = data[4]
|
|
||||||
if not check_license(license, folderpart, "Write"):
|
|
||||||
return HttpResponse(status=404)
|
|
||||||
content_key = license['content_key']
|
|
||||||
datetime_given_formatted = datetime.strptime(datetime_given, '%Y-%m-%d|%H:%M:%S')
|
|
||||||
date_difference = datetime.now() - datetime_given_formatted
|
|
||||||
content_key_decrypt = decrypt(content_key)
|
|
||||||
patient = User.objects.get(username=license["patient"])
|
|
||||||
part_class = FolderPart_Name.objects.get(part_name=folderpart)
|
|
||||||
part = FolderPart.objects.get(folder_id=patient.folderinfo, part_class=part_class)
|
|
||||||
justified = User.objects.get(username=license["justified"])
|
|
||||||
if date_difference.seconds//60.0 > 4.0 or not check_change_siganture(get_pubkey(justified), user_sign, datetime_given, content):
|
|
||||||
return HttpResponse(status=404)
|
|
||||||
content = folderpart + content
|
|
||||||
part.part_context = encrypt_aes(content, content_key_decrypt)
|
|
||||||
if JustifiedKey.objects.filter(part=part, justified_name=justified).exists():
|
|
||||||
part.save()
|
|
||||||
json_obj = {'works': 'fined'}
|
|
||||||
return JsonResponse(json_obj, status=201)
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def create_new_folder(request):
|
|
||||||
if request.method == 'POST':
|
|
||||||
data = json.loads(request.body)
|
|
||||||
print(data)
|
|
||||||
license = data[0]
|
|
||||||
if not check_license(license):
|
|
||||||
return HttpResponse(status=404)
|
|
||||||
content_key = license['content_key']
|
|
||||||
content_key_decrypt = decrypt(content_key)
|
|
||||||
patient = User.objects.get(username=license["patient"])
|
|
||||||
for c in range(1, len(data)):
|
|
||||||
part_class = data[c]["part_class"]
|
|
||||||
content = data[c]["content"]
|
|
||||||
content = part_class + content
|
|
||||||
encrypted_key = data[c]["encrypted_key"]
|
|
||||||
encrypted_content = encrypt_aes(content, content_key_decrypt)
|
|
||||||
part_class = FolderPart_Name.objects.get(part_name=part_class)
|
|
||||||
part = FolderPart(folder_id=patient.folderinfo, part_class=part_class, part_context=encrypted_content)
|
|
||||||
part.save()
|
|
||||||
justified = User.objects.get(username=license["justified"])
|
|
||||||
justified_key = JustifiedKey(part=part, justified_name=justified, key=encrypted_key)
|
|
||||||
justified_key.save()
|
|
||||||
json_obj = {'works': 'fined'}
|
|
||||||
return JsonResponse(json_obj, status=201)
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def create_key(request):
|
|
||||||
if request.method == 'POST':
|
|
||||||
data = json.loads(request.body)
|
|
||||||
license = data[0]
|
|
||||||
part_class = data[1]
|
|
||||||
key = data[2]
|
|
||||||
if not check_license(license):
|
|
||||||
return HttpResponse(status=404)
|
|
||||||
patient = User.objects.get(username=license["patient"])
|
|
||||||
part_class = FolderPart_Name.objects.get(part_name=part_class)
|
|
||||||
justified = User.objects.get(username=license["justified"])
|
|
||||||
part = FolderPart.objects.get(folder_id=patient.folderinfo, part_class=part_class)
|
|
||||||
if not JustifiedKey.objects.filter(part=part, justified_name=justified, key=key).exists():
|
|
||||||
justified_key = JustifiedKey(part=part, justified_name=justified, key=key)
|
|
||||||
justified_key.save()
|
|
||||||
content_response = {"done": 1}
|
|
||||||
return JsonResponse(content_response, status=201)
|
|
||||||
|
|
||||||
|
|
||||||
@api_view(['POST'])
|
|
||||||
@csrf_exempt
|
|
||||||
@permission_classes([IsAdminUser])
|
|
||||||
def delete_justified_key(request):
|
|
||||||
post_content = json.loads(request.body)
|
|
||||||
print(post_content)
|
|
||||||
patient = post_content['patient']
|
|
||||||
justified = post_content['justified']
|
|
||||||
folder_parts_delete_key = post_content['folder_parts']
|
|
||||||
old_total_key = post_content['old_total_key']
|
|
||||||
new_total_key = post_content['new_total_key']
|
|
||||||
old_total_key_decrypt = decrypt(old_total_key)
|
|
||||||
new_total_key_decrypt = decrypt(new_total_key)
|
|
||||||
patient = User.objects.get(username=patient)
|
|
||||||
justified = User.objects.get(username=justified)
|
|
||||||
all_folder_parts = FolderPart_Name.objects.all().values_list()
|
|
||||||
for part in all_folder_parts:
|
|
||||||
folder_part_name_object = FolderPart_Name.objects.get(part_name=part[1])
|
|
||||||
folder_part_object = FolderPart.objects.get(part_class=folder_part_name_object,folder_id=patient.folderinfo)
|
|
||||||
decrypted_content = decrypt_aes(folder_part_object.part_context, old_total_key_decrypt)
|
|
||||||
encrypted_content = encrypt_aes(decrypted_content, new_total_key_decrypt)
|
|
||||||
folder_part_object.part_context = encrypted_content
|
|
||||||
folder_part_object.save()
|
|
||||||
for part in folder_parts_delete_key:
|
|
||||||
folder_part_name_object = FolderPart_Name.objects.get(part_name=part)
|
|
||||||
folder_part_object = FolderPart.objects.get(folder_id=patient.folderinfo, part_class=folder_part_name_object)
|
|
||||||
key = JustifiedKey.objects.filter(part=folder_part_object, justified_name=justified)
|
|
||||||
key.delete()
|
|
||||||
return Response(status=201)
|
|
||||||
|
|
||||||
|
|
||||||
class UserViewSet(viewsets.ModelViewSet):
|
|
||||||
"""
|
|
||||||
API endpoint that allows users to be viewed or edited.
|
|
||||||
"""
|
|
||||||
queryset = User.objects.all().order_by('-date_joined')
|
|
||||||
serializer_class = UserSerializer
|
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
|
||||||
|
|
||||||
|
|
||||||
class GroupViewSet(viewsets.ModelViewSet):
|
|
||||||
"""
|
|
||||||
API endpoint that allows groups to be viewed or edited.
|
|
||||||
"""
|
|
||||||
queryset = Group.objects.all()
|
|
||||||
serializer_class = GroupSerializer
|
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
|
||||||
|
|
||||||
|
|
||||||
class GetFolderPartNames(viewsets.ModelViewSet):
|
|
||||||
queryset = FolderPart_Name.objects.all()
|
|
||||||
serializer_class = FolderPartNameSerializer
|
|
@ -6,8 +6,8 @@ import requests
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
#needs logindata from admin account form Contentserver
|
#logindata for admin acc on Contentserver
|
||||||
loginname_restapi = ''
|
loginname_restapi = ''
|
||||||
passwort_restapi = ''
|
passwort_restapi = ''
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,5 +8,4 @@ urlpatterns = [
|
|||||||
path('license/<int:fid>/create/', views.create_license, name='create-license'),
|
path('license/<int:fid>/create/', views.create_license, name='create-license'),
|
||||||
path('license/show/<int:pk>/own/', views.get_license_details, name='license-detail-own'),
|
path('license/show/<int:pk>/own/', views.get_license_details, name='license-detail-own'),
|
||||||
path('license/show/<int:pk>/given/', views.get_license_details, name='license-detail-given'),
|
path('license/show/<int:pk>/given/', views.get_license_details, name='license-detail-given'),
|
||||||
path('delete_license', views.delete_license, name='delete_license')
|
|
||||||
]
|
]
|
@ -179,6 +179,3 @@ def create_license(request, fid):
|
|||||||
context = {'form': form}
|
context = {'form': form}
|
||||||
return render(request, 'health_view/create_license.html', context)
|
return render(request, 'health_view/create_license.html', context)
|
||||||
|
|
||||||
|
|
||||||
def delete_license(request):
|
|
||||||
print("test")
|
|
||||||
|
90
requirements.txt
Normal file
90
requirements.txt
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
appdirs==1.4.4
|
||||||
|
apturl==0.5.2
|
||||||
|
asgiref==3.3.1
|
||||||
|
bcrypt==3.1.7
|
||||||
|
blinker==1.4
|
||||||
|
Brlapi==0.7.0
|
||||||
|
certifi==2019.11.28
|
||||||
|
chardet==3.0.4
|
||||||
|
Click==7.0
|
||||||
|
colorama==0.4.3
|
||||||
|
command-not-found==0.3
|
||||||
|
crypto==1.4.1
|
||||||
|
cryptography==2.8
|
||||||
|
cupshelpers==1.0
|
||||||
|
dbus-python==1.2.16
|
||||||
|
defer==1.0.6
|
||||||
|
distlib==0.3.1
|
||||||
|
distro==1.4.0
|
||||||
|
distro-info===0.23ubuntu1
|
||||||
|
Django==3.1.4
|
||||||
|
django-cors-headers==3.7.0
|
||||||
|
django-filter==2.4.0
|
||||||
|
djangorestframework==3.12.2
|
||||||
|
duplicity==0.8.12.0
|
||||||
|
ecdsa==0.16.1
|
||||||
|
entrypoints==0.3
|
||||||
|
fasteners==0.14.1
|
||||||
|
filelock==3.0.12
|
||||||
|
future==0.18.2
|
||||||
|
httpie==1.0.3
|
||||||
|
httplib2==0.14.0
|
||||||
|
idna==2.8
|
||||||
|
keyring==18.0.1
|
||||||
|
language-selector==0.1
|
||||||
|
launchpadlib==1.10.13
|
||||||
|
lazr.restfulclient==0.14.2
|
||||||
|
lazr.uri==1.0.3
|
||||||
|
lockfile==0.12.2
|
||||||
|
louis==3.12.0
|
||||||
|
macaroonbakery==1.3.1
|
||||||
|
Mako==1.1.0
|
||||||
|
Markdown==3.3.3
|
||||||
|
MarkupSafe==1.1.0
|
||||||
|
monotonic==1.5
|
||||||
|
Naked==0.1.31
|
||||||
|
netifaces==0.10.4
|
||||||
|
oauthlib==3.1.0
|
||||||
|
olefile==0.46
|
||||||
|
paramiko==2.6.0
|
||||||
|
pexpect==4.6.0
|
||||||
|
Pillow==7.0.0
|
||||||
|
protobuf==3.6.1
|
||||||
|
pycairo==1.16.2
|
||||||
|
pycrypto==2.6.1
|
||||||
|
pycryptodome==3.9.9
|
||||||
|
pycups==1.9.73
|
||||||
|
Pygments==2.3.1
|
||||||
|
PyGObject==3.36.0
|
||||||
|
PyJWT==1.7.1
|
||||||
|
pymacaroons==0.13.0
|
||||||
|
PyNaCl==1.3.0
|
||||||
|
PyQt5==5.15.1
|
||||||
|
PyQt5-sip==12.8.1
|
||||||
|
pyqt5-tools==5.15.1.1.7.4
|
||||||
|
pyRFC3339==1.1
|
||||||
|
python-apt==2.0.0+ubuntu0.20.4.3
|
||||||
|
python-dateutil==2.7.3
|
||||||
|
python-debian===0.1.36ubuntu1
|
||||||
|
python-dotenv==0.14.0
|
||||||
|
pytz==2019.3
|
||||||
|
pyxdg==0.26
|
||||||
|
PyYAML==5.3.1
|
||||||
|
reportlab==3.5.34
|
||||||
|
requests==2.22.0
|
||||||
|
requests-unixsocket==0.2.0
|
||||||
|
SecretStorage==2.3.1
|
||||||
|
shellescape==3.8.1
|
||||||
|
simplejson==3.16.0
|
||||||
|
six==1.14.0
|
||||||
|
sqlparse==0.4.1
|
||||||
|
systemd-python==234
|
||||||
|
ubuntu-advantage-tools==20.3
|
||||||
|
ubuntu-drivers-common==0.0.0
|
||||||
|
ufw==0.36
|
||||||
|
unattended-upgrades==0.1
|
||||||
|
urllib3==1.25.8
|
||||||
|
usb-creator==0.3.7
|
||||||
|
virtualenv==20.2.2
|
||||||
|
wadllib==1.3.3
|
||||||
|
xkit==0.0.0
|
Loading…
x
Reference in New Issue
Block a user