Looking for good programming challenges?

Use the search below to find our solutions for selected questions!

Distributed system for data security and data privacy – Part 2

Sharing is caring!

In the first part, I have described how one can design a distributed system for maximum security and data privacy. Now its time to provide a sample technology stack for such a system as well as a basic functioning prototype.

Technology Stack
Our architecture will make use of the following technologies:

Purpose Technology
Frontend AngularJS, HTML5, JavaScript, CSS(3)
Backend Java 1.8+
Application Server Apache Tomcat
Application Framework Spring Framework (Spring MVC, Spring Core, Spring Security, Spring Test)
REST Spring Framework (Spring MVC), Jackson
ORM Hibernate, Spring ORM
Database Encryprion Jasypt, Bouncy Castle
RDBMS MySQL(MariaDB or Oracle MySQL)
Testing JUnit, Spring Test
Build Automation Gradle

The modules will not have a separate GUI, but rather will be steered using one GUI (e.g. index.html) from the user’s browser which will be provided by the APP module. The basic Tier & Technology stack for each module will look as follows:

Architecture & Technology Stack
Distributed system for data security and data privacy

In all modules (APP, IDAT, PSNS and VDAT) the REST Service layer can be thought of as the public API of the module. That is, it will consist of a collection of RestControllers that handle HTTP requests and execute the appropriate service functionality. The View is available only in the APP since the APP will provide the GUI for the application to the end user in addition to the regular API functionality.

The REST service will be used by the frontend (browser) using AngularJS. It provides functions for authentication, fetching and resolving pseudonyms, etc.

Below are listed some of the available RESTful web service operations. For a full list of available operations please refer to the available API. In many cases we make use of the HTTP POST method instead of GET, to avoid exposing sensitive information via the URL.

POST Authenticate with user credentials
Authenticate using username and password.

Resource: /services/authenticate

Method: POST

Parameter: TXLUserCredentialsDTO the username and password

Returns: TXLUserDTO The authenticated user.


var credentials = {"username": "puser1", "password": "s3cret"};

$http.post(host + "/services/authenticate", credentials).success(function (user, status, headers) {
    var token = headers()[TXL_CONFIG.AUTH_HEADER];
    if (token) {
}).error(function () {
    console.log("Authentication failed for username '"+credentials.username+"'");

POST Fetch EID for user
Get EID(PSN1) for user.

Resource: /rest/client/eidForUser

Method: POST

Parameter: TXLUserDTO the user you want its EID

Returns: TXLPsnDTO The EID of the user.


var user = {"username": "ecuser1"};
    url: TXL_CONFIG.IDAT_HOST + "/rest/client/eidForUser",
    method: "POST",
    headers: headers,
    data: user
}).success(function (eid) {

POST Resolve pseudonym
Resolve a given pseudonym. From PSN1 -> PSN2 or PSN2 -> PSN1, depending on where we come from. For instance a TXLCase (VDAT) holds a client profile pseudonym of type PSN1 that needs to be resolved to a pseudonym of type PSN2, which is the pseudonym of the client profile in IDAT. Here we come from VDAT and want to fetch something in IDAT (PSN1 -> PSN2).

Another example would be fetching the cases of a client with EID (PSN1) in IDAT. The EID (PSN1) needs to be resolved to PSN2(s), which are the pseudonyms of TXLCases in VDAT. Here we come from IDAT and want to fetch something in VDAT. Again this is a PSN1 -> PSN2 resolving.

Another example is the case when we have an existing client profile (IDAT) that has a pseudonym (PSN2), that we want to assign to a new case. Here we need to know the PSN1 counterpart so that we can assign it to the case.clientProfilePsnToBeResolved property of the TXLCase in VDAT. For that we ask the PSNS to resolve a pseudonym of type PSN2 and give us the PSN1 counterpart. The PSNS will return an array of counterparts, but it will optimally contain only one pseudonym of type PSN1. This is a PSN2 -> PSN1 resolving.

Resource: /rest/resolve

Method: POST

Parameter: TXLPsnDTO the pseudonym to resolve

Returns: TXLPsnDTO[] Array of counterpart pseudonyms corresponding to the pseudonym to resolve.


var psnToResolve = {"type":{"name":"PSN2"},"value":"ebad4277-399c-48a1-9c93-a38ced158c1f"};
    url: TXL_CONFIG.PSNS_HOST + "/rest/resolve",
    method: "POST",
    headers: headers,
    data: psnToResolve
}).success(function (resolvedPsn) {
    for (var i = 0; i < resolvedPsn.length; i++) { 


POST Fetch case by pseudonym

Fetch a case that has the given pseudonym.

Resource: /rest/case/caseWithPsn

Method: POST

Parameter: TXLPsnDTO the pseudonym of the case

Returns: TXLCaseDTO the case object


var casePsn = {"type":{"name":"PSN1"},"value":"ebad4277-399c-48a1-9c93-a38ced158c1f"};
    url: TXL_CONFIG.VDAT_HOST + "/rest/case/caseWithPsn",
    method: 'POST',
    headers: headers,
    data: casePsn
}).success(function (txlCase) {

The full working prototype along with IDE setup instructions is available here.