CyberCAPTOR-P2DS

Licence

This project contains ZHAW’s Contribution towards Privacy-Preserving Data Sharing (P2DS) for the Cybersecurity GE in FIWARE.

Copyright © 2015 Zürcher Hochschule der Angewandten Wissenschaften (ZHAW).

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Table of Contents

Architecture

The SEPIA library has rather fixed ideas of how communication between the various peers should happen, and it is unfortunately rather difficult to untangle these from the basic protocols.

At its base, SEPIA creates a thread for every peer, and that thread communicates with other peers through messages that signify events. When a peer waits for a message, it blocks at a socket. Needless to say, this is not nice when in the context of servlets. We solve this problem by spawning a thread for every peer, and then connecting the input of the thread to a blocking message queue. Whenever the servlet receives a message that’s for a particular thread, the servlet extracts the message, verifies its signature (which has to be done separately from SSL for techncial reasons) and puts it into the message queue.

P2DS Installation and Administration Guide

Setting Up

You need at least four parties in order for P2DS to work: three parties have data on which they want to perform a computation, and one party manages that computation. Neither party needs to trust any other party. The parties having the data host input and privacy peers and the managing party hosters the group manager.

Installing the Services
Installing from WAR

You should have received three WAR files as part of the P2DS distribution, or you can build them yourself; see below.

  • p2ds-group-management.war contains the group manager
  • p2ds-peer.war contains peers
  • p2ds-receiver.war may be used for demo purposes (receives final results)

These must be deployed on application servers. Deploy p2ds-group-management.war on your group manager and deploy the pe2ds-peer.war on each organisation that wants to participate in the computation. Additionally you can also deploy the receiver, but you should write your own endpoint.

Installing from Source

In order to build and compile the services from source code, first get the source, then build:

git clone https://github.com/fiware-cybercaptor/cybercaptor-P2DS
cd sepia
mvn install -DskipTests
cd ../p2ds
mvn package

Now the directories group-management/target, peer/target, and receiver/target will contain the respective WAR files.

Generating Key Pairs

All messages that are exchanged in P2DS are digitally signed. Additionally, all parties should employ TLS. Digital signatures are needed to be able to check the messages by the receiving parties in addition to the transport security offered by TLS. And TLS is needed because in some cases, sensitive information like an authentication token is transported in the messages.

First, get and build the P2DS key generation program:

git clone https://github.engineering.zhaw.ch/munt/p2dsKeygen.git
cd p2dsKeygen
mvn package -DskipTests

Next, use it to generate a key pair:

java -cp target/keygen-0.0.0.1.jar ch.zhaw.ficore.p2ds.keygen/Main
base64 key.private > key.private.b64
base64 key.public > key.public.b64
srm -s key.private key.public

The last command deletes the (unneeded) binary key files, leaving only the Base64-encoded ones.

This generates an Elliptic Curve DSA key of 409 bits, which is supposed to have the equivalent RSA strength of more than 8192 bits (see here). However, it uses Java’s SecureRandom generator, which has had trouble in the past. So it is probably best to be on the lookout for messages about SecureRandom.

This program generates two files, key.public and key.private, both of which must be uploaded to the respective peer. They can in principle be uploaded to any directory on the application server, but we recommend a directory to which only the applicaiton server has read access. Since it is not necessary to change the key files, once uploaded, we also recommend setting the permissions on these files to read-only. On Unix-like operating systems, do this:

sudo cp key.public.b64 key.private.b64 /var/p2ds
srm -s key.public.b64 key.private.b64
cd /var/p2ds
sudo chown apache key.public.b64 key.private.b64
sudo chmod 444 key.public.b64
sudo chmod 400 key.private.b64
sudo chmod 500 .

Again, the unneeded copies of the key files are securely deleted. This is not important for the pubic key but very important indeed for the private key.

Here, apache is the system’s pseudo user that runs the application server’s processes.

Configuring the Services

Group Management

The Group Management’s database configuration is described in its persistence.xml file:

