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.
Files changed (54) hide show
  1. shorkin-0.2.0/PKG-INFO +404 -0
  2. shorkin-0.2.0/README.md +360 -0
  3. shorkin-0.2.0/pyproject.toml +71 -0
  4. shorkin-0.2.0/setup.cfg +4 -0
  5. shorkin-0.2.0/shorkin/__init__.py +6 -0
  6. shorkin-0.2.0/shorkin/classical/__init__.py +0 -0
  7. shorkin-0.2.0/shorkin/classical/continued_fractions.py +31 -0
  8. shorkin-0.2.0/shorkin/classical/math_utils.py +43 -0
  9. shorkin-0.2.0/shorkin/classical/order_finder.py +22 -0
  10. shorkin-0.2.0/shorkin/cli.py +138 -0
  11. shorkin-0.2.0/shorkin/display.py +47 -0
  12. shorkin-0.2.0/shorkin/factor.py +169 -0
  13. shorkin-0.2.0/shorkin/qkd/__init__.py +44 -0
  14. shorkin-0.2.0/shorkin/qkd/_types.py +60 -0
  15. shorkin-0.2.0/shorkin/qkd/b92.py +168 -0
  16. shorkin-0.2.0/shorkin/qkd/bb84.py +135 -0
  17. shorkin-0.2.0/shorkin/qkd/channel.py +174 -0
  18. shorkin-0.2.0/shorkin/qkd/e91.py +169 -0
  19. shorkin-0.2.0/shorkin/qkd/encryption.py +52 -0
  20. shorkin-0.2.0/shorkin/qkd/error_estimation.py +94 -0
  21. shorkin-0.2.0/shorkin/qkd/key_store.py +101 -0
  22. shorkin-0.2.0/shorkin/qkd/privacy_amplification.py +61 -0
  23. shorkin-0.2.0/shorkin/qkd/protocol.py +27 -0
  24. shorkin-0.2.0/shorkin/qkd/sifting.py +102 -0
  25. shorkin-0.2.0/shorkin/quantum/__init__.py +0 -0
  26. shorkin-0.2.0/shorkin/quantum/modular_exp.py +82 -0
  27. shorkin-0.2.0/shorkin/quantum/order_finder.py +120 -0
  28. shorkin-0.2.0/shorkin/rsa.py +37 -0
  29. shorkin-0.2.0/shorkin/transport/__init__.py +1 -0
  30. shorkin-0.2.0/shorkin/transport/_key_manager.py +167 -0
  31. shorkin-0.2.0/shorkin/transport/_messages.py +126 -0
  32. shorkin-0.2.0/shorkin/transport/grpc/__init__.py +1 -0
  33. shorkin-0.2.0/shorkin/transport/grpc/interceptor.py +141 -0
  34. shorkin-0.2.0/shorkin/transport/grpc/qkd_pb2.py +44 -0
  35. shorkin-0.2.0/shorkin/transport/grpc/qkd_pb2_grpc.py +148 -0
  36. shorkin-0.2.0/shorkin/transport/grpc/servicer.py +102 -0
  37. shorkin-0.2.0/shorkin/transport/http/__init__.py +1 -0
  38. shorkin-0.2.0/shorkin/transport/http/_base.py +129 -0
  39. shorkin-0.2.0/shorkin/transport/http/django.py +138 -0
  40. shorkin-0.2.0/shorkin/transport/http/fastapi.py +151 -0
  41. shorkin-0.2.0/shorkin/transport/http/starlette.py +112 -0
  42. shorkin-0.2.0/shorkin/transport/http/tornado.py +176 -0
  43. shorkin-0.2.0/shorkin.egg-info/PKG-INFO +404 -0
  44. shorkin-0.2.0/shorkin.egg-info/SOURCES.txt +52 -0
  45. shorkin-0.2.0/shorkin.egg-info/dependency_links.txt +1 -0
  46. shorkin-0.2.0/shorkin.egg-info/entry_points.txt +2 -0
  47. shorkin-0.2.0/shorkin.egg-info/requires.txt +34 -0
  48. shorkin-0.2.0/shorkin.egg-info/top_level.txt +1 -0
  49. shorkin-0.2.0/tests/test_classical_order_finder.py +45 -0
  50. shorkin-0.2.0/tests/test_cli.py +66 -0
  51. shorkin-0.2.0/tests/test_factor.py +71 -0
  52. shorkin-0.2.0/tests/test_math_utils.py +80 -0
  53. shorkin-0.2.0/tests/test_quantum_order_finder.py +78 -0
  54. 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