shorkin 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- shorkin-0.2.0/PKG-INFO +404 -0
- shorkin-0.2.0/README.md +360 -0
- shorkin-0.2.0/pyproject.toml +71 -0
- shorkin-0.2.0/setup.cfg +4 -0
- shorkin-0.2.0/shorkin/__init__.py +6 -0
- shorkin-0.2.0/shorkin/classical/__init__.py +0 -0
- shorkin-0.2.0/shorkin/classical/continued_fractions.py +31 -0
- shorkin-0.2.0/shorkin/classical/math_utils.py +43 -0
- shorkin-0.2.0/shorkin/classical/order_finder.py +22 -0
- shorkin-0.2.0/shorkin/cli.py +138 -0
- shorkin-0.2.0/shorkin/display.py +47 -0
- shorkin-0.2.0/shorkin/factor.py +169 -0
- shorkin-0.2.0/shorkin/qkd/__init__.py +44 -0
- shorkin-0.2.0/shorkin/qkd/_types.py +60 -0
- shorkin-0.2.0/shorkin/qkd/b92.py +168 -0
- shorkin-0.2.0/shorkin/qkd/bb84.py +135 -0
- shorkin-0.2.0/shorkin/qkd/channel.py +174 -0
- shorkin-0.2.0/shorkin/qkd/e91.py +169 -0
- shorkin-0.2.0/shorkin/qkd/encryption.py +52 -0
- shorkin-0.2.0/shorkin/qkd/error_estimation.py +94 -0
- shorkin-0.2.0/shorkin/qkd/key_store.py +101 -0
- shorkin-0.2.0/shorkin/qkd/privacy_amplification.py +61 -0
- shorkin-0.2.0/shorkin/qkd/protocol.py +27 -0
- shorkin-0.2.0/shorkin/qkd/sifting.py +102 -0
- shorkin-0.2.0/shorkin/quantum/__init__.py +0 -0
- shorkin-0.2.0/shorkin/quantum/modular_exp.py +82 -0
- shorkin-0.2.0/shorkin/quantum/order_finder.py +120 -0
- shorkin-0.2.0/shorkin/rsa.py +37 -0
- shorkin-0.2.0/shorkin/transport/__init__.py +1 -0
- shorkin-0.2.0/shorkin/transport/_key_manager.py +167 -0
- shorkin-0.2.0/shorkin/transport/_messages.py +126 -0
- shorkin-0.2.0/shorkin/transport/grpc/__init__.py +1 -0
- shorkin-0.2.0/shorkin/transport/grpc/interceptor.py +141 -0
- shorkin-0.2.0/shorkin/transport/grpc/qkd_pb2.py +44 -0
- shorkin-0.2.0/shorkin/transport/grpc/qkd_pb2_grpc.py +148 -0
- shorkin-0.2.0/shorkin/transport/grpc/servicer.py +102 -0
- shorkin-0.2.0/shorkin/transport/http/__init__.py +1 -0
- shorkin-0.2.0/shorkin/transport/http/_base.py +129 -0
- shorkin-0.2.0/shorkin/transport/http/django.py +138 -0
- shorkin-0.2.0/shorkin/transport/http/fastapi.py +151 -0
- shorkin-0.2.0/shorkin/transport/http/starlette.py +112 -0
- shorkin-0.2.0/shorkin/transport/http/tornado.py +176 -0
- shorkin-0.2.0/shorkin.egg-info/PKG-INFO +404 -0
- shorkin-0.2.0/shorkin.egg-info/SOURCES.txt +52 -0
- shorkin-0.2.0/shorkin.egg-info/dependency_links.txt +1 -0
- shorkin-0.2.0/shorkin.egg-info/entry_points.txt +2 -0
- shorkin-0.2.0/shorkin.egg-info/requires.txt +34 -0
- shorkin-0.2.0/shorkin.egg-info/top_level.txt +1 -0
- shorkin-0.2.0/tests/test_classical_order_finder.py +45 -0
- shorkin-0.2.0/tests/test_cli.py +66 -0
- shorkin-0.2.0/tests/test_factor.py +71 -0
- shorkin-0.2.0/tests/test_math_utils.py +80 -0
- shorkin-0.2.0/tests/test_quantum_order_finder.py +78 -0
- shorkin-0.2.0/tests/test_rsa.py +53 -0
shorkin-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shorkin
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Quantum cryptography toolkit: Shor's algorithm and QKD protocols
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Classifier: Development Status :: 4 - Beta
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Intended Audience :: Science/Research
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Topic :: Security :: Cryptography
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: cirq-core<2.0,>=1.3
|
|
19
|
+
Requires-Dist: sympy>=1.12
|
|
20
|
+
Requires-Dist: cryptography>=41.0
|
|
21
|
+
Requires-Dist: numpy>=1.24
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest-timeout>=2.0; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
26
|
+
Requires-Dist: httpx>=0.24; extra == "dev"
|
|
27
|
+
Provides-Extra: fastapi
|
|
28
|
+
Requires-Dist: fastapi>=0.100; extra == "fastapi"
|
|
29
|
+
Requires-Dist: starlette>=0.27; extra == "fastapi"
|
|
30
|
+
Provides-Extra: starlette
|
|
31
|
+
Requires-Dist: starlette>=0.27; extra == "starlette"
|
|
32
|
+
Provides-Extra: django
|
|
33
|
+
Requires-Dist: django>=4.2; extra == "django"
|
|
34
|
+
Provides-Extra: tornado
|
|
35
|
+
Requires-Dist: tornado>=6.3; extra == "tornado"
|
|
36
|
+
Provides-Extra: grpc
|
|
37
|
+
Requires-Dist: grpcio>=1.57; extra == "grpc"
|
|
38
|
+
Requires-Dist: grpcio-tools>=1.57; extra == "grpc"
|
|
39
|
+
Requires-Dist: protobuf>=4.24; extra == "grpc"
|
|
40
|
+
Provides-Extra: http
|
|
41
|
+
Requires-Dist: shorkin[django,fastapi,starlette,tornado]; extra == "http"
|
|
42
|
+
Provides-Extra: all
|
|
43
|
+
Requires-Dist: shorkin[dev,grpc,http]; extra == "all"
|
|
44
|
+
|
|
45
|
+
# Shorkin
|
|
46
|
+
|
|
47
|
+
A quantum cryptography toolkit for Python. Implements **Shor's algorithm** for integer factorization and **Quantum Key Distribution (QKD)** protocols with HTTP and gRPC transport integrations.
|
|
48
|
+
|
|
49
|
+
Quantum simulation is powered by [Google Cirq](https://quantumai.google/cirq). QKD-derived keys are used for AES-256-GCM payload encryption.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Core library (Shor's algorithm + QKD protocols)
|
|
55
|
+
pip install shorkin
|
|
56
|
+
|
|
57
|
+
# With a specific web framework
|
|
58
|
+
pip install shorkin[fastapi]
|
|
59
|
+
pip install shorkin[django]
|
|
60
|
+
pip install shorkin[starlette]
|
|
61
|
+
pip install shorkin[tornado]
|
|
62
|
+
|
|
63
|
+
# With gRPC support
|
|
64
|
+
pip install shorkin[grpc]
|
|
65
|
+
|
|
66
|
+
# Everything
|
|
67
|
+
pip install shorkin[all]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Requires Python 3.10+.
|
|
71
|
+
|
|
72
|
+
## Shor's Algorithm
|
|
73
|
+
|
|
74
|
+
Factor composite integers using a quantum (simulated via Cirq) or classical order-finding backend.
|
|
75
|
+
|
|
76
|
+
### CLI
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Factor an integer
|
|
80
|
+
shorkin factor 15
|
|
81
|
+
# 15 = 3 x 5
|
|
82
|
+
|
|
83
|
+
# Factor with a specific mode
|
|
84
|
+
shorkin factor 21 --mode classical
|
|
85
|
+
shorkin factor 15 --mode quantum --verbose
|
|
86
|
+
|
|
87
|
+
# Factor the modulus from an RSA public key
|
|
88
|
+
shorkin factor-key path/to/public.pem
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Library
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from shorkin.factor import factor
|
|
95
|
+
from shorkin.classical.order_finder import find_order
|
|
96
|
+
|
|
97
|
+
class ClassicalFinder:
|
|
98
|
+
method_name = "classical"
|
|
99
|
+
def find_order(self, x, n):
|
|
100
|
+
return find_order(x, n)
|
|
101
|
+
|
|
102
|
+
result = factor(15, ClassicalFinder())
|
|
103
|
+
print(result.factors) # [3, 5]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## QKD Protocols
|
|
107
|
+
|
|
108
|
+
Three quantum key distribution protocols, all following a common `QKDProtocol` interface:
|
|
109
|
+
|
|
110
|
+
| Protocol | Description | Sifting Yield | QBER Threshold |
|
|
111
|
+
|----------|-------------|---------------|----------------|
|
|
112
|
+
| **BB84** | 2 bases, 4 states (Bennett-Brassard 1984) | ~50% | ~11% |
|
|
113
|
+
| **B92** | 2 non-orthogonal states (Bennett 1992) | ~25% | ~5% |
|
|
114
|
+
| **E91** | Entanglement-based with CHSH Bell test (Ekert 1991) | ~22% | ~11% |
|
|
115
|
+
|
|
116
|
+
### Basic Usage
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from shorkin.qkd import BB84, B92, E91, SimulatedChannel
|
|
120
|
+
|
|
121
|
+
# Create a simulated quantum channel
|
|
122
|
+
channel = SimulatedChannel(error_rate=0.02, seed=42)
|
|
123
|
+
|
|
124
|
+
# Generate a shared key using BB84
|
|
125
|
+
protocol = BB84(seed=42)
|
|
126
|
+
result = protocol.generate_key(num_qubits=4096, channel=channel)
|
|
127
|
+
|
|
128
|
+
print(f"Protocol: {result.protocol}")
|
|
129
|
+
print(f"QBER: {result.qber:.4f}")
|
|
130
|
+
print(f"Key: {result.final_key.hex()}")
|
|
131
|
+
print(f"Key bits: {result.key_length_bits}")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Choosing a Protocol
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
# BB84 -- the standard, good balance of efficiency and security
|
|
138
|
+
protocol = BB84(seed=42)
|
|
139
|
+
result = protocol.generate_key(num_qubits=4096, channel=channel)
|
|
140
|
+
|
|
141
|
+
# B92 -- simpler (2 states), lower yield, needs more qubits
|
|
142
|
+
protocol = B92(seed=42)
|
|
143
|
+
result = protocol.generate_key(num_qubits=8000, channel=channel)
|
|
144
|
+
|
|
145
|
+
# E91 -- entanglement-based, includes Bell inequality (CHSH) test
|
|
146
|
+
protocol = E91(seed=42)
|
|
147
|
+
result = protocol.generate_key(num_qubits=20000, channel=channel)
|
|
148
|
+
print(f"CHSH value: {result.metadata['chsh_value']:.3f}") # > 2.0 = secure
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Encrypt / Decrypt with QKD Keys
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from shorkin.qkd import BB84, SimulatedChannel, encrypt, decrypt
|
|
155
|
+
|
|
156
|
+
channel = SimulatedChannel(seed=42)
|
|
157
|
+
result = BB84(seed=42).generate_key(num_qubits=4096, channel=channel)
|
|
158
|
+
|
|
159
|
+
ciphertext = encrypt(b"secret payload", result.final_key)
|
|
160
|
+
plaintext = decrypt(ciphertext, result.final_key)
|
|
161
|
+
assert plaintext == b"secret payload"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Simulated Channel Options
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from shorkin.qkd import SimulatedChannel
|
|
168
|
+
|
|
169
|
+
# Perfect channel (no errors, no loss)
|
|
170
|
+
channel = SimulatedChannel()
|
|
171
|
+
|
|
172
|
+
# Noisy channel (5% bit-flip error rate)
|
|
173
|
+
channel = SimulatedChannel(error_rate=0.05)
|
|
174
|
+
|
|
175
|
+
# Lossy channel (10% photon loss)
|
|
176
|
+
channel = SimulatedChannel(loss_rate=0.10)
|
|
177
|
+
|
|
178
|
+
# Both noise and loss
|
|
179
|
+
channel = SimulatedChannel(error_rate=0.03, loss_rate=0.05, seed=42)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The `QuantumChannel` is a `typing.Protocol` -- you can implement your own to connect to real quantum hardware.
|
|
183
|
+
|
|
184
|
+
## HTTP Integration
|
|
185
|
+
|
|
186
|
+
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.
|
|
187
|
+
|
|
188
|
+
### FastAPI
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from fastapi import Depends, FastAPI
|
|
192
|
+
from shorkin.transport.http.fastapi import QKDMiddleware, QKDSession, qkd_session
|
|
193
|
+
|
|
194
|
+
app = FastAPI()
|
|
195
|
+
|
|
196
|
+
# Option 1: Middleware (encrypts all responses for active sessions)
|
|
197
|
+
app.add_middleware(QKDMiddleware, protocol="bb84")
|
|
198
|
+
|
|
199
|
+
# Option 2: Dependency injection (per-route control)
|
|
200
|
+
@app.get("/secure")
|
|
201
|
+
async def secure_endpoint(qkd: QKDSession = Depends(qkd_session("bb84"))):
|
|
202
|
+
if qkd.is_active:
|
|
203
|
+
return {"encrypted": qkd.encrypt(b"secret").hex()}
|
|
204
|
+
return {"message": "no QKD session"}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### Client usage with FastAPI
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
import httpx
|
|
211
|
+
|
|
212
|
+
# Step 1: Initiate key exchange
|
|
213
|
+
resp = httpx.post("http://localhost:8000/.well-known/qkd/initiate", json={
|
|
214
|
+
"protocol": "bb84",
|
|
215
|
+
"peer_id": "my-client",
|
|
216
|
+
})
|
|
217
|
+
session_id = resp.json()["session_id"]
|
|
218
|
+
|
|
219
|
+
# Step 2: Make requests with the session
|
|
220
|
+
resp = httpx.get("http://localhost:8000/secure", headers={
|
|
221
|
+
"X-QKD-Session-Id": session_id,
|
|
222
|
+
})
|
|
223
|
+
# Response body is AES-256-GCM encrypted
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Starlette
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
from starlette.applications import Starlette
|
|
230
|
+
from shorkin.transport.http.starlette import QKDMiddleware
|
|
231
|
+
|
|
232
|
+
app = Starlette(routes=[...])
|
|
233
|
+
app.add_middleware(QKDMiddleware, protocol="bb84")
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Django
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
# settings.py
|
|
240
|
+
MIDDLEWARE = [
|
|
241
|
+
# ...
|
|
242
|
+
"shorkin.transport.http.django.QKDMiddleware",
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
SHORKIN_QKD = {
|
|
246
|
+
"PROTOCOL": "bb84", # or "b92", "e91"
|
|
247
|
+
"NUM_QUBITS": 4096,
|
|
248
|
+
"TARGET_KEY_BITS": 256,
|
|
249
|
+
"STRICT": False, # True = reject requests without QKD session
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Tornado
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
import tornado.web
|
|
257
|
+
from shorkin.transport.http.tornado import QKDRequestMixin, qkd_routes
|
|
258
|
+
|
|
259
|
+
class SecureHandler(QKDRequestMixin, tornado.web.RequestHandler):
|
|
260
|
+
def get(self):
|
|
261
|
+
self.write(b"encrypted if QKD session is active")
|
|
262
|
+
|
|
263
|
+
app = tornado.web.Application(
|
|
264
|
+
qkd_routes("bb84") + [
|
|
265
|
+
(r"/secure", SecureHandler, {"qkd_protocol": "bb84"}),
|
|
266
|
+
]
|
|
267
|
+
)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Strict Mode
|
|
271
|
+
|
|
272
|
+
All HTTP integrations support `strict=True`, which rejects any request without an active QKD session (returns 403). QKD negotiation endpoints are always accessible.
|
|
273
|
+
|
|
274
|
+
## gRPC Integration
|
|
275
|
+
|
|
276
|
+
QKD key exchange is exposed as a `QKDKeyExchange` gRPC service. Client and server interceptors handle session metadata transparently.
|
|
277
|
+
|
|
278
|
+
### Server
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
from concurrent import futures
|
|
282
|
+
import grpc
|
|
283
|
+
from shorkin.transport.grpc.servicer import QKDKeyExchangeServicer
|
|
284
|
+
from shorkin.transport.grpc.interceptor import QKDServerInterceptor
|
|
285
|
+
from shorkin.transport.grpc import qkd_pb2_grpc
|
|
286
|
+
|
|
287
|
+
interceptor = QKDServerInterceptor(protocol="bb84")
|
|
288
|
+
server = grpc.server(
|
|
289
|
+
futures.ThreadPoolExecutor(max_workers=10),
|
|
290
|
+
interceptors=[interceptor],
|
|
291
|
+
)
|
|
292
|
+
servicer = QKDKeyExchangeServicer(protocol="bb84")
|
|
293
|
+
qkd_pb2_grpc.add_QKDKeyExchangeServicer_to_server(servicer, server)
|
|
294
|
+
server.add_insecure_port("[::]:50051")
|
|
295
|
+
server.start()
|
|
296
|
+
server.wait_for_termination()
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Client
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
import grpc
|
|
303
|
+
from shorkin.transport.grpc.interceptor import QKDClientInterceptor
|
|
304
|
+
from shorkin.transport.grpc import qkd_pb2, qkd_pb2_grpc
|
|
305
|
+
|
|
306
|
+
# Set up intercepted channel
|
|
307
|
+
interceptor = QKDClientInterceptor(protocol="bb84")
|
|
308
|
+
channel = grpc.intercept_channel(
|
|
309
|
+
grpc.insecure_channel("localhost:50051"),
|
|
310
|
+
interceptor,
|
|
311
|
+
)
|
|
312
|
+
stub = qkd_pb2_grpc.QKDKeyExchangeStub(channel)
|
|
313
|
+
|
|
314
|
+
# Initiate key exchange
|
|
315
|
+
response = stub.Initiate(qkd_pb2.KeyExchangeInitRequest(
|
|
316
|
+
protocol="bb84",
|
|
317
|
+
peer_id="my-service",
|
|
318
|
+
))
|
|
319
|
+
print(f"Session: {response.session_id}")
|
|
320
|
+
print(f"Status: {response.status}")
|
|
321
|
+
|
|
322
|
+
# Set session for subsequent calls
|
|
323
|
+
interceptor.session_id = response.session_id
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Architecture
|
|
327
|
+
|
|
328
|
+
### QKD and Classical Networks
|
|
329
|
+
|
|
330
|
+
True QKD requires a physical quantum channel (photon transmission over fiber optics). This library simulates the quantum channel using Cirq, making it suitable for:
|
|
331
|
+
|
|
332
|
+
- **Education and prototyping** -- learn and develop QKD-secured applications without quantum hardware
|
|
333
|
+
- **Integration testing** -- validate your application's encryption pipeline end-to-end
|
|
334
|
+
- **Research** -- experiment with protocol parameters, noise models, and error thresholds
|
|
335
|
+
|
|
336
|
+
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.
|
|
337
|
+
|
|
338
|
+
### Package Structure
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
shorkin/
|
|
342
|
+
classical/ # Classical order finding (brute-force)
|
|
343
|
+
quantum/ # Quantum order finding (Cirq QPE)
|
|
344
|
+
factor.py # Shor's algorithm orchestration
|
|
345
|
+
cli.py # CLI entry point
|
|
346
|
+
qkd/ # QKD protocol engines
|
|
347
|
+
bb84.py # BB84 protocol
|
|
348
|
+
b92.py # B92 protocol
|
|
349
|
+
e91.py # E91 protocol
|
|
350
|
+
channel.py # QuantumChannel Protocol + SimulatedChannel
|
|
351
|
+
encryption.py # AES-256-GCM encrypt/decrypt
|
|
352
|
+
key_store.py # Session key storage with rotation/expiration
|
|
353
|
+
transport/ # HTTP & gRPC integrations
|
|
354
|
+
http/
|
|
355
|
+
fastapi.py # FastAPI middleware + Depends()
|
|
356
|
+
starlette.py
|
|
357
|
+
django.py
|
|
358
|
+
tornado.py
|
|
359
|
+
grpc/
|
|
360
|
+
servicer.py # QKDKeyExchange gRPC service
|
|
361
|
+
interceptor.py # Client + server interceptors
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Key Types
|
|
365
|
+
|
|
366
|
+
```python
|
|
367
|
+
from shorkin.qkd import QKDResult
|
|
368
|
+
|
|
369
|
+
result: QKDResult
|
|
370
|
+
result.final_key # bytes -- the usable symmetric key
|
|
371
|
+
result.raw_key # bytes -- key before privacy amplification
|
|
372
|
+
result.protocol # str -- "bb84", "b92", or "e91"
|
|
373
|
+
result.qber # float -- quantum bit error rate
|
|
374
|
+
result.key_length_bits # int -- final key length in bits
|
|
375
|
+
result.initial_qubit_count # int -- qubits transmitted
|
|
376
|
+
result.sifted_key_length # int -- bits after sifting
|
|
377
|
+
result.amplified # bool -- privacy amplification applied
|
|
378
|
+
result.metadata # dict -- protocol-specific (e.g., chsh_value for E91)
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Development
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
# Clone and install in dev mode
|
|
385
|
+
git clone https://github.com/yourusername/shorkin.git
|
|
386
|
+
cd shorkin
|
|
387
|
+
pip install -e ".[all]"
|
|
388
|
+
|
|
389
|
+
# Run tests
|
|
390
|
+
pytest
|
|
391
|
+
|
|
392
|
+
# Run only QKD tests
|
|
393
|
+
pytest tests/qkd/
|
|
394
|
+
|
|
395
|
+
# Run only transport tests
|
|
396
|
+
pytest tests/transport/
|
|
397
|
+
|
|
398
|
+
# Run only the original Shor tests
|
|
399
|
+
pytest tests/test_*.py
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## License
|
|
403
|
+
|
|
404
|
+
MIT
|