<?xml version-"1.0"?>
<persistence version-"1.0" xmlns-"http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="p2ds-group-management" transaction-type="RESOURCE_LOCAL">
      <provider>
          org.hibernate.ejb.HibernatePersistence
      </provider>
      <class>ch.zhaw.ficore.p2ds.group.storage.Group</class>
      <class>ch.zhaw.ficore.p2ds.group.storage.Peer</class>
      <class>ch.zhaw.ficore.p2ds.group.storage.Registration</class>
      <properties>
        <property name="hibernate.connection.driver_class"
                  value-"com.mysql.jdbc.Driver"/>
        <property name="hibernate.connection.url"
                  value-"jdbc:mysql://localhost/p2ds"/>
        <property name="hibernate.connection.username"
                  value-"sepia"/>
        <property name="hibernate.connection.password"
                  value-"my=password"/>
        <property name="hibernate.dialect"
                  value-"org.hibernate.dialect.MySQLDialect"/>
        <property name="hibernate.hbm2ddl.auto" value-"create"/>
        <property name="hibernate.show_sql" value-"true"/>
        <property name="hibernate.format_sql" value-"true"/>
      </properties>
  </persistence-unit>
</persistence>

The obviously configurable parameters are hibernate.connection.driver_class, hibernate.connection.url, hibernate.connection.username, and hibernate.connection.password. Change these to suit your database setup.

The group management service’s configuration can be found in the web.xml. You only need to configure the group/adminKey option which is the password for admin functionality.

<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
     see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e194 -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>ch.zhaw.ficore.p2ds</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/res/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

  <env-entry>
      <env-entry-name>peer/adminKey</env-entry-name>
      <env-entry-value>default-admin-key</env-entry-value>
      <env-entry-type> java.lang.String </env-entry-type>
    </env-entry>
</web-app>

