Setting Up The Backend For A Quantum Cryptography Simulation

Learning Lab
My Journey Through Books, Discoveries, and Ideas

Setting up the backend for a quantum cryptography simulation

In this blog post, I outline the initial steps taken to build the backend for my quantum cryptography simulation project. The goal is to create a platform demonstrating various cryptographic methods, including classical and quantum approaches.

Technology stack

I chose Python for the backend development due to its extensive libraries and ease of use. The core components are:

  • Flask: a lightweight web framework used to serve the main application and handle basic HTTP requests,
  • Flask-SocketIO: an extension for Flask that enables real-time, bidirectional communication between the server and clients (simulating Alice, Bob, and Eve) using WebSockets.

Configuration and setup

Project configuration, such as secret keys and logging verbosity, is managed through a config.json file. This file is loaded at startup, and its contents are parsed into a SimpleNamespace object for convenient attribute-style access within the code.


import json
from types import SimpleNamespace
from flask import Flask
from flask_socketio import SocketIO
import logging

# Load configuration
with open('config.json', 'r') as f:
    cfg = json.load(f, object_hook=lambda d: SimpleNamespace(**d))

# Initialize Flask app and SocketIO
app = Flask(cfg.APP_NAME)
app.config['SECRET_KEY'] = cfg.SECRET_KEY
socketio = SocketIO(app)

# Setup logging
log_level = logging.INFO if cfg.VERBOSE else logging.ERROR
logging.basicConfig(
    level=log_level,
    format="[%(asctime)s] [%(levelname)s] %(message)s",
    datefmt="%d/%b/%Y %H:%M:%S"
)
logger = logging.getLogger()

# Global cache for protocol state
cache = SimpleNamespace(protocol=None, enc=None, enc_message=None)

This setup provides a basic Flask application instance integrated with SocketIO and configured logging. A simple cache object holds the application’s state concerning the selected protocol and associated encryption details.

Protocol handling

The backend needs to manage different cryptographic protocols. I created placeholder functions to initialize, check, encode, and decode messages based on the selected protocol.


def init_protocol(encryption):
    cache.protocol = encryption
    if encryption == "No Protocol":
        # Initialize NoEncryption class (details omitted)
        cache.enc = NoEncryption(cfg.NoEncryption)
        cache.enc.generateKey() # Example key generation
        logger.info("Initialized No Protocol")
    elif encryption == "BB84 Protocol":
        logger.info("BB84 Protocol selected (implementation pending)")
        # Placeholder for BB84 initialization
        pass
    elif encryption == "Ekert Protocol":
        logger.info("Ekert Protocol selected (implementation pending)")
        # Placeholder for Ekert initialization
        pass

def check_protocol(encryption):
    return encryption == cache.protocol

# encode_message, decode_message_bob, decode_message_eve follow...

Currently, only the “No Protocol” option has a basic implementation using a simple encryption class (NoEncryption). The functions for BB84 and Ekert protocols are present but await future implementation. The encode_message function handles message transformation based on the active protocol, while decode_message_bob and decode_message_eve simulate message decryption by Bob and Eve, respectively. For “No Protocol”, base64 encoding is used for displaying the ‘encrypted’ message.

Real-time communication with SocketIO

SocketIO event handlers manage the interactions between the simulated parties.

  • handle_alice_key: Triggered when Alice initiates the key exchange. It calls init_protocol and informs all clients about the selected protocol and whether eavesdropping is active.
  • handle_reconcile_key: Simulates the key reconciliation step (currently just confirms success).
  • handle_alice_message: Processes a message sent by Alice. It encodes the message using encode_message and broadcasts it to Bob and potentially Eve.
  • handle_bob_decode: Triggered when Bob attempts to decode a message. It uses decode_message_bob and sends the result back.
  • handle_eve_decode: Triggered when Eve attempts to decode. It uses decode_message_eve only if eavesdropping is enabled for the session.

Here is an example of a handler:


@socketio.on("alice_message")
def handle_alice(data):
    encoded_message = encode_message(data["message"], data["encryption"])
    logger.info(f"Alice sent: {encoded_message}")
    # Emit to Eve
    emit("eve_receive_encrypted", {
        "message": encoded_message, "encryption": data["encryption"],
        "sender": "Alice"}, broadcast=True)
    # Emit to Bob
    emit("bob_receive_encrypted", {
        "message": encoded_message, "encryption": data["encryption"]},
        broadcast=True)

This backend structure provides the necessary server-side logic to manage different cryptographic simulations and handle real-time interactions between the simulated participants. The next steps involve implementing the quantum protocols like BB84 and Ekert91.

For access to the complete simulation code, please visit the GitHub repository here.