Skip to content

Latest commit

 

History

History
452 lines (353 loc) · 14.4 KB

README.md

File metadata and controls

452 lines (353 loc) · 14.4 KB

qkd-net

Overview

The OpenQKDNetwork project aims to provide a reference implementation of a 4-layer Quantum Key Distribution (QKD) network solution. Two sample applications are also provided to show case how an application can fetch and make use of the keys generated by a QKD network.

A very flexible layered approach has been adopted adhering to SOLID principles.

Microservice based architecture approach has been taken for software design and and implementation. One benefit of it is to have flexibility in production deployment.

Complied and tested successfully on Ubuntu 16.04 and Linux Mint 18.3 with Java 8, Ubuntu 20.4/Java 11. Changes will be needed for working in other environments (OS, Java version, etc.)

Layers

  1. Key Management System (KMS)
  2. Quantum Network Layer (QNL)
  3. Quantum Link Layer (QLL)

The fourth layer is the User (or Host) Layer, which belongs to the client of this system, and thus is beyond the scope of this project. QKD devices belong to the QLL, and may need a vendor specific glue layer of code in QLL to make it work with the other layers, before any international standard (e.g. ETSI, ITU-T) on the interface is widely adopted.

Key Management System (KMS)

The KMS layer provides an application interface for fetching keys for symmetric cryptography. The details of how the key is used belong to the applications at the User layer.

KMS layer comprises the following microservices:

  1. Configuration service
  2. Registration Service
  3. Authorization Service
  4. KMS Service
  5. KMS API Gateway Service
  6. KMS QNL Service

Quantum Network Layer (QNL)

QNL is the core compoent to extend the QKD technology from point-to-point to network level. It is the middle layer sandwiched between KMS layer and QLL (Quantum Link Layer). QNL provides key blocks to KMS after fetching it from QLL. Thus, it keeps the KMS layer QKD-technology-agnostic.

QNL currently consists of a single microservice:

  1. Key Routing Service

Key Routing Service contains a routing modual and key relaying modual, to react to the QKD network topology dynamics automatically and in a timely fashion. It not only pushes key blocks to KMS QNL service for KMS service, but also responds to pull requests for key blocks directly from KMS service.

QKD Link Layer (QLL)

Ideally, QLL consists of working QKD devices. A QLL simulator is provided in this project for situations where real QKD devices based links are unavailable, e.g., a planned satellite based QKD link between two nodes that are geographically far away.

How to Run The Project

Prerequisites (Required)

Install following before proceeding. Make sure the executables are in system path.

  1. Java SDK 8 or later - http://www.oracle.com/technetwork/java/javase/downloads/index.html
  2. Maven - https://maven.apache.org/ or apt-get, if on Ubuntu
  3. screen - apt-get, if on Ubuntu
  4. git - apt-get, if on Ubuntu
  5. libjson-c-dev

Prerequisites for testing (Optional)

On a Linux(Ubuntu) system apt-get can be used to install the programs.

  1. Curl
  2. jq

Quick start guide

On two Linux (Ubuntu) systems, please follow the steps below to get a two nodes system running quickly.

  1. Assume IP address of A is 192.168.2.207 and IP address of B is 192.168.2.212
  2. On Ubuntu A
  3. git clone https://github.com/Open-QKD-Network/qkd-net.git
  4. cd qkd-net
  5. git checkout disable-spring-auth
  6. cd kms
  7. ./scripts/build
  8. rm ~/.qkd (Step 6 generates ~/.qkd directory)
  9. cd ..
  10. tar xvf qkd-kaiduan-a.tar
  11. mv .qkd ~/
  12. Add false to the end of BOTH kms.conf and kms/kms.conf to disable OAuth authentication. After this last 2 lines of kms.conf and kms/kms.conf should be:
# there will be 3 lines above this starting with http://localhost
A
false
  1. On Ubuntu A, changes IP address of B in the ~/.qkd/qnl/routes.json.
{
  "adjacent": {
    "B": "192.168.2.212"
  },
  "nonAdjacent": {
  }
}
  1. Run commands 3 to 9 on Ubuntu B
  2. tar xvf qkd-kaiduan-b.tar
  3. mv .qkd ~/
  4. Like we did for Ubuntu A in Step 12, add false to the end of kms.conf and kms/kms.conf to disable OAuth authentication.
  5. On Ubuntu B, changes IP address of A in the ~/.qkd/qnl/routes.json
{
  "adjacent": {
    "A": "192.168.2.207"
  },
  "nonAdjacent": {
  }
}
  1. On Ubuntu A, cd qkd-net/kms, run command ./scripts/run. Wait for this terminate.
  2. On Ubuntu B, cd qkd-net/kms, run command ./scripts/run
  3. You can check if OpenQKDNetwork is up by looking the ~/.qkd/mapping.log and ~/qkd_logs/lsrp.log
{"192.168.2.207":"A","192.168.2.212":"B"}
========Nodes/Links========
A
    A <----> B = 1
B
    B <----> A = 1
========Nodes/Links========

