Spaces:
Running
Running
| """ | |
| 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}") |