Spaces:
Running
Running
File size: 27,226 Bytes
227c43a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
"""
High-Fidelity BB84 Protocol Simulation using Google Cirq with Realistic Quantum Effects.
This module builds a comprehensive BB84 quantum key distribution simulation that accounts for:
- Realistic photon loss based on distance in fiber optics
- Hardware-specific quantum noise models
- Eavesdropper detection and information leakage analysis
- Information reconciliation and privacy amplification
- Realistic security parameter estimation
"""
import cirq
import random
import numpy as np
import math
from cirq.contrib.svg import circuit_to_svg
# Physical constants
SPEED_OF_LIGHT = 299792458 # m/s
FIBER_LOSS_DB_PER_KM = 0.2 # Standard telecom fiber loss
DETECTOR_EFFICIENCY = 0.85 # Typical superconducting detector efficiency
def create_hardware_noise_model(hardware_type='fiber', distance_km=0, detector_dark_count=1e-6):
"""
Creates a realistic hardware-specific noise model.
Args:
hardware_type: Type of quantum hardware ('fiber', 'satellite', 'trapped_ion')
distance_km: Distance between Alice and Bob in kilometers
detector_dark_count: Dark count probability per detection window
Returns:
Dictionary with noise parameters
"""
models = {
'fiber': {
'photon_loss': 1 - 10**(-FIBER_LOSS_DB_PER_KM * distance_km / 10),
'polarization_drift': min(0.01 * distance_km, 0.1), # Polarization drift in fiber
'phase_drift': min(0.005 * distance_km, 0.1), # Phase drift
'detector_efficiency': DETECTOR_EFFICIENCY,
'dark_count_probability': detector_dark_count,
'timing_jitter': 50e-12 * (1 + 0.01 * distance_km), # Timing jitter in seconds
'coherence_time': 1e-9 # 1 nanosecond coherence time in fiber
},
'satellite': {
'photon_loss': 1 - 10**(-0.07 * distance_km / 10), # Lower atmospheric loss
'polarization_drift': 0.001 * distance_km,
'phase_drift': 0.002 * distance_km,
'detector_efficiency': 0.7, # Lower efficiency in space-based detectors
'dark_count_probability': 1e-7, # Lower dark counts in space
'timing_jitter': 100e-12,
'coherence_time': 5e-9 # Longer coherence in free space
},
'trapped_ion': {
'photon_loss': 0.1, # Minimal loss in controlled environment
'polarization_drift': 0.001,
'phase_drift': 0.001,
'detector_efficiency': 0.95, # High efficiency
'dark_count_probability': 1e-8,
'timing_jitter': 10e-12,
'coherence_time': 1e-6 # Much longer coherence in trapped ion systems
}
}
return models.get(hardware_type, models['fiber'])
def add_realistic_noise(circuit, noise_model, qubit):
"""Add realistic hardware-specific noise to the circuit."""
noisy_circuit = cirq.Circuit()
# Add original operations
for op in circuit.all_operations():
noisy_circuit.append(op)
# Add depolarizing channel to model general noise
depolarizing_prob = min(0.01, noise_model['phase_drift'] + noise_model['polarization_drift'])
noisy_circuit.append(cirq.depolarize(depolarizing_prob).on(qubit))
# Add amplitude damping to model photon loss during computation
if noise_model['photon_loss'] > 0:
amp_damp_prob = min(0.1, noise_model['photon_loss'] / 10) # Scale down for gate operations
noisy_circuit.append(cirq.amplitude_damp(amp_damp_prob).on(qubit))
# Add phase damping to model decoherence
coherence_error = min(0.05, 1e-9 / noise_model['coherence_time'])
noisy_circuit.append(cirq.phase_damp(coherence_error).on(qubit))
return noisy_circuit
def simulate_eavesdropping(alice_bits, alice_bases, eve_strategy, detection_probability=0.5):
"""
Simulate an eavesdropper with various attack strategies.
Args:
alice_bits: Alice's original random bits
alice_bases: Alice's chosen bases
eve_strategy: Strategy ('intercept_resend', 'beam_splitting', 'trojan_horse')
detection_probability: Probability of Eve being detected per intercepted bit
Returns:
Dictionary with eavesdropping results and analysis
"""
eve_bases = [random.choice(['Z', 'X']) for _ in range(len(alice_bits))]
eve_measurements = []
modified_states = []
detection_events = []
information_gain = 0
for i in range(len(alice_bits)):
if eve_strategy == 'intercept_resend':
# Eve measures in her random basis
if eve_bases[i] == alice_bases[i]:
# If Eve uses same basis as Alice, she gets correct result
eve_measurement = alice_bits[i]
detection = False # Eve won't be detected here
else:
# If Eve uses wrong basis, she gets random result
eve_measurement = random.randint(0, 1)
detection = random.random() < detection_probability # Eve might be detected
# Eve resends based on her measurement and basis
if eve_bases[i] == alice_bases[i]:
# If Eve measured in correct basis, state is unchanged
modified_state = alice_bits[i]
else:
# If Eve measured in wrong basis, state is randomized
modified_state = random.randint(0, 1)
elif eve_strategy == 'beam_splitting':
# Eve captures a portion of photons in a beam splitting attack
# She only gets information when measuring in correct basis
if eve_bases[i] == alice_bases[i]:
eve_measurement = alice_bits[i]
information_gain += 1
else:
eve_measurement = random.randint(0, 1)
# Original state is preserved, harder to detect
modified_state = alice_bits[i]
detection = random.random() < (detection_probability / 3) # Much harder to detect
elif eve_strategy == 'trojan_horse':
# Eve sends additional photons to probe the system
eve_measurement = alice_bits[i] # Gets perfect information
modified_state = alice_bits[i] # State is preserved
detection = random.random() < (detection_probability * 2) # Easier to detect
information_gain += 1
else: # No eavesdropping or unknown strategy
eve_measurement = None
modified_state = alice_bits[i]
detection = False
eve_measurements.append(eve_measurement)
modified_states.append(modified_state)
detection_events.append(detection)
# Calculate information leakage
if eve_strategy != 'none':
information_leak_ratio = information_gain / len(alice_bits)
else:
information_leak_ratio = 0
# Calculate detection probability
if any(detection_events):
eve_detected = True
detection_probability = sum(detection_events) / len(detection_events)
else:
eve_detected = False
detection_probability = 0
return {
'eve_bases': eve_bases,
'eve_measurements': eve_measurements,
'modified_states': modified_states,
'eve_detected': eve_detected,
'detection_probability': detection_probability,
'information_leak_ratio': information_leak_ratio
}
def information_reconciliation(alice_key, bob_key, error_rate, reconciliation_efficiency=0.8):
"""
Simulate information reconciliation to correct errors in the sifted key.
Args:
alice_key: Alice's sifted key bits
bob_key: Bob's sifted key bits
error_rate: Estimated quantum bit error rate
reconciliation_efficiency: Efficiency of the reconciliation protocol
Returns:
Dictionary with reconciliation results
"""
if not alice_key or not bob_key:
return {'success': False, 'corrected_bits': 0, 'bits_used': 0, 'remaining_error_rate': 0, 'final_key': []}
# Calculate theoretical bits needed for correction
if error_rate <= 0:
return {'success': True, 'corrected_bits': 0, 'bits_used': 0, 'remaining_error_rate': 0, 'final_key': alice_key}
# Shannon entropy for binary symmetric channel
h_binary = -error_rate * math.log2(error_rate) - (1-error_rate) * math.log2(1-error_rate) if 0 < error_rate < 1 else 0
bits_needed = len(alice_key) * h_binary / reconciliation_efficiency
# Simulate error correction
errors_identified = 0
corrected_key = bob_key.copy()
# Error correction simulation (simplified CASCADE protocol)
block_size = max(1, int(1 / error_rate))
for block_start in range(0, len(alice_key), block_size):
block_end = min(block_start + block_size, len(alice_key))
alice_block = alice_key[block_start:block_end]
bob_block = corrected_key[block_start:block_end]
# Check parity
alice_parity = sum(alice_block) % 2
bob_parity = sum(bob_block) % 2
# If parity differs, find and fix an error
if alice_parity != bob_parity:
# Binary search for error (simplified)
if len(bob_block) > 1:
mid = len(bob_block) // 2
if sum(alice_block[:mid]) % 2 != sum(bob_block[:mid]) % 2:
# Error is in first half
for i in range(mid):
if bob_block[i] != alice_block[i]:
corrected_key[block_start + i] = alice_block[i]
errors_identified += 1
break
else:
# Error is in second half
for i in range(mid, len(bob_block)):
if bob_block[i] != alice_block[i]:
corrected_key[block_start + i] = alice_block[i]
errors_identified += 1
break
else:
# Single bit block with error
corrected_key[block_start] = alice_block[0]
errors_identified += 1
# Calculate remaining error rate
remaining_errors = sum(1 for a, b in zip(alice_key, corrected_key) if a != b)
remaining_error_rate = remaining_errors / len(alice_key) if alice_key else 0
return {
'success': remaining_error_rate < error_rate / 10,
'corrected_bits': errors_identified,
'bits_used': min(len(alice_key), int(bits_needed)),
'remaining_error_rate': remaining_error_rate,
'final_key': corrected_key
}
def privacy_amplification(reconciled_key, leaked_bits, security_parameter=0.1):
"""
Perform privacy amplification to reduce potential knowledge by eavesdropper.
Args:
reconciled_key: Key after information reconciliation
leaked_bits: Estimated bits of information leaked to Eve
security_parameter: Extra security margin (0-1)
Returns:
Final secure key after privacy amplification
"""
if not reconciled_key:
return []
# Calculate final key length after privacy amplification
final_length = max(1, len(reconciled_key) - int(leaked_bits) - int(security_parameter * len(reconciled_key)))
if final_length <= 0:
return []
# Apply universal hash function (simplified as XOR with random bit masks)
secure_key = []
for i in range(final_length):
# Create random bit mask (Toeplitz matrix row)
mask = [random.randint(0, 1) for _ in range(len(reconciled_key))]
# XOR the key with mask
secure_bit = sum(k * m for k, m in zip(reconciled_key, mask)) % 2
secure_key.append(secure_bit)
return secure_key
def calculate_theoretical_key_rate(distance_km, hardware_type='fiber', eavesdropping=False):
"""
Calculate theoretical key rate based on distance and hardware parameters.
Args:
distance_km: Distance between Alice and Bob
hardware_type: Type of quantum hardware
eavesdropping: Whether eavesdropping is present
Returns:
Estimated key rate in bits/second
"""
# Get hardware parameters
noise_model = create_hardware_noise_model(hardware_type, distance_km)
# Calculate photon transmission probability
transmission_prob = (1 - noise_model['photon_loss']) * noise_model['detector_efficiency']
# Calculate QBER from noise parameters
qber = min(0.5, noise_model['polarization_drift'] + noise_model['phase_drift'] +
noise_model['dark_count_probability'] / max(1e-15, transmission_prob))
if eavesdropping:
qber = min(0.5, qber + 0.15) # Increased QBER due to eavesdropping
# Source rate (typical for QKD systems)
source_rate = 1e9 # 1 GHz photon generation rate
# Calculate raw key rate
raw_rate = source_rate * transmission_prob
# Calculate sifted key rate (50% of raw due to basis mismatch)
sifted_rate = raw_rate * 0.5
# Error correction efficiency factor
ec_efficiency = 1.2 # Typical CASCADE efficiency
# Calculate final key rate using GLLP formula (simplified)
if qber >= 0.11: # Above threshold for secure BB84
return 0
# Asymptotic key rate formula
h_binary = lambda x: 0 if x <= 0 or x >= 1 else -x*math.log2(x)-(1-x)*math.log2(1-x)
final_rate = sifted_rate * (1 - h_binary(qber) - ec_efficiency * h_binary(qber))
# Apply practical limitations
final_rate = max(0, final_rate) # Can't be negative
return final_rate
def bb84_protocol_cirq(num_bits=10, distance_km=0, hardware_type='fiber',
eve_present=False, eve_strategy='intercept_resend',
detector_dark_count=1e-6, detailed_simulation=True,
perform_reconciliation=True, perform_amplification=True,
noise_prob=0.0):
"""
Simulates the BB84 quantum key distribution protocol with realistic physical effects.
Args:
num_bits: Number of qubits to transmit
distance_km: Distance between Alice and Bob in kilometers
hardware_type: Type of quantum hardware ('fiber', 'satellite', 'trapped_ion')
eve_present: Whether an eavesdropper is present
eve_strategy: Eve's attack strategy if present
detector_dark_count: Dark count probability per detection window
detailed_simulation: Whether to run full quantum circuit simulation for each qubit
perform_reconciliation: Whether to perform information reconciliation
perform_amplification: Whether to perform privacy amplification
Returns:
Dictionary with BB84 protocol results and analysis
"""
log = []
log.append("=== BB84 Protocol Simulation with Realistic Quantum Effects ===")
# Create noise model based on hardware parameters
noise_model = create_hardware_noise_model(hardware_type, distance_km, detector_dark_count)
log.append(f"Hardware configuration: {hardware_type} over {distance_km} km")
log.append(f"Noise model parameters: {noise_model}")
# Calculate theoretical key rate
theoretical_key_rate = calculate_theoretical_key_rate(distance_km, hardware_type, eve_present)
log.append(f"Theoretical key rate: {theoretical_key_rate:.2f} bits/second")
# Alice generates random bits and basis choices
alice_bits = [random.randint(0, 1) for _ in range(num_bits)]
alice_bases = [random.choice(['Z', 'X']) for _ in range(num_bits)]
log.append(f"Alice generated {num_bits} random bits and basis choices")
# Bob generates random basis choices
bob_bases = [random.choice(['Z', 'X']) for _ in range(num_bits)]
log.append(f"Bob generated {num_bits} random basis choices")
# Quantum transmission simulation
transmitted_states = []
bob_received_states = []
bob_measurements = []
# Create a sample circuit visualization using only the first qubit
# This ensures we always have a valid circuit for SVG generation
sample_circuit = cirq.Circuit()
sample_q = cirq.NamedQubit('q0')
# Add representative operations to sample circuit
sample_circuit.append(cirq.H(sample_q))
sample_circuit.append(cirq.measure(sample_q))
circuit_svg = circuit_to_svg(sample_circuit)
# Process each bit for quantum transmission
for i in range(num_bits):
log.append(f"\n-- Bit {i} --")
q = cirq.NamedQubit(f'q{i}')
circuit = cirq.Circuit()
# State preparation by Alice
if alice_bits[i] == 1:
circuit.append(cirq.X(q))
log.append(f"Alice prepares |1⟩ state for bit {i}")
else:
log.append(f"Alice prepares |0⟩ state for bit {i}")
# Basis selection by Alice
if alice_bases[i] == 'X':
circuit.append(cirq.H(q))
log.append(f"Alice uses X basis (Hadamard applied)")
else:
log.append(f"Alice uses Z basis (computational basis)")
# Simulate photon loss based on distance
photon_lost = random.random() < noise_model['photon_loss']
if photon_lost:
log.append(f"Photon lost in transmission (probability: {noise_model['photon_loss']:.4f})")
bob_received_states.append(None)
bob_measurements.append(None)
continue
# Eve's interaction if present
if eve_present:
if i == 0: # Log once for clarity
log.append(f"Eve is present using '{eve_strategy}' strategy")
# Create Eve's circuit for interception (detailed simulation only for first few bits)
if i < 5 and detailed_simulation:
eve_q = cirq.NamedQubit(f'eve_q{i}')
eve_circuit = cirq.Circuit()
# Eve measures in her chosen basis
if eve_strategy == 'intercept_resend':
eve_basis = random.choice(['Z', 'X'])
if eve_basis == 'X':
eve_circuit.append(cirq.H(eve_q))
eve_circuit.append(cirq.measure(eve_q, key='eve_meas'))
# Prepare state to send to Bob based on Eve's measurement
eve_result = random.randint(0, 1) # Simplified for non-executed circuit
if eve_result == 1:
circuit.append(cirq.X(q))
if eve_basis == 'X':
circuit.append(cirq.H(q))
log.append(f"Eve intercepted bit {i} using {eve_strategy}")
# Add realistic hardware noise
if detailed_simulation:
circuit = add_realistic_noise(circuit, noise_model, q)
# Bob's basis selection and measurement
if bob_bases[i] == 'X':
circuit.append(cirq.H(q))
log.append(f"Bob uses X basis (Hadamard applied)")
else:
log.append(f"Bob uses Z basis (computational basis)")
# Detector dark count simulation
dark_count_occurred = random.random() < noise_model['dark_count_probability']
if dark_count_occurred:
bob_measurement = random.randint(0, 1)
log.append(f"Detector dark count occurred, random measurement: {bob_measurement}")
else:
# Measurement simulation
if detailed_simulation:
circuit.append(cirq.measure(q, key='meas'))
simulator = cirq.Simulator()
result = simulator.run(circuit, repetitions=1)
bob_measurement = int(result.measurements['meas'][0][0])
else:
# Simplified measurement model without full circuit simulation
correct_basis = alice_bases[i] == bob_bases[i]
if correct_basis:
# With probability (1-error_rate), Bob gets correct result
error_prob = noise_model['polarization_drift'] + noise_model['phase_drift']
if random.random() < error_prob:
bob_measurement = 1 - alice_bits[i] # Error in measurement
else:
bob_measurement = alice_bits[i] # Correct measurement
else:
# Different bases, random outcome
bob_measurement = random.randint(0, 1)
log.append(f"Bob's measurement: {bob_measurement}")
bob_measurements.append(bob_measurement)
bob_received_states.append(True) # Successfully received
# Sift key - keep only bits where both used same basis and photon wasn't lost
matching_bases = [i for i in range(num_bits) if
bob_received_states[i] is not None and
alice_bases[i] == bob_bases[i]]
shared_key = [alice_bits[i] for i in matching_bases]
bob_key = [bob_measurements[i] for i in matching_bases]
# Calculate QBER (Quantum Bit Error Rate)
errors = sum(a != b for a, b in zip(shared_key, bob_key))
qber = errors / len(shared_key) if shared_key else 0
log.append(f"\nMatching bases indices: {matching_bases}")
log.append(f"Raw key length: {num_bits}")
log.append(f"Sifted key length: {len(shared_key)}")
log.append(f"Transmission efficiency: {len(bob_received_states) - bob_received_states.count(None)}/{num_bits}")
log.append(f"Sifted key efficiency: {len(shared_key)}/{num_bits}")
log.append(f"Alice's sifted key: {shared_key}")
log.append(f"Bob's measured key: {bob_key}")
log.append(f"QBER: {qber:.4f}")
# Eavesdropper detection using QBER
qber_threshold = 0.11 # Theoretical threshold for BB84
eve_detected_by_qber = qber > qber_threshold
if eve_detected_by_qber:
log.append(f"WARNING: QBER ({qber:.4f}) exceeds threshold ({qber_threshold}), possible eavesdropper detected!")
else:
log.append(f"QBER within acceptable limits, no evidence of eavesdropping")
# Eavesdropping simulation results
eve_results = None
if eve_present:
eve_results = simulate_eavesdropping(alice_bits, alice_bases, eve_strategy)
log.append(f"\nEavesdropping simulation:")
log.append(f"Eve detected: {eve_results['eve_detected']}")
log.append(f"Information leak ratio: {eve_results['information_leak_ratio']:.4f}")
# Information reconciliation
reconciliation_results = None
if shared_key and perform_reconciliation:
reconciliation_results = information_reconciliation(shared_key, bob_key, qber)
log.append(f"\nInformation reconciliation:")
log.append(f"Errors corrected: {reconciliation_results['corrected_bits']}")
log.append(f"Bits used for correction: {reconciliation_results['bits_used']}")
log.append(f"Remaining error rate: {reconciliation_results['remaining_error_rate']:.6f}")
log.append(f"Reconciliation success: {reconciliation_results['success']}")
bob_key = reconciliation_results['final_key']
# Privacy amplification
final_key = None
if shared_key and bob_key and perform_amplification:
# Estimate information leakage
leaked_bits = 0
if eve_present and eve_results:
leaked_bits = int(eve_results['information_leak_ratio'] * len(shared_key))
elif qber > 0:
# Conservative estimate based on QBER
leaked_bits = int(qber * len(shared_key) * 2)
final_key = privacy_amplification(bob_key, leaked_bits)
log.append(f"\nPrivacy amplification:")
log.append(f"Estimated information leakage: {leaked_bits} bits")
log.append(f"Final secure key length: {len(final_key)}")
log.append(f"Final key rate: {len(final_key)/(num_bits)} bits per transmitted qubit")
# Calculate theoretical secure key rate for this setup
secure_key_rate = calculate_theoretical_key_rate(distance_km, hardware_type, eve_present)
log.append(f"\nTheoretical secure key rate: {secure_key_rate:.2f} bits/second")
# Return comprehensive results
return {
'alice_bits': alice_bits,
'alice_bases': alice_bases,
'bob_bases': bob_bases,
'bob_measurements': bob_measurements,
'matching_bases': matching_bases,
'shared_key': shared_key,
'bob_key': bob_key,
'final_key': final_key,
'error_rate': qber,
'eve_detected_by_qber': eve_detected_by_qber,
'photon_loss_rate': noise_model['photon_loss'],
'transmission_efficiency': (len(bob_received_states) - bob_received_states.count(None))/num_bits,
'sifted_key_ratio': len(shared_key)/num_bits if num_bits > 0 else 0,
'final_key_ratio': len(final_key)/num_bits if final_key and num_bits > 0 else 0,
'secure_key_rate': secure_key_rate,
'noise_model': noise_model,
'eavesdropper_results': eve_results,
'reconciliation_results': reconciliation_results,
'circuit_svg': circuit_svg,
'log': "\n".join(log)
}
if __name__ == '__main__':
# Basic simulation
result = bb84_protocol_cirq(10, distance_km=0)
print("Cirq BB84 Simulation Result:")
print("Shared key:", result['shared_key'])
print("Error rate:", f"{result['error_rate']:.2%}")
# Run realistic range test
distances = [0, 10, 50, 100, 200]
print("\nDistance Test:")
for dist in distances:
dist_result = bb84_protocol_cirq(100, distance_km=dist, detailed_simulation=False)
print(f"{dist} km: Key rate = {dist_result['secure_key_rate']:.2f} bits/s, "
f"QBER = {dist_result['error_rate']:.4f}")
# Eavesdropper test
eve_result = bb84_protocol_cirq(100, distance_km=50, eve_present=True,
eve_strategy='intercept_resend')
print("\nWith Eavesdropper:")
print(f"QBER = {eve_result['error_rate']:.4f}")
print(f"Eve detected: {eve_result['eve_detected_by_qber']}")
print(f"Final key length: {len(eve_result['final_key']) if eve_result['final_key'] else 0}") |