NOTE: If you cannot see these 2 files, then please stop & don't proceeed further. Troubleshoot if need be, but first get this working.

  1. We will run tls-demo application alice on Ubuntu A and run bob on Ubuntu B
  2. On Ubuntu A, cd ../applications/tls-demo/, run make command
  3. On Ubuntu B, run command ./bob -b 10446
  4. On Ubuntu A, run command ./alice -i 192.168.2.212 -b 10446 -f ./data/whale.mp3
  5. On Ubuntu A, you should see something like below
 -- Successfully conected to Bob
    -- Received PSK identity hint 'B 5048deac-4aa0-42a3-9b9a-f9d01b8a884d 0'
post String siteid=B&index=0&blockid=5048deac-4aa0-42a3-9b9a-f9d01b8a884d
HTTP-FETCH-REQUEST, url:http://localhost:8095/api/getkey,post:siteid=B&index=0&blockid=5048deac-4aa0-42a3-9b9a-f9d01b8a884d

HTTP-FETCH-RESPONSE:{"index":0,"hexKey":"36b4bf06cc5cbb7e61983f8b4dfd7771edc2ee01bb049b52e0a91a4f2e90fa0c","blockId":"5048deac-4aa0-42a3-9b9a-f9d01b8a884d"}

index: 0
key: 36b4bf06cc5cbb7e61983f8b4dfd7771edc2ee01bb049b52e0a91a4f2e90fa0c
blockId: 5048deac-4aa0-42a3-9b9a-f9d01b8a884d
    -- SHA1 of the received key : F7DC264E8C6165228EF9E0EBF0EFCF50B217B4D3
  1. On Ubuntu B, file is received and saved in bobdemo and should see something like below
 -- Bob is listening for incomming connections on port 10446 ...
key_post : siteid=A
HTTP-FETCH-REQUEST, url:http://localhost:8095/api/newkey,post:siteid=A

HTTP-FETCH-RESPONSE:{"index":0,"hexKey":"36b4bf06cc5cbb7e61983f8b4dfd7771edc2ee01bb049b52e0a91a4f2e90fa0c","blockId":"5048deac-4aa0-42a3-9b9a-f9d01b8a884d"}

index: 0
key: 36b4bf06cc5cbb7e61983f8b4dfd7771edc2ee01bb049b52e0a91a4f2e90fa0c
blockId: 5048deac-4aa0-42a3-9b9a-f9d01b8a884d
SSL-Server-PSK-Hint:B 5048deac-4aa0-42a3-9b9a-f9d01b8a884d 0
    -- SHA1 of the received key : F7DC264E8C6165228EF9E0EBF0EFCF50B217B4D3
 -- TLS Closed
 -- Connection Closed
 -- Accept Connection
  1. For 3 nodes system, extract qkd-kaiduan-c.tar on Ubuntu, assume we will run alice on A and bob on C, the network topology looks below,

A <----> B <---> C

  1. Assume IP address of C is 192.168.2.235, Add C to B's adjacent nodes
{
  "adjacent": {
    "A": "192.168.2.207",
    "C": "192.168.2.235"
  },
  "nonAdjacent": {
  }
}

Correctly Handle Configuration Files

As this is a multi-layer distributed system, a few configuration files are used to facilitate the deployment for different nodes (or sites). They need to be carefully checked before running/testing the system.

kms.conf

Sample applications provided (qTox and tls-demo) require kms.conf to be present under the $HOME/.qkd directory.

This file can be manually created by puting following entries:

http://localhost:9992/uaa/oauth/token
http://localhost:8095/api/newkey
http://localhost:8095/api/getkey
C
false

Depending on where the KMS node is deployed, localhost can be replaced by the IP address of the host running the KMS layer. The last line represents the KMS site id, which should be updated with the correct site id. Above is just an example.

config-repo

config-repo directory under $HOME/ contains all the configuration property files required by all the microservices.

All the files reside under /qkd-net/kms/config-repo from where they are copied to $HOME/config-repo and checked in a local git repository.

site.properties

This file is located under /qkd-net/kms/kms-service/src/main/resources/.

Explanation of site specific configuration properties used by KMS service:

//Number of keys per block
kms.keys.blocksize=1024
//Size of a key in bytes
kms.keys.bytesize=32
//Top level location for locating key blocks
kms.keys.dir=${HOME}/.qkd/kms/pools/
//IP address of the host where key routing service is running
qnl.ip=localhost
//Port on which key routing service is listening for key block requests
qnl.port=9292
config.yaml (KMS QNL Service)

This file is copied from /qkd-net/kms/kms-qnl-service/src/main/resources/ to $HOME/.qkd/kms/qnl from where it is used by KMS QNL service

Expalantion of configuration properties used by KMS QNL service:

//Port on which KMS QNL service is listening
port: 9393
//Size of a key in bytes
keyByteSz: 32
//Number of keys in a block. Key routing service provides KMS keys in blocks of size    
keyBlockSz: 1024
//Location where KMS QNL service puts the pushed key blocks from key-routing service
poolLoc: kms/pools
config.yaml and routes.json (Key-Routing Service)
routes.json:

This file is copied from /qkd-net/qnl/conf/ to $HOME/.qkd/qnl.

Topology information is contained in route.json. This information is populated manually for adjacent (neighboring) nodes, while the non-adjacent nodes will be discovered by the routing module. Adjacent nodes section contains the name of the node as key and it's IP address as the value.

Example route.json file for a QNL Node "B":

{
  "adjacent": {
    "A": "192.168.1.101",
    "C": "192.168.1.103"
  },
  "nonAdjacent": {
  }
}
config.yaml:

This file is copied from /qkd-net/qnl/conf/ to $HOME/.qkd/qnl. It contains various configuration parameters for the key routing service running as a network layer.

Brief explanation of various properties is given with the following example file:

//Base location for finding other paths and configuration files.
base: .qkd/qnl
//Route configuration file name.
routeConfigLoc: routes.json
//Location where QLL puts the key blocks for QNL to carve out key blocks for KMS.
qnlSiteKeyLoc: qll/keys
//Each site has an identifier uniquely identifying that site.
siteId: A
//Port on which key routing service is listening for key block requests.
port: 9292
//Size of a key in bytes.
keyBytesSz: 32
//Number of keys in a block. Key routing service provides KMS keys in blocks of size.  
keyBlockSz: 1024
//Key routing service expects QLL to provide keys in blocks of qllBlockSz.
qllBlockSz: 4096
//IP address of the host running KMS QNL service.
kmsIP: localhost
//Port on which KMS QNL service is listening.
kmsPort: 9393
//One Time Key configuration.
OTPConfig:
 //Same as above
 keyBlockSz: 1024
 //Location of the OTP key block.
 keyLoc: otp/keys

Build and Install Services

For building the services,

cd <top level director>/qkd-net/kms
./scripts/build

For running the services

cd <top level director>/qkd-net/kms
./scripts/run

Checking registration service

Open a browser, check http://localhost:8761/

Testing KMS service

We don't have to deal with OAuth at all in this branch :-).

There are two REST API endpoints:

  1. New Key

Application at site B makes a newkey call.

Request

Method : POST URL path : /api/newkey URL params: siteid=[alhpanumeric] e.g. siteid=A

Response Format in JSON

{
  index: Index of he key
  hexKey: Key in hexadecimal format
  blockId: Id of the block containing the key
}

e.g. request-response:

curl 'http://localhost:8095/api/newkey?siteid=A' | jq
{
  "index": 28,
  "hexKey": "a2e1ff3429ff841f5d469893b9c28cbcb586d55c8ecf98c83c704824e889fc43"
  "blockId": "133ad3f8de6cc9da"
}
  1. Get Key

Application on site A makes the getkey call by using part of the response from the newkey call above.

NOTE: Since the sites are different hence OAuth tokens will be different, which means a new OAuth token like above is fetched first by the application on site A.

Request

  Method :      POST
  URL path :    /api/getkey
  URL params:   siteid=[alhpanumeric] e.g. siteid=B
                blockid=
                index=[Integer]

Response Format in JSON

  {
    index: Index of he key
    hexKey: Key in hexadecimal format
    blockId: Id of the block containing the key
  }

e.g. request-response:

curl 'http://localhost:8095/api/getkey?siteid=B&index=1&blockid=' | jq
{
  "index": 1,
  "hexKey": "4544a432fb045f4940e1e2fe005470e1a35d85ede55f78927ca80f46a0a4b045"
  "blocId": "8a94dc22e761de8c5501addc05"
}

TROUBLESHOOTING

Stopping things

Stop OpenQKDNet by cd into qkd-net/kms and running ./scripts/stop and ./scripts/cleanup.

It is alright if on running./scripts/stop you get No screen session found.

Ensure the nodes can talk to each other.

We'll use netcat to check whether the 2 nodes can connect to each other on TCP Port 9395.

  • On Ubuntu B run nc -l 9395,
  • On Ubuntu A run nc IP_addr_of_node_B 9395.

Enter any text on A. If you get the same text on B, then we know that the 2 nodes are able to talk to each other.

Inspecting running Java processes

Ideally, once you've run './scripts/run, the number of Java processes on both nodes should be 13`.

You can get the number of Java processes running on each node by running ps -aux | grep java | wc -l on both nodes.

If you get a number which is more than this, run ps -aux | grep java and figure out which other processes are running. If the process has no side effects for OpenQKDNet (e.g. VS Code Plugin related Java process), then you're good.

But, in particular, if you can see any process related to jitsi and/or jicofo running, we want to stop them via:

  • sudo systemctl stop jicofo
  • sudo systemctl stop jitsi-videobridge2

TEAM

The Open QKD Network project is led by Professors Michele Mosca and Norbert Lutkenhaus at Institute for Quantum Computing (IQC) of the University of Waterloo.

Contributors

Main contributors to this master branch so far include:

  • Shravan Mishra (University of Waterloo)
  • Kaiduan Xie (University of Waterloo)
  • Dr. Xinhua Ling (University of Waterloo, evolutionQ Inc.)