Skip to main content

Quantum computing toolkit: Shor's, Grover's, Deutsch-Jozsa, teleportation, gates, and QKD protocols

Project description

Shorkin

A quantum computing toolkit for Python. Implements Shor's algorithm for integer factorization, Deutsch-Jozsa for constant/balanced classification, Grover's algorithm for unstructured search, quantum teleportation, and Quantum Key Distribution (QKD) protocols with HTTP and gRPC transport integrations.

Quantum simulation is powered by Google Cirq. QKD-derived keys are used for AES-256-GCM payload encryption.

Installation

# Core library (Shor's algorithm + QKD protocols)
pip install shorkin

# With a specific web framework
pip install shorkin[fastapi]
pip install shorkin[django]
pip install shorkin[starlette]
pip install shorkin[tornado]

# With gRPC support
pip install shorkin[grpc]

# Everything
pip install shorkin[all]

Requires Python 3.10+.

Shor's Algorithm

Factor composite integers using a quantum (simulated via Cirq) or classical order-finding backend.

CLI

# Factor an integer
shorkin factor 15
# 15 = 3 x 5

# Factor with a specific mode
shorkin factor 21 --mode classical
shorkin factor 15 --mode quantum --verbose

# Factor the modulus from an RSA public key
shorkin factor-key path/to/public.pem

Library

from shorkin.factor import factor
from shorkin.classical.order_finder import find_order

class ClassicalFinder:
    method_name = "classical"
    def find_order(self, x, n):
        return find_order(x, n)

result = factor(15, ClassicalFinder())
print(result.factors)  # [3, 5]

Deutsch-Jozsa Algorithm

Determine whether a Boolean function f: {0,1}^n -> {0,1} is constant or balanced with a single quantum query (classically requires up to 2^(n-1)+1 evaluations).

from shorkin.deutsch_jozsa import deutsch_jozsa

# Constant function (always returns 1)
result = deutsch_jozsa(lambda x: 1, n=3)
print(result.function_type)  # "constant"
print(result.is_constant)    # True

# Balanced function (returns 1 for odd inputs)
result = deutsch_jozsa(lambda x: x % 2, n=3)
print(result.function_type)  # "balanced"
print(result.is_balanced)    # True

Grover's Algorithm

Search an unstructured space of 2^n items in O(sqrt(N)) oracle queries (vs O(N) classically).

from shorkin.grover import grover

# Find item 5 in a space of 8
result = grover(lambda x: int(x == 5), n=3)
print(result.found)            # 5
print(result.search_space_size)  # 8

# Multiple marked items
marked = {3, 5}
result = grover(lambda x: int(x in marked), n=3, num_marked=2)
print(result.found)  # 3 or 5

# Reproducible results with a seed
result = grover(lambda x: int(x == 5), n=3, seed=42)

Quantum Teleportation

Transfer an arbitrary single-qubit state using a shared Bell pair and two classical bits.

import math
from shorkin.teleportation import teleport

# Teleport |1> state (theta=pi)
result = teleport(theta=math.pi)
print(result.fidelity)     # ~1.0
print(result.success)      # True
print(result.alice_bits)   # (0, 0), (0, 1), (1, 0), or (1, 1)

# Teleport |+> state (theta=pi/2)
result = teleport(theta=math.pi / 2)
print(result.fidelity)     # ~1.0

Quantum Gates

Convenience wrappers around Cirq gates with a fluent GateChain builder.

import cirq
from shorkin.gates import H, CNOT, rotate_x, GateChain

q0, q1 = cirq.LineQubit.range(2)

# Gate aliases
circuit = cirq.Circuit()
circuit.append(H(q0))
circuit.append(CNOT(q0, q1))

# Fluent chaining
import math
chain = GateChain().h(q0).cnot(q0, q1).rz(q1, math.pi / 4)
circuit.append(chain.operations)

QKD Protocols

Three quantum key distribution protocols, all following a common QKDProtocol interface:

Protocol Description Sifting Yield QBER Threshold
BB84 2 bases, 4 states (Bennett-Brassard 1984) ~50% ~11%
B92 2 non-orthogonal states (Bennett 1992) ~25% ~5%
E91 Entanglement-based with CHSH Bell test (Ekert 1991) ~22% ~11%

Basic Usage

from shorkin.qkd import BB84, B92, E91, SimulatedChannel

# Create a simulated quantum channel
channel = SimulatedChannel(error_rate=0.02, seed=42)

# Generate a shared key using BB84
protocol = BB84(seed=42)
result = protocol.generate_key(num_qubits=4096, channel=channel)

print(f"Protocol:  {result.protocol}")
print(f"QBER:      {result.qber:.4f}")
print(f"Key:       {result.final_key.hex()}")
print(f"Key bits:  {result.key_length_bits}")

Choosing a Protocol

