QuantumCrypt / src /e91.py
marlonsousa's picture
Upload 17 files
0173bbf verified
from .base import QuantumProtocol
from qiskit_aer import Aer
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
import numpy as np
import random
from typing import Dict, List, Tuple
from qiskit.visualization import circuit_drawer
class E91Protocol(QuantumProtocol):
"""
Implementação do protocolo E91 (Ekert91) baseado em emaranhamento.
O protocolo E91 usa pares de qubits emaranhados e medições em diferentes ângulos
para estabelecer uma chave segura e verificar a presença de espionagem através
da violação das desigualdades de Bell.
"""
def __init__(self, key_length: int = 128):
super().__init__(key_length)
self.simulator = Aer.get_backend('qasm_simulator')
self.current_circuit = None
# Ângulos de medição para Alice e Bob
self.alice_angles = [0, np.pi/4, np.pi/2]
self.bob_angles = [np.pi/4, np.pi/2, 3*np.pi/4]
def _prepare_entangled_pair(self) -> QuantumCircuit:
"""
Prepara um par de qubits emaranhados no estado de Bell Φ+.
Returns:
QuantumCircuit: Circuito com o par emaranhado
"""
qr = QuantumRegister(2, 'q')
cr = ClassicalRegister(2, 'c')
qc = QuantumCircuit(qr, cr)
# Criar estado de Bell Φ+ = (|00⟩ + |11⟩)/√2
qc.h(qr[0])
qc.cx(qr[0], qr[1])
self.current_circuit = qc
return qc
def _measure_qubit(self, circuit: QuantumCircuit, angle: float, qubit: int) -> QuantumCircuit:
"""
Adiciona medição em um ângulo específico para um qubit.
Args:
circuit (QuantumCircuit): Circuito a ser medido
angle (float): Ângulo de medição
qubit (int): Índice do qubit a ser medido
Returns:
QuantumCircuit: Circuito com medição adicionada
"""
# Rotação para o ângulo de medição
circuit.ry(2*angle, qubit)
circuit.measure([qubit], [qubit])
return circuit
def _check_bell_inequality(self, correlations: List[float]) -> bool:
"""
Verifica a violação da desigualdade de CHSH.
Args:
correlations (List[float]): Lista de correlações medidas
Returns:
bool: True se a desigualdade for violada (indicando ausência de espião)
"""
# Cálculo do parâmetro S da desigualdade CHSH
S = abs(sum(correlations))
# O valor teórico máximo é 2√2 ≈ 2.82
# Um valor > 2 indica violação da desigualdade
return S > 2
def _calculate_correlation(self, alice_results: List[int],
bob_results: List[int]) -> float:
"""
Calcula a correlação entre as medições de Alice e Bob.
Args:
alice_results (List[int]): Resultados das medições de Alice
bob_results (List[int]): Resultados das medições de Bob
Returns:
float: Valor da correlação (-1 a 1)
"""
if not alice_results or not bob_results:
return 0
return np.mean([a == b for a, b in zip(alice_results, bob_results)])
def generate_key(self) -> Dict[str, List[int]]:
"""
Executa o protocolo E91 completo para gerar uma chave compartilhada.
Returns:
Dict[str, List[int]]: Dicionário contendo as chaves finais de Alice e Bob
"""
self.logger.info(f"Iniciando protocolo E91 para gerar chave de {self.key_length} bits")
alice_key = []
bob_key = []
correlations = []
# Precisamos de mais pares para compensar descartes
num_pairs = self.key_length * 4
for _ in range(num_pairs):
# Preparar par emaranhado
circuit = self._prepare_entangled_pair()
# Alice e Bob escolhem ângulos aleatoriamente
alice_angle = random.choice(self.alice_angles)
bob_angle = random.choice(self.bob_angles)
# Adicionar medições
circuit = self._measure_qubit(circuit, alice_angle, 0) # Alice
circuit = self._measure_qubit(circuit, bob_angle, 1) # Bob
# Executar circuito
job = self.simulator.run(circuit, shots=1)
result = job.result()
counts = list(result.get_counts().keys())[0]
alice_result = int(counts[0])
bob_result = int(counts[1])
# Verificar se os ângulos são compatíveis para a chave
if alice_angle == bob_angle:
alice_key.append(alice_result)
bob_key.append(bob_result)
else:
# Usar para teste de Bell
correlation = self._calculate_correlation([alice_result], [bob_result])
correlations.append(correlation)
# Verificar violação da desigualdade de Bell
if not self._check_bell_inequality(correlations):
self.logger.error("Possível espionagem detectada - violação de Bell não observada!")
return {"alice": [], "bob": []}
# Cortar para o tamanho desejado
alice_key = alice_key[:self.key_length]
bob_key = bob_key[:self.key_length]
self.logger.info(f"Protocolo E91 concluído com sucesso. "
f"Chave final de {len(alice_key)} bits gerada.")
return {
"alice": alice_key,
"bob": bob_key
}
def get_circuit_visualization(self) -> str:
"""
Retorna a visualização do circuito atual em ASCII.
Returns:
str: Representação ASCII do circuito
"""
if self.current_circuit:
return circuit_drawer(self.current_circuit, output='text')
return "Nenhum circuito disponível"