The following repository contains an implementation proposal for the KME (Key Management Entity) server defined in the ETSI QKD standard for Quantum Key Distribution.
Cross-datacenter communication is a common use case in the cloud. It is often necessary to encrypt data in transit between datacenters, and this encryption almost always involves public key cryptography.
However, currently used public key cipher suites, such as RSA or ECC are not quantum-safe, and it is expected that quantum computers will be able to break them in the future.
There are public key cipher suites that are quantum-safe, such as the ones based on lattice cryptography, but they are not yet widely used. Furthermore, no one can be sure that they will never be broken in the future. So public key cryptography is not a good solution for guaranteed forward secrecy.
On the other hand, Quantum Key Distribution (QKD) is a mechanism that allows two parties to produce a shared random secret key, which can be used to encrypt and decrypt messages, and which guarantees theoretical forward secrecy.
Indeed, QKD is based on the laws of quantum physics, and it is theoretically impossible to eavesdrop on a QKD key exchange without being detected. The only condition is that the two parties have correctly authenticated each other beforehand.
The ETSI standard defines a protocol for usage of quantum-distributed keys by applications.
It assumes the existence of "secure-zones", meaning zones protected against cyber and physical intrusions. It is possible to assume traditional public-key cryptography is secure in these zones. These zones can be, for example, datacenters.
On the other hand, communications between "secure-zones" as to be secured using QKD.
Standard defines the following entities:
- Key Management Entity (KME): responsible for managing the keys exchanged between the secure zones and furnishing them to Secure Application Entities (SAEs).
- Secure Application Entity (SAE): Exchange keys with other SAEs.
This software intends to manage QKD-exchanged key, in a way compliant with the ETSI standard.
This software has to be run in the KME servers. One KME can support multiple remote KMEs connections. For compatibility purpose, it also supports key exchange between KMEs in the same zone (for which direct public-key encryption is enough).
There should exist a directory where binary key files are stored after Privacy Amplification. These files have to be named equally on both KMEs.
π Note: QKD can be performed while this software is running, it will simply detect new key files in the directory.
All the authentication is performed via SSL client and server certificates. Within the same "secure-zone", SAEs are distinguished by their client certificate serial number.
For now read QKD keys are stored inside a SQLite database, either in memory or on disk.
π I plan to add a feature to store keys in a secure database in the future.
Install Rust programming language, as explained at https://www.rust-lang.org/tools/install.
git clone https://github.com/thomasarmel/qkd_kme_server.git
cd qkd_kme_server
cargo test
cargo build --release
It has been tested for both Linux and Windows.
You run unit tests with:
cargo test
For a simple proof of concept in local, you can run the software with config_kme1.json
and config_kme2.json
files as argument for respectively KME1 and KME2.
For local tests, certificates are pre-generated and stored in the certs
folder.
First of all, please ensure there is a directory in both KMEs where the QKD keys are stored.
Files should have the same name and contents in both KMEs. They should have the .cor
extension. π΄ These must be the files generated AFTER Privacy Amplification. π΄
This software will detect new files automatically in case you are doing QKD on-the-fly.
You must generate SSL certificates for both SAE-to-KME and KME-to-KME communications (in the latter certificates are used only for authentication).
Here is an example of how to quickly generate all SSL certificates. If your adversary already has access to an efficient quantum computer (I don't know when you are reading this), you can use Open Quantum Safe OpenSSL fork to generate your certificates.
KMEs' server certificates:
For all KMEs, you can generate a self-signed certificate with:
openssl genrsa -out kme_server.key 4096
openssl req -new -key kme_server.key -out kme_server.csr
openssl x509 -req -days 3650 -in kme_server.csr -signkey kme_server.key -out kme_server.crt
π Add the certificate to the trusted store of the other KMEs, and trusted stires of the SAEs of the same zone.
KMEs' CA certificates:
For all your KMEs, you must generate two CA certificates, one for authenticating SAE-to-KME communications, and one for KME-to-KME communications.
Create a root-ca.cnf
file containing
[root_ca]
basicConstraints = critical,CA:TRUE,pathlen:1
keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
subjectKeyIdentifier=hash
Generate CA for authenticating SAEs:
openssl genrsa -out "root_ca_saes_auth.key" 4096
openssl req -new -key "root_ca_saes_auth.key" -out "root_ca_saes_auth.csr" -sha256 -subj '/CN=KME CA to authenticate its SAEs'
openssl x509 -req -days 3650 -in "root_ca_saes_auth.csr" -signkey "root_ca_saes_auth.key" -sha256 -out "root_ca_saes_auth.crt" -extfile "root-ca.cnf" -extensions root_ca
Generate CA for authenticating other KMEs:
openssl genrsa -out "root_ca_kmes_auth.key" 4096
openssl req -new -key "root_ca_kmes_auth.key" -out "root_ca_kmes_auth.csr" -sha256 -subj '/CN=KME CA to authenticate other KMEs'
openssl x509 -req -days 3650 -in "root_ca_kmes_auth.csr" -signkey "root_ca_kmes_auth.key" -sha256 -out "root_ca_kmes_auth.crt" -extfile "root-ca.cnf" -extensions root_ca
Client certificates
Create a client.cnf
file containing
[client]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "Client Certificate to authenticate to KME server"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
Now you need to generate client certificates for all SAE inside the secure zone:
openssl genrsa -out "sae1_client_secure_zone.key" 4096
openssl req -new -key "sae1_client_secure_zone.key" -out "sae1_client_secure_zone.csr" -sha256 -subj '/CN=Secure zone SAE1 Client'
openssl x509 -req -days 750 -in "sae1_client_secure_zone.csr" -sha256 -CA "root_ca_saes_auth.crt" -CAkey "root_ca_saes_auth.key" -CAcreateserial -out "sae1_client_secure_zone.crt" -extfile "client.cnf" -extensions client
cat sae1_client_secure_zone.key sae1_client_secure_zone.crt root_ca_saes_auth.crt > sae1_client_secure_zone.pem
openssl pkcs12 -export -out sae1_client_secure_zone.pfx -inkey sae1_client_secure_zone.key -in sae1_client_secure_zone.pem -certfile root_ca_saes_auth.crt
Do the same for all the SAEs within the secure zone.
π Take note somewhere of the serial number of the certificates, as it will be used to identify the SAEs.
Generate client certificates for all KMEs:
openssl genrsa -out "kmeb_client_external.key" 4096
openssl req -new -key "kmeb_client_external.key" -out "kmeb_client_external.csr" -sha256 -subj '/CN=KMEb external Client from'
openssl x509 -req -days 750 -in "kmeb_client_external.csr" -sha256 -CA "root_ca_kmes_auth.crt" -CAkey "root_ca_kmes_auth.key" -CAcreateserial -out "kmeb_client_external.crt" -extfile "client.cnf" -extensions client
cat kmeb_client_external.key kmeb_client_external.crt root_ca_kmes_auth.crt > kmeb_client_external.pem
openssl pkcs12 -export -out kmeb_client_external.pfx -inkey kmeb_client_external.key -in kmeb_client_external.pem -certfile root_ca_kmes_auth.crt
Here is a scheme of the expected certificates for a KME:
target/release/qkd_kme_server kme_config.json
with kme_config.json
being the configuration file for the KME, explained below.
Wait a few seconds until all keys are loaded and the server is ready.
Launch the server on all KMEs.
The whole configuration is stored in a JSON file. You can find examples in config_kme1.json
and config_kme2.json
.
π I plan to use JSON5 in the future to allow comments and hex numbers in the configuration file.
Here are the configuration sections:
this_kme
This section describes the KME itself
id
Unique ID of the KME in the whole network, as a 64-bit integer. Please note that SAE and KME IDs are different, meaning a SAE and a KME can share the same ID.
nickname
An optional human-readable name for the KME, such as "Alice or Bob". The nickname will appear on the logs in the web UI. If the nickname is not set, the web UI will display "KME {ID}".
sqlite_db_path
Path to the SQLite database file. The software will create the tables if they do not exist. You can specify:memory:
to use an in-memory database.
key_directory_to_watch
A directory containing the QKD keys for key exchange between SAEs inside the secure zone. It's not very useful as direct public-key encryption is more suitable for this purpose, but it has to be set for compatibility purpose.
saes_https_interface
This section describes the private HTTPS interface for SAEs inside the secure zone:
listen_address
The address to listen SAEs HTTPS requests, such as10.0.0.2:13000
(:warning: you should avoid using0.0.0.0
as this interface should be exposed only to the secure zone).
ca_client_cert_path
Path to the.crt
CA certificate used to authenticate SAEs.
server_cert_path
Path to the.crt
server certificate (the one you should have added to SAEs trusted certificates store).
server_key_path
Path to the.key
server private key.
debugging_http_interface
An optional address for the debugging HTTP interface, to be consulted using a web browser (see below). It is only for demonstration purpose and should not be exposed to the public.
kmes_https_interface
This section describes the public HTTPS interface for remote KMEs:
listen_address
The address to listen KMEs HTTPS requests, such as0.0.0.0:13001
.
ca_client_cert_path
Path to the.crt
CA certificate used to authenticate KMEs.
server_cert_path
Path to the.crt
server certificate (the one you should have added to KMEs trusted certificates store).
server_key_path
Path to the.key
server private key.
other_kmes
This array of sections describe all other KMEs in the network. Each section has the following fields:
id
Unique ID of the KME in the whole network, as a 64-bit integer.
key_directory_to_watch
A directory containing.cor
QKD key files, after Privacy Amplification between the two zones.
inter_kme_bind_address
The address to connect to the other KME via HTTPS, such as1.2.3.4:14001
.
ignore_system_proxy_settings
Should be set totrue
if you want to ignore system proxy settings for connection to this remote KME.
https_client_authentication_certificate
.pfx
client certificate used to authenticate to the other KME.
https_client_authentication_certificate_password
Password for the.pfx
client certificate.
saes
This array of sections describe all SAEs either inside the secure zone or the ones belonging to other KMEs. Each section has the following fields:
id
Unique ID of the SAE in the whole network, as a 64-bit integer.
kme_id
ID of the KME to which the SAE belongs, either ID of this KME or a remote KME.
https_client_certificate_serial
If SAE belongs to this KME, integer array of the serial number of the.crt
client certificate. π΄ As the configuration does not support JSON5 for now, you must type all the numbers in decimal format π΄
Note: SAE ids are 64 bits integers
This route should be called by the master SAE
Get the status of the QKD key exchange with the slave SAE, ie how much exchanged keys are available.
ID of the calling SAE is automatically retrieved from the client certificate.
Response example:
{ "source_KME_ID": "1", "target_KME_ID": "2", "master_SAE_ID": "1", "slave_SAE_ID": "2", "key_size": 256, "stored_key_count": 1, "max_key_count": 10, "max_key_per_request": 1, "max_key_size": 256, "min_key_size": 256, "max_SAE_ID_count": 0 }
This route should be called by the master SAE
π Note: Only one key per request is supported for now.
Retrieve a key already exchanged between the master KME (the one responding) and the slave KME.
It returns the key encoded in base64 and the key ID, that should be sent directly to the slave SAE in order to let it retrieve the key.
Response example:
{ "keys": [ { "key_ID": "8844cba7-29e1-3251-a50a-25da13e65eea", "key": "dGhpc19pc19zZWNyZXRfa2V5XzFfb2ZfMzJfYnl0ZXM=" } ] }
This route should be called by the slave SAE
Retrieve a key already exchanged between the master KME and the slave KME (the one responding), from the key id.
Key id is the one sent by the master KME.
Request example:
{ "key_IDs": [ { "key_ID": "8844cba7-29e1-3251-a50a-25da13e65eea" }, { "key_ID": "8844cba7-29e1-3251-a50a-25da13e65eea" } ] }
Response example:
{ "keys": [ { "key_ID": "8844cba7-29e1-3251-a50a-25da13e65eea", "key": "dGhpc19pc19zZWNyZXRfa2V5XzFfb2ZfMzJfYnl0ZXM=" }, { "key_ID": "8844cba7-29e1-3251-a50a-25da13e65eea", "key": "dGhpc19pc19zZWNyZXRfa2V5XzFfb2ZfMzJfYnl0ZXM=" } ] }
This route should be called by any SAE
Get the information of the calling SAE, identified by its certificate serial number.
If the SAE is not registered, a not found error is returned.
Response example:
{ "SAE_ID": 1 }
This route should be called by any SAE
Get the Shannon entropy of all the keys stored in the KME.
β οΈ If you notice the entropy is abnormally low, it may be a sign that an attacker compromised the QKD key exchange or the Privacy Amplification process.
Response example:
{ "total_entropy": 7.919922493186846 }
As explained above, you can access a web interface using your web browser to consult the KME status and logs if you set it in configuration.
Events displayed look like:
2024-02-26T08:53:16.847785700Z: [Bob] Key de4f4010-ed34-2d51-ab3c-63240a8df9e1 activated between SAEs 1 and 2
2024-02-26T08:53:16.879269100Z: [Bob] SAE 2 requested key de4f4010-ed34-2d51-ab3c-63240a8df9e1 (from 1)
2024-02-26T08:55:11.036073500Z: [Bob] Key 4985cdbb-35ed-d555-9030-b171773d6483 activated between SAEs 1 and 2
2024-02-26T08:55:11.061108300Z: [Bob] SAE 2 requested key 4985cdbb-35ed-d555-9030-b171773d6483 (from 1)
2024-02-26T08:56:01.653345800Z: [Bob] SAE 2 requested a key to communicate with 1
2024-02-26T08:56:01.690181100Z: [Bob] As SAE 1 belongs to KME 1, activating it through inter KMEs network
2024-02-26T08:56:01.690332800Z: [Bob] Key b7a86bdd-c342-5b5f-b10c-c957cb1d8e75 activated between SAEs 2 and 1