# BB84 -- the standard, good balance of efficiency and security
protocol = BB84(seed=42)
result = protocol.generate_key(num_qubits=4096, channel=channel)

# B92 -- simpler (2 states), lower yield, needs more qubits
protocol = B92(seed=42)
result = protocol.generate_key(num_qubits=8000, channel=channel)

# E91 -- entanglement-based, includes Bell inequality (CHSH) test
protocol = E91(seed=42)
result = protocol.generate_key(num_qubits=20000, channel=channel)
print(f"CHSH value: {result.metadata['chsh_value']:.3f}")  # > 2.0 = secure

Encrypt / Decrypt with QKD Keys

from shorkin.qkd import BB84, SimulatedChannel, encrypt, decrypt

channel = SimulatedChannel(seed=42)
result = BB84(seed=42).generate_key(num_qubits=4096, channel=channel)

ciphertext = encrypt(b"secret payload", result.final_key)
plaintext = decrypt(ciphertext, result.final_key)
assert plaintext == b"secret payload"

Simulated Channel Options

from shorkin.qkd import SimulatedChannel

# Perfect channel (no errors, no loss)
channel = SimulatedChannel()

# Noisy channel (5% bit-flip error rate)
channel = SimulatedChannel(error_rate=0.05)

# Lossy channel (10% photon loss)
channel = SimulatedChannel(loss_rate=0.10)

# Both noise and loss
channel = SimulatedChannel(error_rate=0.03, loss_rate=0.05, seed=42)

The QuantumChannel is a typing.Protocol -- you can implement your own to connect to real quantum hardware.

HTTP Integration

QKD key exchange runs at /.well-known/qkd/initiate. Once a session is established, request and response bodies are AES-256-GCM encrypted using the QKD-derived key, identified by the X-QKD-Session-Id header.

FastAPI

from fastapi import Depends, FastAPI
from shorkin.transport.http.fastapi import QKDMiddleware, QKDSession, qkd_session

app = FastAPI()

# Option 1: Middleware (encrypts all responses for active sessions)
app.add_middleware(QKDMiddleware, protocol="bb84")

# Option 2: Dependency injection (per-route control)
@app.get("/secure")
async def secure_endpoint(qkd: QKDSession = Depends(qkd_session("bb84"))):
    if qkd.is_active:
        return {"encrypted": qkd.encrypt(b"secret").hex()}
    return {"message": "no QKD session"}

Client usage with FastAPI

import httpx

# Step 1: Initiate key exchange
resp = httpx.post("http://localhost:8000/.well-known/qkd/initiate", json={
    "protocol": "bb84",
    "peer_id": "my-client",
})
session_id = resp.json()["session_id"]

# Step 2: Make requests with the session
resp = httpx.get("http://localhost:8000/secure", headers={
    "X-QKD-Session-Id": session_id,
})
# Response body is AES-256-GCM encrypted

Starlette

from starlette.applications import Starlette
from shorkin.transport.http.starlette import QKDMiddleware

app = Starlette(routes=[...])
app.add_middleware(QKDMiddleware, protocol="bb84")

Django

# settings.py
MIDDLEWARE = [
    # ...
    "shorkin.transport.http.django.QKDMiddleware",
]

SHORKIN_QKD = {
    "PROTOCOL": "bb84",      # or "b92", "e91"
    "NUM_QUBITS": 4096,
    "TARGET_KEY_BITS": 256,
    "STRICT": False,          # True = reject requests without QKD session
}

Tornado

import tornado.web
from shorkin.transport.http.tornado import QKDRequestMixin, qkd_routes

class SecureHandler(QKDRequestMixin, tornado.web.RequestHandler):
    def get(self):
        self.write(b"encrypted if QKD session is active")

app = tornado.web.Application(
    qkd_routes("bb84") + [
        (r"/secure", SecureHandler, {"qkd_protocol": "bb84"}),
    ]
)

Strict Mode

All HTTP integrations support strict=True, which rejects any request without an active QKD session (returns 403). QKD negotiation endpoints are always accessible.

gRPC Integration

QKD key exchange is exposed as a QKDKeyExchange gRPC service. Client and server interceptors handle session metadata transparently.

Server

from concurrent import futures
import grpc
from shorkin.transport.grpc.servicer import QKDKeyExchangeServicer
from shorkin.transport.grpc.interceptor import QKDServerInterceptor
from shorkin.transport.grpc import qkd_pb2_grpc

interceptor = QKDServerInterceptor(protocol="bb84")
server = grpc.server(
    futures.ThreadPoolExecutor(max_workers=10),
    interceptors=[interceptor],
)
servicer = QKDKeyExchangeServicer(protocol="bb84")
qkd_pb2_grpc.add_QKDKeyExchangeServicer_to_server(servicer, server)
server.add_insecure_port("[::]:50051")
server.start()
server.wait_for_termination()

