Quant
The quant
repository contains a prototypical software stack that allows to emulate a key exchange within a Quantum Key Distribution Network (QKDN).
Currently quant
contains the following main parts: goKMS, quantumlayer, akms-simulator, etsi14module
goKMS
A Key Management System (KMS) for QKDN written in go.
goKMS
can pull or receive QKD key material from different sources depending on the configured operating mode. This material gets processed into keys and it provides a key store for each registered KMS peer. So called forwarding routes can be set through gnmi, either via assign-forwarding
or key-routing-sessions
(see temp.yang).
If a route is configured the goKMS
that has no prev-hop
provided within its
route configuration, will initiate the process to exchange a so-called
platform-key
using keys derived from QKD key material to encrypt and decrypt the platform-key
hop-by-hop during the exchange process. Afterwards, the start and end goKMS
have a platform-key
available to perform a KSA key exchange.
Note well: This is currently not intended to be used in production environments, neither in networks that can be reached by everybody, nor in other uncontrolled settings.
Configuration of a goKMS
A goKMS can be configured through a configuration file, as seen below:
Id: "0ff33c82-7fe1-482b-a0ca-67565806ee4b" # ID of the kms
Name: kms01 # name of the kms
InterComAddr: 0.0.0.0:50910 # IP and port to bind the local gRPC server for inter KMS communication to
QuantumAddr: 0.0.0.0:50911 # IP and port to bind the local gRPC server for QKD modules to reach the KMS to (optional, only used for specific emulated or experimental QKD modules)
AkmsURL: "http://172.100.20.22:4444/api/v1/keys/push_ksa_key" # address of the rest endpoint of a connected AKMS (used for sending KSA key to the AKMS).
AkmsCkmsServerPort: "9696" # Port of connected AKMS
GRPCTimeoutInSeconds: 10 # Time in seconds for timeout of gRPC connections as a client. Defaults to 10 seconds. Should not be set to 0 or negative values.
GnmiTLS: # Settings for TLS for gNMI endpoint. Can be overwritten with cli parameters.
Active: true # Whether TLS is enabled
CAFile: "ssl/ca.crt" # Path to ca
CertFile: "ssl/kms/kms1-selfsigned.crt" # Path to cert
KeyFile: "ssl/kms/kms1-selfsigned.key" # Path to key
KmsTLS: # Settings for TLS for inter KMS communication
Active: true # Whether TLS is enabled
CAFile: "ssl/ca.crt" # Path to ca
CertFile: "ssl/kms/kms1-selfsigned.crt" # Path to cert
KeyFile: "ssl/kms/kms1-selfsigned.key" # Path to key
AkmsCkmsTLS: # Settings for TLS for akms ckms interface
Active: true # Whether TLS is enabled
CAFile: "ssl/ca.crt" # Path to ca
CertFile: "ssl/kms/kms1-selfsigned.crt" # Path to cert
KeyFile: "ssl/kms/kms1-selfsigned.key" # Path to key
Peers: # Peers to other goKMS
# peer to goKMS02
- PeerId: "5e41c291-6121-4335-84f6-41e04b8bdaa2" # id of the peer
PeerInterComAddr: 172.100.20.11:50910 # inter com endpoint of the peer
Type: danet # type of communication method between KMS (currently only danet supported)
QuantumModule: # Quantum module used for this peer
Type: emulated # Type of the quantum module e.g. emulated or etsi
TLS: # Settings for TLS for quantum module communication
Active: true # Whether TLS is enabled
CAFile: "ssl/ca.crt" # Path to ca
CertFile: "ssl/kms/kms1-selfsigned.crt" # Path to cert
KeyFile: "ssl/kms/kms1-selfsigned.key" # Path to key
Address: 172.100.20.14 # Address of the quantum module
Hostname: quantumlayer_1 # Optional addressing of the quantum module as hostname
# peer to goKMS03
- PeerId: "f80db2c0-2480-46b9-b7d1-b63f954e8227"
PeerInterComAddr: 172.100.20.12:50910
Type: danet
QuantumModule:
Type: emulated
Address: 172.100.20.18
Other configuration options:
ETSI14Server: # Configuration for ETSI014 server, should not be used together with AKMS configurations
Address: "0.0.0.0:1414" # IP and port to bind the local ETSI014 HTTP server to, provides the endpoints defined in ETSI014
RemoteCKMSID: "5e41c291-6121-4335-84f6-41e04b8bdaa2" # UUID of the target CKMS when doing a (ETSI014) GetKey
QkdnManagerServer: # Server on KMS side for monitoring purposes, currently only supports few example endpoints
Address: "0.0.0.0:8090" # IP and port to bind the local management monitoring HTTP server to
Peers:
# peer to goKMS02
- PeerId: "5e41c291-6121-4335-84f6-41e04b8bdaa2"
PeerInterComAddr: 172.100.20.11:50910
Type: danet # type of communication method between KMS (currently only danet supported)
QuantumModule:
Type: etsi # Type of the quantum module e.g. emulated or etsi
Address: http://172.100.20.14:1414 # Address of the quantum module
Mastermode: true # (Type: etsi specific) Sets the QuantumModule in MasterMode. Keys are requested via GetKey and synced with peer KMS.
LocalSAEID: "localSAEID" # the related ID of the local SAE
TargetSAEID: "targetSAEID" # the related ID of the target SAE
KeyFetchInterval: 10 # interval in seconds for how often keys should be requested from a QuantumModule (optional, uses default if not provided)
KeyFetchAmount: 10 # amount of keys to be requested from a QuantumModule (optional, uses default if not provided)
MaxKeyFillLevel: 100 # maximum number of keys to be stored in the storage related to one KMS peer (should be the same for the peer on the other side, uses default if not provided)
# peer to goKMS03
- PeerId: "f80db2c0-2480-46b9-b7d1-b63f954e8227"
PeerInterComAddr: 172.100.20.12:50910
Type: danet
QuantumModule:
Type: etsi
Address: http://172.100.20.14:1414
Mastermode: false # (Type: etsi specific) Sets QuantumModule to request keys via GetKeyWithId, setting false explicitly is optional
LocalSAEID: "localSAEID" # the related ID of the local SAE
TargetSAEID: "targetSAEID" # the related ID of the target SAE
There are many example configuration files available in this repository under config. Note, for some configuration options, there are different operating modes or ways to configure the behaviour. Not all of them can work together, possible working configurations can be found within the provided example configurations.
You can also provide some configuration via command line arguments. Only settings relevant for running goKMS with remote configuration via gNMI are available here. This includes gNMI TLS settings and log level. Furthermore a path to a configuration file can be provided. Keep in mind that cli arguments will be prioritized, so you can overwrite your gNMI settings in the config file with your cli arguments.
Available are the following flags:
Usage of goKMS:
-caFile string
location of the gNMI ca file (overwrites settings in config file)
-certFile string
location of the gNMI cert file (overwrites settings in config file)
-gnmiBindAddress string
address to bind gNMI to (overwrites settings in config file) (default ":7030")
-gnmiTLS
If true do use TLS for gNMI, paths to ca, cert and key must be set aswell (overwrites settings in config file)
-noGRPCPassthrough
set the default resolve scheme for grpc to not use passthrough, default is false
-keyFile string
location of the gNMI key file (overwrites settings in config file)
-kms_config string
path to the config file
-log string
logrus log level (debug, info, warn, error, fatal, panic) (default "info")
Interfaces
Inter-KMS Communication
This interface is required for the communication between the peering KMS in order to coordinate their actions for key selection and key forwardwing after a path has been established. The definition can be found in: api/kmsintercom/kmsintercom/kmsintercom.proto
Note: In the future, goKMS
might support additional, different protocols for the key exchange.
Interface to quantum modules
goKMS
provides the possibility to use different kinds of interfaces to communicate with quantum modules. Which one to use, can be defined via the configuration files in the quantum module section under the peer configuration (see).
Currently there are two interfaces available:
-
First there is our own interface implementation which can be found under: danet/quipsec This is the interface that is used within our implementation of an emulated quantum module (see
quantumlayer
). -
Second there is the REST-based implementation of ETSI014 which allows us to handle quantum modules that implemented the ETSI014 API (polling is currently hardcoded to 2 seconds).
gNMI
To manage the goKMS we provide a gNMI endpoint.
By using the gnmi-target package it is possible to manage (GET/SET/subscribe) configuration data of the KMS. Currently we use the temp.yang file for this and only a part of it is implemented yet.
Interfaces to trigger key exchange
Depending on the chosen configuration of the KMS, there are different possibilities of triggering a key exchange.
Via AKMS:
It is possible to simulate a request send by an AKMS (see akms-simulator). The request should look like something this, where receiving_CKMS_ID is the ID of the KMS that should be reached. Check config/configure-and-run-docker-playground.sh
for other examples:
curl -X POST -H "Content-Type: application/json" -d '{
"receiving_CKMS_ID": "968fd594-b0e7-41f0-ba4b-de259047a933",
"request_ID": "request_ID-1234",
"key_properties": {
"number": 1,
"key_length": 256,
"timeout": 20,
"TTL": 24
}
}' 'http://172.100.20.10:9696/api/v1/keys/ksa_key_req'
After a successful key exchange both AKMS simulators will log the ID and the key value.
Via ETSI014:
The key exchange can also be triggered by sending a GetKey
request as defined in ETSI014. After a successful key exchange, the key can then be fetched on the other end using the GetKeyWithIDs
call.
Debug setup
For goKMS there is a debug setup available for VS Code. It uses the standard docker-compose.yml
setup and simply adds the debugger to it in the docker-compose.override.yaml
- Set your breakpoints for the goKMS (akms-simulator and quantumlayer currently not supported)
- Go to the debugger tab in vscode and select
Debug all kms parallel
. The single KMS options may work for certain things, but are not guaranteed to work because of how the debugging setup works. - Wait for it to start. At the end you can follow the instruction printed in your terminal to add the devices to the qkdn-controller.
If you are finished stop the debugger and run make compose-debug-down
to stop the environment.
Quantumlayer
An implementation of an emulated quantum module. This QKD module pushes an amount of random numbers (called bulk keys) to the connected KMS, whereas the actual amount will vary over time and depending on the operation mode. It has two possible operation modes:
(Pseudo) Random Numbers
The generation of random numbers is done via the golang's math/rand pseudo random number generator(PRNG). The synchronization is done in an "offline" way, as both quantum modules simply wait to the next full 20 seconds on their clock before sending data. As both modules use the same seed for it's number generation, they will send the same data. After sending, it will sleep a given amount of time.
For this a quantumlayer uses the gRPC interface defined in: danet/quipsec.
Replay Numbers
The generation of random numbers is done with the help of a CSV file. This file should include a timestamp in ms and the number of bits that should be sent at that time. The quantum module always waits the given duration and then sends the given amount of data. For the random numbers, the same method as in the random operation mode is used.
Configuration of a quantumlayer
A quantumlayer can be configured through a configuration file, as seen below:
KMSAddr: "kms_1:50911" # The address of the connected goKMS.
OperationMode: "normal" # The operations mode. Can be either "normal" or "replay"
SleepTimerForGenerationInMs: 5000 # How long the module should sleep between each send process. Only relevant if mode is "normal"
Seed: 1337 # The seed for the random number generation. Must be the same on both matching quantum modules. If empty, the current day is used.
replayFilePath: './data.csv' # The path to the replay data. Only relevant if mode is "replay"
Also available are the following arguments:
Usage of quantumlayer:
-config string
path to the config file
-noGRPCPassthrough
set the default resolve scheme for grpc to not use passthrough, default is false (default false)
-log string
logrus lof level (debug, info, warn, error, fatal, panic), default: info (default "info")
akms-simulator
A simple simulation of an AKMS endpoint. This provides a REST endpoint to receive KSA keys from a goKMS
. The following functionalities are not implemented, the explanation is just there as a means of describing the KMS type. The 'A' stands for access and one of the main purposes of this type of KMS is providing a security barrier protecting the core network of a provider from malicious activity of an end user. Its further purpose is to interact with AAA instances of providers for contractual matters.
etsi14module
A simple implementation of a QKD module providing the REST endpoint as defined in ETSI014. Depending on the desired configuration of the whole QKD network, it can be used as provider of pseudo QKD key material. There is no complex logic behind the endpoint, it just provides randomly genrated keys using the random number generator of Go on a GetKey
call. This keys get stored in memory to be able to provide them afterwards on GetKeyWithIDs
calls.
Usage
See the makefile for options.
To use private repos rename build_env.env.example
to build_env.env
and add valid credentials. If you have access, simply use your username and a GitLab access token.
Minimal Test Setup
A docker-compose file provides a minimal test setup to play around with quant
.
This minimal setup contains four goKMS
, with goKMS01
and goKMS04
as endpoints.
Both of those are then connected to a akms-simulator
. Quantumlayers
are
used as quantum modules.
Start and Stop
By running make compose-up
and make compose-down
the setup can be started
or stopped with its default config. Please note that you need access to private QKDN repos to do this. If you don"t have this access, you can use the small examples in /dev_env_data
.
The default config is based on the configuration files provided in the config/goKMS and config/quantumlayer folder.
Setting routes
We provide some example .json
files to configure forwarding routes. They can
be found under config.
It is possible to configure the goKMS
through
gNMI. This also applies for setting
entries within the goKMS internal routing table. Therefore the paths
assign-forwarding
as well as key-routing-sessions
are both suitable.
The following is an example of a gNMI set request sent through gnmic:
gnmic -a "172.100.20.12:7030" -u admin -p admin --insecure -e JSON_IETF set --update-path 'key-routing-sessions/routing-sessions[path-id=38e0588b-6a2d-42c9-85a0-887cc877c299]' --update-file ./config/goKMS02-a.json
The .json
provided in this case contains information about previous
and next hops, as well as a path id.
{
"path-id": "38e0588b-6a2d-42c9-85a0-887cc877c299",
"prev-hop": {
"node-id": "0ff33c82-7fe1-482b-a0ca-67565806ee4b",
"ip-address": "172.100.20.10",
"port": 50910
},
"next-hop": {
"node-id": "968fd594-b0e7-41f0-ba4b-de259047a933",
"ip-address": "172.100.20.13",
"port": 50910
}
}
Instant playground
For an instant playground the bash script configure-and-run-docker-playground.sh
can be used (see
config/configure-and-run-docker-playground.sh). This adds two
key-routing-sessions which results in the exchange of two platform keys.
-
kms01
->kms02
->kms04
-
kms01
->kms03
->kms04
After that two requests from an AKMS are simulated through two curl requests.
Demo with goSDN-Controller
There is an additional playground where the goSDN-Controller can be used to configure goKMS. Therefore a small lab is provided.
Requirements:
- docker
- containerlab
Below is a short demo video of this setup in combination with the goSDN-Controller.
Integration Tests
Everything needed for the integration tests is found in the integration-tests
folder.
You can run them by simply using make integration-tests
in the project root.
If you need to debug the integration tests you can use vscode and provided configurations.
Open the integration test file you want to debug and set your breakpoints in the test and the kms code (a breakpoint before the tests add the devices to the controller is nearly always required), then go to VSCodes debug tab and start Debug open integration test and kms
.
After all images are build and started wait around 25 seconds before starting to progress through the test.
You can switch between stepping through the test and each kms. Stepping through the quantum layer, controller, routing app and akms-simulator is currently not supported.
Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository.
- Create a new branch.
- Make your changes.
- Submit a pull request.
Acknowledgements
Developed in the DemoQuanDT project ("Quantenschlüsselaustausch im deutschen Telekommunikationsnetz für höhere IT-Sicherheit", engl. quantum key exchange in the german telecommunications network for higher IT security).
The DemoQuanDT project is funded by the german ministry of education and research (BMBF).