Additionally you may want to add some security constraints to disable the GUI from being public. You should read up on tomcat’s security constraints documentation on how to setup security constraints, roles and realms. We recommend using at least http basic auth. In general everything except /group-mgmt/* is something you might not want to be public:

<security-constraint>
  <web-resource-collection>
    <web-resource-name>GUI</web-resource-name>
    <description>all pages</description>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
     <role-name>admins</role-name>
  </auth-constraint>
</security-constraint>
<security-constraint>
  <web-resource-collection>
    <web-resource-name>API</web-resource-name>
    <description>REST-API</description>
    <url-pattern>/group-mgmt/*</url-pattern>
  </web-resource-collection>
  <!-- without auth-constraint == public -->
</security-constraint>
Peer

The peer’s database configuration is also described in the persistence.xml:

<?xml version="1.0"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="p2ds-peer" transaction-type="RESOURCE_LOCAL">
        <provider>
            org.hibernate.ejb.HibernatePersistence
        </provider>
        <class>ch.zhaw.ficore.p2ds.peer.storage.PeerConfiguration</class>
        <properties>
             <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
                <property name="hibernate.connection.url" value="jdbc:mysql://localhost/p2ds_input?user=sepia&amp;password=8M07r8FlZZ"/>
                <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
                <property name="hibernate.hbm2ddl.auto" value="create"/>
                <property name="hibernate.show_sql" value="true"/>
                <property name="hibernate.format_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

You may and should change the properties based on your setup.

The input peer’s configuration is likewise in its web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
     see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e194 -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>ch.zhaw.ficore.p2ds</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

    <env-entry>
        <env-entry-name>peer/url</env-entry-name>
        <env-entry-value>http://localhost:12001/p2ds-peer</env-entry-value>
        <env-entry-type> java.lang.String </env-entry-type>
    </env-entry>

    <env-entry>
      <env-entry-name>peer/adminKey</env-entry-name>
      <env-entry-value>default-admin-key</env-entry-value>
      <env-entry-type> java.lang.String </env-entry-type>
    </env-entry>
</web-app>

You only need to configure the peer/url and peer/adminKey environment entries. peer/url is the url under which the peer service can be contacted (the url you host it at) and peer/adminKey is the admin key for REST-API methods only to be used by the admin.

Note about persistence.xml

<property name="hibernate.hbm2ddl.auto" value="create"/>

The hibernate.hbm2ddl.auto property set to create will re-create the database (deleting existing entries) at every launch of the services. This is a good setting if you are just experimenting with P2DS but it’s not a production setting. You may leave the property on create for the setup phase but once you go live you should absolutely remove it.

P2DS User and Programmer’s Guide

Performing a Computation

This part manual is written mainly for the person who runs the group manager. If you run a peer, start reading from here.

Creating a Group

First, locate your administration key. This can be given to you by the person who installed the group manager WAR file, since it is contained in the web services web.xml file. This administration key should always be appended to any administration URL. For example, if the group manager is installed on grpman.example.com, then the initial URL should be https://grpman.example.com:8080/p2ds-group-management?adminKey=key. (Obviously, substitute the correct port numbers and key value.)

Navigate to the group manager GUI (typically .../p2ds-group-management/). There you will initially see a simple form field, asking you to supply a group name. Let’s say you enter “SimpleGroup” and click on “Create group!”. When you return to the main page and click on the name of your group, you will see something like this:

Overview

Overview

Next, you should set up a configuration. This configuraiton says what you want to compute and how to compute it. If you click on “Configuration”, you should see the following.

Configuration

Configuration

The first element to fill in is “MpcProtocol”. This answers the question “what do you want to compute?”. The only protocol we have definitive demand for is “additive”, meaning that you can compute a vector sum. So you have to put “additive” in that row. (Other protocols include top-k, where you can compute the top k elements of each column. For example, the maximum element would be top-1. However, at the time of writing, we have no demand for that protocol, and, while it is implemented, we do not support it.)

The next element you should fill in is “MaxElement”. This is the largest intermediate result you envisage. For “additive” it’s the largest value you think will occur in a result vector. For example, if you sample “number of attacks” in 1-minute intervals, you should hardly expect more than 1000 attacks, so 1000 is a good value.

Next should be “Field”. This is a prime number larger than MaxElement. In our case, 1013 does the trick. If you are in doubt, you can put the value 263 - 5 = 9223372036854775783 in that field, even though computations in that field will take longer.

Next you should take care of NumberOfTimeSlots and NumberOfItems. What this means is that of you have N = m x n items, you will serve these items n at a time, m times. For example, let’s say you have 6 numbers in your vector. You can choose to compute the vector sum by adding up two numbers, three times; three numbers, two times; one number, six times; or six numbers, once. They will all give the correct result, but some settings will be faster than others, and some settings will also be more robust. For example, if you have more items (large n), the computation will generally be faster, but if you have more time slots (large m), the computation will be more robust against peers failing occasionally. (In R terms, you can have a few “N/A” terms in your result vector.)

A special value for NumberOfTimeSlots is “-1”. This value will cause the peers to run in streaming mode. Usually, peers will run for NumberOfTimeSlots time slots and then shut down. When peers are running in streaming mode, they will forever wait for the next batch of numbers to process. Upside: you don’t have to initiate a new computation when you have new data. Downside: one downed or stuck peer will cause the whole computation to stall.

Finally, you can set ResultBufferSize to control in how many chunks the results are sent to the configured result endpoint (see the configuration guide on how to configure this). If you have ten timeslots and set the result buffer size to 1, then ten final results (one per timeslot) will be sent to the result endpoint. If you configure the result buffer size to be 10, only one large result will be sent, after all timeslots have completed.

If the computation fails, no results are sent. If a peer fails, restart the computation.

Registering the Peers

Next, talk to the administrators of all the participating organisations and give them the URL of your group manager service. They should deploy and configure a peer service on one of their application servers.

Now you can generate registration codes. These codes are one-time codes that peers use to authorise their registration. If you plan on having m input peers and n privacy peers, klick the “Create registration” button m + n times:

Actions

Actions

For each registration code, you should see one “Open registration code”:

Registration

Registration

Give one code per peer to the admins. They will need these codes to register the peers with the group manager. Eventually, you will find a picture like this:

Members

Members

Here we show only one peer, but every peer should be present. Peers have registered, and in registering, they have used up one of the registration codes. There should therefore be no open registration codes at this point.

Peers have registered, but they have not been activated. Only activated peers can participate in the protocol. To do that, talk to each of the admins of each participating organisation and read the public key of their peers to them. These should be identtical to the public keys of those peers that the admins have configured for their peers. Once that is done, click on “Mark as verified”. Rinse and repeat until all peers are verified.

The reason there is an additional verification step is that in principle, everyone can register a peer, but only you, the group manager, gets to decide who can participate in a computation. This step also serves as an authentication step to make sure that the public keys you got from the peers are authentic. This saves you from the hassle that is PKI.

Starting the Peers

Starting the peers is very simple: go to “Actions” and click on “Start peers”:

Actions

Actions

Once that is successful, you should see that “All peers are running”:

Running

Running

Giving the Peers Some Inputs

Once you have created input and privacy peers (refer to the API guide how to do that), you need to give them some inputs. Ideally, you have a web service that does that for you, but if not, you can do that by hand, using curl. Let’s say that your peer is called swisscom:ddos-input-peer-1 and that your NumberOfItems in the peer configuration (see the Group Manager guide above) is 6, since you are sampling every 10 minutes per hour. You have seen 1, 4, 2, 8, 9, and 23 DDoS-attempts, respectively, so there is clearly something going on. Your peer runs on p2ds.swisscom.ch:8080 and your registration code is JKSdh3h7njs (this is part of the peer service’s configuration). Here is how to supply the peer with that input row:

curl -i -v -X POST --header "Content-Type: application/json" \
  -d '{"peerName":"swisscom:ddos-input-peer-1","data":"1;4;2;8;9;23"}' \
  https://p2ds.swisscom.ch:8080/p2ds-peer/input?registrationCode= JKSdh3h7njs
Viewing the Results

The input peers report results back to a URL that is set in the peer’s configuration (the finalResultsURL property). We deliver a very simple results viewer with P2DS, which runs under /receiver. If you configure your input peer’s finalResultsURL to read https://p2ds.swisscom.ch:8080/receiver/receive (substitute correct protocol, hostname, and port), then your results might look like this:

Results

Results

Useful Hints
  • Always use https, never use plain http when feeding data to the input peers. The value of P2DS would be greatly diminished if the supposedly secret data were sent in plain text. The protocol between the peers can be plain http, since P2DS uses encrypted shares already and additional encryption doesn’t buy you much security.
  • Always use https for talking to the group manager.

Using the APIs

Please refer to the API Documentation. Exemplary usage of the APIs can be found in the file grp.sh in the source code’s main directory, available from the github page.

Here is a more verbose version of that file (with some parts skipped to keep this guide shorter). We assume that the admin key is default-admin-key and that the registration codes for all peers is TEST.

Please don’t use default-admin-key and testmode in a production setting.

If you just want to experiment and/or play around otherwise on the shell using curl setting testmode to on can be quite convenient. If in testmode the registration codes generated by the group management service will not be random and Please don’t use testmode=on in production.

#Set group-mgmt service to test mode
#Don't do that in production!
curl -i -v -X POST http://localhost:12001/p2ds-group-management/group-mgmt/testmode?on=true\&adminKey=default-admin-key

To get started we need to create a group on the group management service:

curl -i -v -X POST --header "Content-Type: application/json" -d '{"name":"SimpleGroup"}' http://localhost:12001/p2ds-group-management/group-mgmt/group?adminKey=default-admin-key

Once we have a group we can generate registration codes for peers. The registration code is used by the peers to sign-up for a group. From the output of the previous command (see above) we know the id of the group (in this case 1)

curl -i -v -X POST http://localhost:12001/p2ds-group-management/group-mgmt/registration/1?adminKey=default-admin-key

The above command will give the group management admin a registration code that the admin needs to communicate to the peer operator. In this case the registration code is TEST. The peer operator can now create a peer (named peerhans) on the peer service:

curl -i -v -X POST --header "Content-Type: application/json" -d @./demo/files/peerhans.json http://localhost:12001/p2ds-peer/peer?adminKey=default-admin-key

./demo/files/peerhans.json contains the configuration of the peer:

{
  "finalResultsURL":"http://localhost:12001/p2ds-receiver/receiver/receive",
  "peerType":1,
  "name":"peerhans",
  "privateKey":"MFECAQAwEAYHKoZIzj0CAQYFK4EEACQEOjA4AgEBBDNyjBeP85atxkIfiYqW+0kUB2H3guXcQWXT/tXVktbn3MyUdRmNIL99G3rK1XoGSRAM6js=",
  "publicKey":"MH4wEAYHKoZIzj0CAQYFK4EEACQDagAEAJig6xXX4SuME5lRB2ADn7T7CgyH7LXbxy/oS5XhIElBPwz/40cwDAc/VgGbDKa+HGBc/AGzwSlScoCDHc7WA1tSkRUkaW/lL9NbA6gIzJLMw+FV3RPor0vpJIofVcAaV6WI1r99v8Y=",
  "registrationCode":"TEST",
  "groupMgmtURL":"http://localhost:12001/p2ds-group-management/group-mgmt"}

privateKey and publicKey must be PKCS resp. X.509 encoded as base64. Please generate your own keypairs. peerType=1 refers to an input peer where as peerType=2 refers to a privacy peer.

The peer will automatically sign-up for group membership and will be a member of the group on the group management service but marked as unverified. The peer operater and group admin should exchange fingerprints of the public key to verify the identity of the peer. If the group admin has verified the keys he can then mark the peer as verified:

curl -i -v -X POST http://localhost:12001/p2ds-group-management/group-mgmt/verify/hanspeer?adminKey=default-admin-key\&verified=true

Before we can start any peers we need to set a group configuration. The group configuration defines the parameters of the computation to do:

curl -i -v -X POST --header "Content-Type: application/json" -d '{"field":"1013","gid":"1","maxElement":"1000","mpcProtocol":"additive","numberOfItems":"2","numberOfTimeSlots":"2"}' http://localhost:12001/p2ds-group-management/group-mgmt/configuration?adminKey=default-admin-key

Please note that you will need at least three privacy peers and two input peers for the cryptographic protocol to work. You can start peers individually or let the group management service start all peers together. You can start individual peers by doing:

curl -i -v -X POST http://localhost:12001/p2ds-peer/start/hanspeer?registrationCode=TEST

Please note that the registration code is used as a means of authentication to prevent anybody from starting a peer. It is thus important that registration codes remain secret and are only known the the group management admin and the peer operator of the corresponding peer.

Once we have started all peers (in the case of grp.sh you will have two input peers and three privacy peers) we can add inputs:

curl -i -v -X POST --header "Content-Type: application/json" -d '{"peerName":"hanspeer","data":["1;3","4;5"]}' http://localhost:12001/p2ds-peer/inputs?registrationCode=TEST

P2DS Workflow

Recall the graphic from the README:

Scenario

Scenario

Let’s say we have three organisations, called Domain 1, Domain 2, and Domain 3 in the graphic, that want to know the total number of attacks seen in the last 24 hours, with a granularity of five minutes. In mathematical terms, what these organisations want is x1 + x2 + x3, where x1, x2, and x3 are vectors with 24*60/5 = 288 elements, and they want to do this without revealing their own *xi* to any of the other domains. Here is how the three domains could use P2DS for their needs.

Step 1: Setting Up

This section describes how to set up the group management and the various peers. Some actions have to be done only once, whereas others have to be done for each new computation.

Step 1.1: Set Up Group Management
Step 1.2: Set Up Peers
Step 1.2: Generate Certificates

This process is also described in SEPIA’s User Manual.

First, each organisation generates a public key certificate for each input and privacy peer. There must also be a certificate for the group management service.

Key generation and management is something that is done vastly differently from organisation to organisation. We sketch here a process that will work with Java’s keytool; if your organisation follows a different process, use that. The important thing is that at the end, you have a Base64-encoded self-signed X.509 certificate.

In this example, we first generate a 2048-bit RSA key, which conforms to current best practices; Each organisation should replace the names privacypeer01 with a name that they are more comfortable with. Each organisation must replace privacypeer01KeyPass, which will be the password that unlocks the private key and privacypeer01StorePass, which will be the password that unlocks the keystore.

This command line will generate the key pair, asking for some information about the organisation in the process. This information will be embedded into the key pair.

keytool -genkey -v \  -alias privacypeer01Alias \  -keystore privacypeer01KeyStore.jks \  -storepass privacypeer01StorePass \  -keypass privacypeer01KeyPass \  -keyalg RSA \
  -keysize 2048

Next, generate a self-signed certificate, again replacing the various names with the ones that your organisation has chosen.

~[STRIKEOUT:bashkeytool -export
-alias privacypeer01Alias   -keystore privacypeer01KeyStore.jks

-storepass privacypeer01StorePass   -file privacypeer01Certificate.crt ~]

We will later describe how to upload these certificates to the Group Management.

Step 2: Define a Computation

Now, all the organisations need to get together and define what they want to compute. In this example, it’s x1 + x2 + x3, where each xi is a 288-elements, and they want to do this without revealing their own xi. This must be done outside the P2DS framework, and there are important details to consider that are not part of the framework.

One such detail is the question of time synchronisation. If the local clocks of the IDSes are skewed, then so will be the xi. Worse, if the clocks also show significant drift, the xi will also drift and the final computation will be more noisy and more unreliable. We recommend to connect each timestamping participant to an NTP stratum 1 server (or to connect a stratum 0 time source to it of course).

Once that is decided... (describe here group management -> New Computation -> ...)

Step 3: Define the Group

Now it’s time for the organisations to decide what the peers are that will take part in that computation. They need to drill holes in their firewalls, set up the peers, ...

Then the group manager can either create a new group in the Group Management GUI or reuse an existing one and link the computation defined in the previous step with that group.

Step 4: Prepare the Data

Now the Input Peers need access to the data.

Step 5: Launch the Computation

Step 6: Look at the Results

Information about development is also available in the README file.