Client

import grpc
from shorkin.transport.grpc.interceptor import QKDClientInterceptor
from shorkin.transport.grpc import qkd_pb2, qkd_pb2_grpc

# Set up intercepted channel
interceptor = QKDClientInterceptor(protocol="bb84")
channel = grpc.intercept_channel(
    grpc.insecure_channel("localhost:50051"),
    interceptor,
)
stub = qkd_pb2_grpc.QKDKeyExchangeStub(channel)

# Initiate key exchange
response = stub.Initiate(qkd_pb2.KeyExchangeInitRequest(
    protocol="bb84",
    peer_id="my-service",
))
print(f"Session: {response.session_id}")
print(f"Status:  {response.status}")

# Set session for subsequent calls
interceptor.session_id = response.session_id

Architecture

QKD and Classical Networks

True QKD requires a physical quantum channel (photon transmission over fiber optics). This library simulates the quantum channel using Cirq, making it suitable for:

  • Education and prototyping -- learn and develop QKD-secured applications without quantum hardware
  • Integration testing -- validate your application's encryption pipeline end-to-end
  • Research -- experiment with protocol parameters, noise models, and error thresholds

The classical post-processing (basis reconciliation, error estimation, privacy amplification) runs over standard HTTP/gRPC and is protocol-accurate. The QuantumChannel abstraction is pluggable -- swap SimulatedChannel for a real hardware adapter without changing application code.

Package Structure

shorkin/
    classical/          # Classical order finding (brute-force)
    quantum/            # Quantum order finding (Cirq QPE)
    factor.py           # Shor's algorithm orchestration
    deutsch_jozsa.py    # Deutsch-Jozsa algorithm
    grover.py           # Grover's search algorithm
    teleportation.py    # Quantum teleportation protocol
    gates.py            # Gate aliases, helpers, and GateChain builder
    cli.py              # CLI entry point
    qkd/                # QKD protocol engines
        bb84.py         # BB84 protocol
        b92.py          # B92 protocol
        e91.py          # E91 protocol
        channel.py      # QuantumChannel Protocol + SimulatedChannel
        encryption.py   # AES-256-GCM encrypt/decrypt
        key_store.py    # Session key storage with rotation/expiration
    transport/          # HTTP & gRPC integrations
        http/
            fastapi.py  # FastAPI middleware + Depends()
            starlette.py
            django.py
            tornado.py
        grpc/
            servicer.py     # QKDKeyExchange gRPC service
            interceptor.py  # Client + server interceptors

Key Types

from shorkin.qkd import QKDResult

result: QKDResult
result.final_key          # bytes -- the usable symmetric key
result.raw_key            # bytes -- key before privacy amplification
result.protocol           # str -- "bb84", "b92", or "e91"
result.qber               # float -- quantum bit error rate
result.key_length_bits    # int -- final key length in bits
result.initial_qubit_count  # int -- qubits transmitted
result.sifted_key_length  # int -- bits after sifting
result.amplified          # bool -- privacy amplification applied
result.metadata           # dict -- protocol-specific (e.g., chsh_value for E91)

Development

# Clone and install in dev mode
git clone https://github.com/yourusername/shorkin.git
cd shorkin
pip install -e ".[all]"

# Run tests
pytest

# Run only QKD tests
pytest tests/qkd/

# Run only transport tests
pytest tests/transport/

# Run only the original Shor tests
pytest tests/test_*.py

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shorkin-1.1.1.tar.gz (52.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shorkin-1.1.1-py3-none-any.whl (57.0 kB view details)

Uploaded Python 3

File details

Details for the file shorkin-1.1.1.tar.gz.

File metadata

  • Download URL: shorkin-1.1.1.tar.gz
  • Upload date:
  • Size: 52.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for shorkin-1.1.1.tar.gz
Algorithm Hash digest
SHA256 b557ab82f734702cf2ba95c495606908227a968c6efda5c6e0e984223a6182f4
MD5 181cb8bfb8feb3fd3216fbda7ff7f375
BLAKE2b-256 85961b4fd4907673e7e0bd41430f95067c26da89be8d53d2f9899ff2918ce5c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for shorkin-1.1.1.tar.gz:

Publisher: publish.yml on bjornaer/shorkin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file shorkin-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: shorkin-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 57.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for shorkin-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0a9ccd797c941d418abda1f704cf8f8e2dc517b46db1f6ee4e9b200ecc18fb67
MD5 1f8173152157c83236a18250bdf81c42
BLAKE2b-256 e7920fd8dbe5733f4e75ed9df6667e851d0a2499c614c2a41d87c538d628b173

See more details on using hashes here.

Provenance

The following attestation bundles were made for shorkin-1.1.1-py3-none-any.whl:

Publisher: publish.yml on bjornaer/shorkin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page