marlonsousa commited on
Commit
0173bbf
·
verified ·
1 Parent(s): f93e9af

Upload 17 files

Browse files
README.md CHANGED
@@ -1,14 +1,105 @@
1
- ---
2
- title: QuantumCrypt
3
- emoji: 🏢
4
- colorFrom: green
5
- colorTo: blue
6
- sdk: gradio
7
- sdk_version: 5.17.1
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- short_description: Applied quantum cryptography
12
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # QuantumCrypt
2
+
3
+ ## BB84
4
+
5
+ ## Introduction
6
+ The BB84 protocol is a Quantum Key Distribution (QKD) scheme developed by Charles Bennett and Gilles Brassard in 1984. It enables two parties, traditionally called Alice and Bob, to securely share a secret key, ensuring resistance against eavesdropping attempts by an adversary (Eve).
7
+
8
+ ## Working Principle
9
+ BB84 leverages quantum mechanics to ensure secure communication. It relies on the properties of photon polarization and Heisenberg's uncertainty principle, making it impossible for an eavesdropper to measure photon states without disturbing the transmission.
10
+
11
+ The protocol operates as follows:
12
+ 1. **Photon Transmission:** Alice sends a sequence of randomly polarized photons in one of two possible bases (rectilinear `+` or diagonal `×`).
13
+ 2. **Random Measurement:** Bob measures each received photon using a randomly chosen basis.
14
+ 3. **Basis Comparison:** Alice and Bob publicly compare the bases used for each photon and discard cases where Bob used the incorrect basis.
15
+ 4. **Key Extraction:** The remaining bits form a shared secret key.
16
+ 5. **Error Checking:** Alice and Bob verify key integrity by publicly comparing a subset of the bits. If errors exceed a threshold, they abort the protocol.
17
+ 6. **Privacy Amplification:** If necessary, they apply classical error correction and privacy amplification techniques to refine the final secret key.
18
+
19
+ ## Security
20
+ The security of BB84 is based on the no-cloning theorem, which prevents an adversary from perfectly copying an unknown quantum state. Any attempt by Eve to measure photons introduces detectable errors, allowing Alice and Bob to discard compromised keys.
21
+
22
+ ## Applications
23
+ - Secure communication
24
+ - Quantum cryptography
25
+ - Future-proof encryption against quantum computing attacks
26
+
27
+
28
+
29
+ # E91
30
+
31
+ ## Overview
32
+
33
+ This project demonstrates how Alice and Bob can securely exchange a cryptographic key using the **E91 Quantum Key Distribution (QKD) Protocol**. The protocol, developed by **Artur Ekert in 1991**, leverages quantum entanglement and **Bell's theorem** to ensure that an eavesdropper, Eve, cannot gain any information about the key without detection.
34
+
35
+ ## Encryption and the One-Time Pad
36
+
37
+ To ensure message confidentiality, Alice encrypts her message using the **one-time pad** technique. This method relies on the **exclusive OR (XOR) operation** to combine the plaintext and a randomly generated key:
38
+
39
+ $$ c_i = m_i \oplus k_i $$
40
+
41
+ where:
42
+ - \( m \) is the plaintext message,
43
+ - \( k \) is the secret key,
44
+ - \( c \) is the ciphertext.
45
+
46
+ Decryption is performed using the same XOR operation:
47
 
48
+ $$ m_i = c_i \oplus k_i $$
49
+
50
+ Since the security of the **one-time pad** depends on the secrecy of the key, the main challenge is securely distributing this key between Alice and Bob. This is where quantum mechanics comes into play.
51
+
52
+ ## The E91 Quantum Key Distribution Protocol
53
+
54
+ The **E91 protocol** ensures secure key exchange using **quantum entanglement**. The steps are as follows:
55
+
56
+ ### 1. Entangled Qubits Distribution
57
+ Charlie (a trusted third party) generates **N pairs of entangled qubits** in the singlet state:
58
+
59
+ $$ \lvert\psi_s\rangle = \frac{1}{\sqrt{2}}(\lvert01\rangle - \lvert10\rangle) $$
60
+
61
+ Charlie then sends **one qubit** from each entangled pair to Alice and the other to Bob over a **quantum channel**.
62
+
63
+ ### 2. Measurement by Alice and Bob
64
+ - Alice and Bob independently choose random measurement bases and measure their received qubits.
65
+ - If they measure along the same basis, their results will be perfectly **anti-correlated** (i.e., opposite values).
66
+
67
+ ### 3. Classical Communication
68
+ - Alice and Bob share their measurement choices over a **public classical channel**.
69
+ - They discard measurements where bases do not match.
70
+ - The remaining bits form the **raw key**.
71
+
72
+ ### 4. Security Verification (Bell Test)
73
+ - Alice and Bob compute the **CHSH correlation value** to check for **Bell inequality violation**:
74
+
75
+ $$ C = \langle X \otimes W \rangle - \langle X \otimes V \rangle + \langle Z \otimes W \rangle + \langle Z \otimes V \rangle $$
76
+
77
+ - If the result exceeds the classical bound of **2** (e.g., \( C = -2\sqrt{2} \)), the key is confirmed to be **secure**.
78
+ - If Eve interfered, the Bell test would fail, alerting Alice and Bob to discard the key.
79
+
80
+ ### 5. Key Extraction
81
+ After removing potentially compromised bits, Alice and Bob apply **error correction** and **privacy amplification** techniques to finalize the **secret key**.
82
+
83
+ ## Why the E91 Protocol is Secure
84
+ - **Quantum Mechanics Guarantees Security**: Any attempt by Eve to measure the qubits **collapses their state**, altering results and revealing her presence.
85
+ - **Bell's Theorem and CHSH Inequality**: These ensure that no **local hidden variable theory** can explain the observed correlations, confirming true quantum entanglement.
86
+
87
+ ## Applications
88
+ - **Quantum-Safe Encryption**: Protects against attacks from quantum computers.
89
+ - **Secure Communications**: Used in diplomatic and military communication systems.
90
+ - **Quantum Networks**: Forms the foundation for future **quantum internet** applications.
91
+
92
+ ## Requirements
93
+ - Python (latest version recommended)
94
+ - Qiskit for quantum simulations
95
+ - Matplotlib for visualizing results
96
+ - NumPy for numerical computations
97
+
98
+ ## References
99
+ - [One-Time Pad](https://en.wikipedia.org/wiki/One-time_pad)
100
+ - [E91 Quantum Key Distribution](https://en.wikipedia.org/wiki/E91_protocol)
101
+ - [Bell's Theorem](https://en.wikipedia.org/wiki/Bell's_theorem)
102
+ - [Qiskit Quantum Information](https://qiskit.org/documentation/tutorials/circuits/3_summary_of_quantum_operations.html)
103
+
104
+ ---
105
+ This project demonstrates a secure method of quantum key distribution using entanglement and Bell's theorem, ensuring the highest level of encryption security.
app.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from src.bb84 import BB84Protocol
3
+ from src.e91 import E91Protocol
4
+ from src.circuit_viz import CircuitVisualizer
5
+ import numpy as np
6
+ import uuid
7
+
8
+ class QuantumCryptApp:
9
+ """Interface gráfica para o QuantumCrypt usando Gradio."""
10
+
11
+ def __init__(self):
12
+ self.bb84 = BB84Protocol()
13
+ self.e91 = E91Protocol()
14
+
15
+ def create_interface(self):
16
+ """Cria a interface Gradio."""
17
+
18
+ with gr.Blocks(title="QuantumCrypt", css="footer{display:none !important}") as interface:
19
+ gr.Markdown("# QuantumCrypt")
20
+
21
+ with gr.Tabs():
22
+ with gr.Tab("BB84"):
23
+ with gr.Row():
24
+ with gr.Column():
25
+ key_length = gr.Slider(
26
+ minimum=8, maximum=256, value=64,
27
+ label="Tamanho da Chave"
28
+ )
29
+ error_correction = gr.Checkbox(
30
+ label="Usar Correção de Erros",
31
+ visible=False
32
+ )
33
+ generate_btn = gr.Button("Gerar Chave BB84")
34
+
35
+ with gr.Column():
36
+
37
+ output_text = gr.TextArea(label="Resultado")
38
+ circuit_viz = gr.Image(label="Visualização do Circuito",
39
+ show_download_button=False,
40
+ show_fullscreen_button=False,
41
+ show_share_button=False)
42
+
43
+
44
+ with gr.Tab("E91"):
45
+ with gr.Row():
46
+ with gr.Column():
47
+ key_length_e91 = gr.Slider(
48
+ minimum=8, maximum=256, value=64,
49
+ label="Tamanho da Chave"
50
+ )
51
+ error_correction_e91 = gr.Checkbox(
52
+ label="Usar Correção de Erros",
53
+ visible=False
54
+ )
55
+ generate_btn_e91 = gr.Button("Gerar Chave BB84")
56
+
57
+ with gr.Column():
58
+
59
+ output_text_e91 = gr.TextArea(label="Resultado")
60
+ circuit_viz_e91 = gr.Image(label="Visualização do Circuito",
61
+ show_download_button=False,
62
+ show_fullscreen_button=False,
63
+ show_share_button=False)
64
+
65
+ with gr.Accordion(label="About", open=False):
66
+ with open("README.md", "r") as readme_file:
67
+ gr.Markdown(
68
+ readme_file.read()
69
+ )
70
+
71
+ def generate_bb84(length, use_correction):
72
+ filename = f"data/{uuid.uuid4()}.png"
73
+ protocol = BB84Protocol(
74
+ key_length=length,
75
+ error_correction=use_correction
76
+ )
77
+ result = protocol.generate_key()
78
+
79
+ # Gerar visualização
80
+ circuit_img = CircuitVisualizer.draw_circuit(
81
+ protocol.current_circuit,
82
+ filename=filename
83
+ )
84
+
85
+ # Formatar resultado
86
+ output = (
87
+ f"Chave Alice: {''.join(map(str, result['alice']))}\n"
88
+ f"Chave Bob: {''.join(map(str, result['bob']))}\n"
89
+ f"Tamanho: {len(result['alice'])} bits\n"
90
+ f"Correção de Erros: {'Ativada' if use_correction else 'Desativada'}"
91
+ )
92
+
93
+ return output, filename
94
+
95
+ def generate_e91(length):
96
+ filename = f"data/{uuid.uuid4()}.png"
97
+ protocol = E91Protocol(
98
+ key_length=length
99
+ )
100
+ result = protocol.generate_key()
101
+
102
+ # Gerar visualização
103
+ circuit_img = CircuitVisualizer.draw_circuit(
104
+ protocol.current_circuit,
105
+ filename=filename
106
+ )
107
+
108
+ # Formatar resultado
109
+ output = (
110
+ f"Chave Alice: {''.join(map(str, result['alice']))}\n"
111
+ f"Chave Bob: {''.join(map(str, result['bob']))}\n"
112
+ f"Tamanho: {len(result['alice'])} bits\n"
113
+ )
114
+
115
+ return output, filename
116
+
117
+ generate_btn_e91.click(
118
+ generate_e91,
119
+ inputs=[key_length_e91],
120
+ outputs=[output_text_e91, circuit_viz_e91]
121
+ )
122
+
123
+ generate_btn.click(
124
+ generate_bb84,
125
+ inputs=[key_length, error_correction],
126
+ outputs=[output_text, circuit_viz]
127
+ )
128
+
129
+ return interface
130
+
131
+ # Exemplo de uso
132
+ if __name__ == "__main__":
133
+ app = QuantumCryptApp()
134
+ interface = app.create_interface()
135
+ interface.launch()
data/03bd51fa-e441-47dd-bd2e-ecc9fde0da3d.png ADDED
data/2f47bf75-5546-44ee-815a-f408612230f4.png ADDED
data/3a8ba655-50ed-4ddc-93ca-2eabee5a36b5.png ADDED
data/3ed20c5a-74a1-4b16-bc33-ab745360536a.png ADDED
requirements.txt ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ annotated-types==0.7.0
3
+ anyio==4.8.0
4
+ certifi==2025.1.31
5
+ charset-normalizer==3.4.1
6
+ click==8.1.8
7
+ contourpy==1.3.1
8
+ cycler==0.12.1
9
+ dill==0.3.9
10
+ exceptiongroup==1.2.2
11
+ fastapi==0.115.8
12
+ ffmpy==0.5.0
13
+ filelock==3.17.0
14
+ fonttools==4.56.0
15
+ fsspec==2025.2.0
16
+ gradio==5.17.1
17
+ gradio_client==1.7.1
18
+ h11==0.14.0
19
+ httpcore==1.0.7
20
+ httpx==0.28.1
21
+ huggingface-hub==0.29.1
22
+ idna==3.10
23
+ Jinja2==3.1.5
24
+ kiwisolver==1.4.8
25
+ markdown-it-py==3.0.0
26
+ MarkupSafe==2.1.5
27
+ matplotlib==3.10.0
28
+ mdurl==0.1.2
29
+ mpmath==1.3.0
30
+ numpy==2.2.3
31
+ orjson==3.10.15
32
+ packaging==24.2
33
+ pandas==2.2.3
34
+ pbr==6.1.1
35
+ pillow==11.1.0
36
+ psutil==7.0.0
37
+ pydantic==2.10.6
38
+ pydantic_core==2.27.2
39
+ pydub==0.25.1
40
+ Pygments==2.19.1
41
+ pylatexenc==2.10
42
+ pyparsing==3.2.1
43
+ python-dateutil==2.9.0.post0
44
+ python-multipart==0.0.20
45
+ pytz==2025.1
46
+ PyYAML==6.0.2
47
+ qiskit==1.4.0
48
+ qiskit-aer==0.16.1
49
+ requests==2.32.3
50
+ rich==13.9.4
51
+ ruff==0.9.7
52
+ rustworkx==0.16.0
53
+ safehttpx==0.1.6
54
+ scipy==1.15.2
55
+ semantic-version==2.10.0
56
+ shellingham==1.5.4
57
+ six==1.17.0
58
+ sniffio==1.3.1
59
+ starlette==0.45.3
60
+ stevedore==5.4.1
61
+ symengine==0.13.0
62
+ sympy==1.13.3
63
+ tomlkit==0.13.2
64
+ tqdm==4.67.1
65
+ typer==0.15.1
66
+ typing_extensions==4.12.2
67
+ tzdata==2025.1
68
+ urllib3==2.3.0
69
+ uvicorn==0.34.0
70
+ websockets==14.2
src/__pycache__/base.cpython-310.pyc ADDED
Binary file (1.24 kB). View file
 
src/__pycache__/bb84.cpython-310.pyc ADDED
Binary file (10.4 kB). View file
 
src/__pycache__/circuit_viz.cpython-310.pyc ADDED
Binary file (900 Bytes). View file
 
src/__pycache__/e91.cpython-310.pyc ADDED
Binary file (5.39 kB). View file
 
src/base.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+ from typing import Dict, List, Tuple, Optional
3
+ import logging
4
+
5
+ class QuantumProtocol(ABC):
6
+ """Classe base abstrata para protocolos de criptografia quântica."""
7
+
8
+ def __init__(self, key_length: int = 128):
9
+ self.key_length = key_length
10
+ self.logger = logging.getLogger(self.__class__.__name__)
11
+
12
+ @abstractmethod
13
+ def generate_key(self) -> Dict[str, List[int]]:
14
+ """Gera uma chave usando o protocolo específico."""
15
+ pass
16
+
17
+ @abstractmethod
18
+ def get_circuit_visualization(self) -> str:
19
+ """Retorna a visualização do circuito quântico."""
20
+ pass
src/bb84.py ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
2
+ from qiskit.visualization import circuit_drawer
3
+ from qiskit_aer import Aer
4
+ import numpy as np
5
+ import random
6
+ from typing import Dict, List, Tuple, Optional
7
+ import logging
8
+ from .base import QuantumProtocol
9
+
10
+ class BB84Protocol(QuantumProtocol):
11
+ """
12
+ Implementação do protocolo BB84 para distribuição quântica de chaves.
13
+ Herda da classe base QuantumProtocol e implementa correção de erros quânticos.
14
+ """
15
+
16
+ def __init__(self, key_length: int = 128, error_correction: bool = True):
17
+ """
18
+ Inicializa o protocolo BB84.
19
+
20
+ Args:
21
+ key_length (int): Tamanho desejado da chave final em bits
22
+ error_correction (bool): Se True, utiliza correção de erros quânticos
23
+ """
24
+ super().__init__(key_length) # Chama o construtor da classe base
25
+ self.error_correction = error_correction
26
+ self.simulator = Aer.get_backend('qasm_simulator')
27
+ self.current_circuit = None
28
+
29
+ def _prepare_qubit(self, bit: int, basis: str) -> QuantumCircuit:
30
+ """
31
+ Prepara um único qubit no estado e base especificados.
32
+
33
+ Args:
34
+ bit (int): Bit a ser codificado (0 ou 1)
35
+ basis (str): Base de medição ('Z' para rectilinear ou 'X' para diagonal)
36
+
37
+ Returns:
38
+ QuantumCircuit: Circuito quântico preparado
39
+ """
40
+ if self.error_correction:
41
+ # Circuito com correção de erros (código de repetição de 3 qubits)
42
+ qr = QuantumRegister(3, 'q')
43
+ cr = ClassicalRegister(1, 'c')
44
+ qc = QuantumCircuit(qr, cr)
45
+
46
+ # Prepara o estado base
47
+ if bit == 1:
48
+ qc.x(qr[0])
49
+
50
+ # Aplica o código de repetição
51
+ qc.cx(qr[0], qr[1]) # CNOT para copiar o estado
52
+ qc.cx(qr[0], qr[2])
53
+
54
+ # Aplica a transformação de base se necessário
55
+ if basis == 'X':
56
+ qc.h(qr) # Aplica H em todos os qubits
57
+ else:
58
+ # Circuito simples sem correção
59
+ qr = QuantumRegister(1, 'q')
60
+ cr = ClassicalRegister(1, 'c')
61
+ qc = QuantumCircuit(qr, cr)
62
+
63
+ # Prepara o estado
64
+ if bit == 1:
65
+ qc.x(qr[0])
66
+ if basis == 'X':
67
+ qc.h(qr[0])
68
+
69
+ self.current_circuit = qc
70
+ return qc
71
+
72
+ def _measure_qubit(self, circuit: QuantumCircuit, basis: str) -> QuantumCircuit:
73
+ """
74
+ Adiciona medição em uma base específica ao circuito.
75
+
76
+ Args:
77
+ circuit (QuantumCircuit): Circuito a ser medido
78
+ basis (str): Base de medição ('Z' ou 'X')
79
+
80
+ Returns:
81
+ QuantumCircuit: Circuito com medição adicionada
82
+ """
83
+ if self.error_correction:
84
+ # Medição com correção de erros
85
+ if basis == 'X':
86
+ circuit.h(range(3)) # Aplica H em todos os qubits para base X
87
+
88
+ # Medição em todos os qubits
89
+ circuit.measure_all()
90
+
91
+ else:
92
+ # Medição simples
93
+ if basis == 'X':
94
+ circuit.h(0)
95
+ circuit.measure([0], [0])
96
+
97
+ return circuit
98
+
99
+ def _error_correction_decode(self, measurements: List[int]) -> int:
100
+ """
101
+ Decodifica medições usando voto majoritário para correção de erros.
102
+
103
+ Args:
104
+ measurements (List[int]): Lista de medições dos qubits
105
+
106
+ Returns:
107
+ int: Bit decodificado
108
+ """
109
+ return 1 if sum(measurements) > len(measurements)/2 else 0
110
+
111
+ def generate_random_bits(self, n: int) -> List[int]:
112
+ """
113
+ Gera uma lista de bits aleatórios.
114
+
115
+ Args:
116
+ n (int): Número de bits a serem gerados
117
+
118
+ Returns:
119
+ List[int]: Lista de bits aleatórios
120
+ """
121
+ return [random.randint(0, 1) for _ in range(n)]
122
+
123
+ def generate_random_bases(self, n: int) -> List[str]:
124
+ """
125
+ Gera uma lista de bases aleatórias.
126
+
127
+ Args:
128
+ n (int): Número de bases a serem geradas
129
+
130
+ Returns:
131
+ List[str]: Lista de bases aleatórias ('Z' ou 'X')
132
+ """
133
+ return [random.choice(['Z', 'X']) for _ in range(n)]
134
+
135
+ def simulate_transmission(self, bits: List[int], bases: List[str]) -> Tuple[List[int], List[str]]:
136
+ """
137
+ Simula a transmissão dos qubits de Alice para Bob.
138
+
139
+ Args:
140
+ bits (List[int]): Bits a serem transmitidos
141
+ bases (List[str]): Bases usadas para codificação
142
+
143
+ Returns:
144
+ Tuple[List[int], List[str]]: Medições de Bob e bases escolhidas
145
+ """
146
+ bob_bases = self.generate_random_bases(len(bits))
147
+ bob_measurements = []
148
+
149
+ for i in range(len(bits)):
150
+ # Alice prepara o qubit
151
+ circuit = self._prepare_qubit(bits[i], bases[i])
152
+
153
+ # Bob mede o qubit
154
+ circuit = self._measure_qubit(circuit, bob_bases[i])
155
+
156
+ # Executa a simulação
157
+ job = self.simulator.run(circuit, shots=1)
158
+ result = job.result()
159
+ counts = list(result.get_counts().keys())[0]
160
+
161
+ if self.error_correction:
162
+ # Decodifica as medições com correção de erros
163
+ measurements = [int(bit) for bit in counts]
164
+ measured_bit = self._error_correction_decode(measurements)
165
+ else:
166
+ measured_bit = int(counts)
167
+
168
+ bob_measurements.append(measured_bit)
169
+
170
+ return bob_measurements, bob_bases
171
+
172
+ def sift_key(self, alice_bits: List[int], alice_bases: List[str],
173
+ bob_measurements: List[int], bob_bases: List[str]) -> Tuple[List[int], List[int]]:
174
+ """
175
+ Realiza o processo de peneiramento da chave.
176
+
177
+ Args:
178
+ alice_bits (List[int]): Bits originais de Alice
179
+ alice_bases (List[str]): Bases usadas por Alice
180
+ bob_measurements (List[int]): Medições de Bob
181
+ bob_bases (List[str]): Bases usadas por Bob
182
+
183
+ Returns:
184
+ Tuple[List[int], List[int]]: Chaves peneiradas de Alice e Bob
185
+ """
186
+ alice_key = []
187
+ bob_key = []
188
+
189
+ for i in range(len(alice_bits)):
190
+ if alice_bases[i] == bob_bases[i]:
191
+ alice_key.append(alice_bits[i])
192
+ bob_key.append(bob_measurements[i])
193
+
194
+ return alice_key, bob_key
195
+
196
+ def check_eavesdropping(self, alice_key: List[int], bob_key: List[int],
197
+ sample_size: float = 0.25) -> bool:
198
+ """
199
+ Verifica a presença de um espião comparando uma amostra das chaves.
200
+
201
+ Args:
202
+ alice_key (List[int]): Chave de Alice
203
+ bob_key (List[int]): Chave de Bob
204
+ sample_size (float): Proporção da chave a ser verificada
205
+
206
+ Returns:
207
+ bool: True se não houver evidência de espionagem, False caso contrário
208
+ """
209
+ if len(alice_key) != len(bob_key):
210
+ return False
211
+
212
+ sample_length = int(len(alice_key) * sample_size)
213
+ indices = random.sample(range(len(alice_key)), sample_length)
214
+
215
+ differences = 0
216
+ for i in indices:
217
+ if alice_key[i] != bob_key[i]:
218
+ differences += 1
219
+
220
+ error_rate = differences / sample_length
221
+ self.logger.info(f"Taxa de erro na amostra: {error_rate:.2%}")
222
+
223
+ # Define um limite aceitável de erro (5%)
224
+ return error_rate < 0.05
225
+
226
+ def get_circuit_visualization(self) -> str:
227
+ """
228
+ Implementação do método abstrato da classe base.
229
+ Retorna a visualização do circuito atual em ASCII.
230
+
231
+ Returns:
232
+ str: Representação ASCII do circuito
233
+ """
234
+ if self.current_circuit:
235
+ return circuit_drawer(self.current_circuit, output='text')
236
+ return "Nenhum circuito disponível"
237
+
238
+ def generate_key(self) -> Dict[str, List[int]]:
239
+ """
240
+ Implementação do método abstrato da classe base.
241
+ Executa o protocolo BB84 completo para gerar uma chave compartilhada.
242
+
243
+ Returns:
244
+ Dict[str, List[int]]: Dicionário contendo as chaves finais de Alice e Bob
245
+ """
246
+ # Fase 1: Preparação
247
+ raw_bits = self.generate_random_bits(self.key_length * 4)
248
+ alice_bases = self.generate_random_bases(len(raw_bits))
249
+
250
+ self.logger.info(f"Iniciando protocolo BB84 para gerar chave de {self.key_length} bits")
251
+ self.logger.info(f"Correção de erros: {'Ativada' if self.error_correction else 'Desativada'}")
252
+
253
+ # Fase 2: Transmissão
254
+ bob_measurements, bob_bases = self.simulate_transmission(raw_bits, alice_bases)
255
+
256
+ # Fase 3: Peneiramento
257
+ alice_key, bob_key = self.sift_key(raw_bits, alice_bases, bob_measurements, bob_bases)
258
+
259
+ self.logger.info(f"Chave peneirada gerada com {len(alice_key)} bits")
260
+
261
+ # Fase 4: Detecção de espionagem
262
+ if not self.check_eavesdropping(alice_key, bob_key):
263
+ self.logger.error("Possível tentativa de espionagem detectada!")
264
+ return {"alice": [], "bob": []}
265
+
266
+ # Fase 5: Finalização
267
+ final_key_length = min(self.key_length, len(alice_key))
268
+ alice_final_key = alice_key[:final_key_length]
269
+ bob_final_key = bob_key[:final_key_length]
270
+
271
+ self.logger.info(f"Protocolo BB84 concluído com sucesso. "
272
+ f"Chave final de {final_key_length} bits gerada.")
273
+
274
+ return {
275
+ "alice": alice_final_key,
276
+ "bob": bob_final_key
277
+ }
278
+
279
+ def get_key_statistics(self, alice_key: List[int], bob_key: List[int]) -> Dict:
280
+ """
281
+ Calcula estatísticas sobre as chaves geradas.
282
+
283
+ Args:
284
+ alice_key (List[int]): Chave de Alice
285
+ bob_key (List[int]): Chave de Bob
286
+
287
+ Returns:
288
+ Dict: Dicionário com estatísticas das chaves
289
+ """
290
+ if not alice_key or not bob_key:
291
+ return {
292
+ "key_length": 0,
293
+ "error_rate": 1.0,
294
+ "matching_rate": 0.0,
295
+ "entropy": 0.0
296
+ }
297
+
298
+ differences = sum(a != b for a, b in zip(alice_key, bob_key))
299
+ error_rate = differences / len(alice_key)
300
+
301
+ # Calcula a entropia da chave
302
+ ones = sum(alice_key) / len(alice_key)
303
+ zeros = 1 - ones
304
+ if zeros == 0 or ones == 0:
305
+ entropy = 0
306
+ else:
307
+ entropy = -(ones * np.log2(ones) + zeros * np.log2(zeros))
308
+
309
+ return {
310
+ "key_length": len(alice_key),
311
+ "error_rate": error_rate,
312
+ "matching_rate": 1 - error_rate,
313
+ "entropy": entropy
314
+ }
315
+
316
+ def main():
317
+ """Função principal para demonstração do protocolo."""
318
+ # Criar uma instância do protocolo
319
+ bb84 = BB84Protocol(key_length=64, error_correction=True)
320
+
321
+ # Gerar uma chave compartilhada
322
+ result = bb84.generate_key()
323
+
324
+ # Verificar se as chaves são idênticas
325
+ if result["alice"] and result["bob"]:
326
+ print("\nChave de Alice:", "".join(map(str, result["alice"])))
327
+ print("Chave de Bob: ", "".join(map(str, result["bob"])))
328
+
329
+ # Obter e mostrar estatísticas
330
+ stats = bb84.get_key_statistics(result["alice"], result["bob"])
331
+ print("\nEstatísticas da chave:")
332
+ print(f"Tamanho: {stats['key_length']} bits")
333
+ print(f"Taxa de erro: {stats['error_rate']:.2%}")
334
+ print(f"Taxa de correspondência: {stats['matching_rate']:.2%}")
335
+ print(f"Entropia: {stats['entropy']:.2f} bits")
336
+
337
+ # Mostrar visualização do último circuito
338
+ print("\nÚltimo circuito gerado:")
339
+ print(bb84.get_circuit_visualization())
340
+ else:
341
+ print("Falha na geração da chave - possível tentativa de espionagem detectada.")
src/circuit_viz.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from qiskit.visualization import circuit_drawer
2
+ from typing import Optional
3
+ import matplotlib.pyplot as plt
4
+
5
+ class CircuitVisualizer:
6
+ """Classe para visualização de circuitos quânticos."""
7
+
8
+ @staticmethod
9
+ def draw_circuit(circuit, filename: Optional[str] = None):
10
+ """Desenha e opcionalmente salva o circuito."""
11
+ fig = plt.figure(figsize=(12, 8))
12
+ circuit_drawer(circuit, output='mpl')
13
+ if filename:
14
+ plt.savefig(filename)
15
+ plt.close()
src/e91.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .base import QuantumProtocol
2
+ from qiskit_aer import Aer
3
+ from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
4
+ import numpy as np
5
+ import random
6
+ from typing import Dict, List, Tuple
7
+ from qiskit.visualization import circuit_drawer
8
+
9
+
10
+
11
+ class E91Protocol(QuantumProtocol):
12
+ """
13
+ Implementação do protocolo E91 (Ekert91) baseado em emaranhamento.
14
+
15
+ O protocolo E91 usa pares de qubits emaranhados e medições em diferentes ângulos
16
+ para estabelecer uma chave segura e verificar a presença de espionagem através
17
+ da violação das desigualdades de Bell.
18
+ """
19
+
20
+ def __init__(self, key_length: int = 128):
21
+ super().__init__(key_length)
22
+ self.simulator = Aer.get_backend('qasm_simulator')
23
+ self.current_circuit = None
24
+
25
+ # Ângulos de medição para Alice e Bob
26
+ self.alice_angles = [0, np.pi/4, np.pi/2]
27
+ self.bob_angles = [np.pi/4, np.pi/2, 3*np.pi/4]
28
+
29
+ def _prepare_entangled_pair(self) -> QuantumCircuit:
30
+ """
31
+ Prepara um par de qubits emaranhados no estado de Bell Φ+.
32
+
33
+ Returns:
34
+ QuantumCircuit: Circuito com o par emaranhado
35
+ """
36
+ qr = QuantumRegister(2, 'q')
37
+ cr = ClassicalRegister(2, 'c')
38
+ qc = QuantumCircuit(qr, cr)
39
+
40
+ # Criar estado de Bell Φ+ = (|00⟩ + |11⟩)/√2
41
+ qc.h(qr[0])
42
+ qc.cx(qr[0], qr[1])
43
+
44
+ self.current_circuit = qc
45
+ return qc
46
+
47
+ def _measure_qubit(self, circuit: QuantumCircuit, angle: float, qubit: int) -> QuantumCircuit:
48
+ """
49
+ Adiciona medição em um ângulo específico para um qubit.
50
+
51
+ Args:
52
+ circuit (QuantumCircuit): Circuito a ser medido
53
+ angle (float): Ângulo de medição
54
+ qubit (int): Índice do qubit a ser medido
55
+
56
+ Returns:
57
+ QuantumCircuit: Circuito com medição adicionada
58
+ """
59
+ # Rotação para o ângulo de medição
60
+ circuit.ry(2*angle, qubit)
61
+ circuit.measure([qubit], [qubit])
62
+ return circuit
63
+
64
+ def _check_bell_inequality(self, correlations: List[float]) -> bool:
65
+ """
66
+ Verifica a violação da desigualdade de CHSH.
67
+
68
+ Args:
69
+ correlations (List[float]): Lista de correlações medidas
70
+
71
+ Returns:
72
+ bool: True se a desigualdade for violada (indicando ausência de espião)
73
+ """
74
+ # Cálculo do parâmetro S da desigualdade CHSH
75
+ S = abs(sum(correlations))
76
+ # O valor teórico máximo é 2√2 ≈ 2.82
77
+ # Um valor > 2 indica violação da desigualdade
78
+ return S > 2
79
+
80
+ def _calculate_correlation(self, alice_results: List[int],
81
+ bob_results: List[int]) -> float:
82
+ """
83
+ Calcula a correlação entre as medições de Alice e Bob.
84
+
85
+ Args:
86
+ alice_results (List[int]): Resultados das medições de Alice
87
+ bob_results (List[int]): Resultados das medições de Bob
88
+
89
+ Returns:
90
+ float: Valor da correlação (-1 a 1)
91
+ """
92
+ if not alice_results or not bob_results:
93
+ return 0
94
+
95
+ return np.mean([a == b for a, b in zip(alice_results, bob_results)])
96
+
97
+ def generate_key(self) -> Dict[str, List[int]]:
98
+ """
99
+ Executa o protocolo E91 completo para gerar uma chave compartilhada.
100
+
101
+ Returns:
102
+ Dict[str, List[int]]: Dicionário contendo as chaves finais de Alice e Bob
103
+ """
104
+ self.logger.info(f"Iniciando protocolo E91 para gerar chave de {self.key_length} bits")
105
+
106
+ alice_key = []
107
+ bob_key = []
108
+ correlations = []
109
+
110
+ # Precisamos de mais pares para compensar descartes
111
+ num_pairs = self.key_length * 4
112
+
113
+ for _ in range(num_pairs):
114
+ # Preparar par emaranhado
115
+ circuit = self._prepare_entangled_pair()
116
+
117
+ # Alice e Bob escolhem ângulos aleatoriamente
118
+ alice_angle = random.choice(self.alice_angles)
119
+ bob_angle = random.choice(self.bob_angles)
120
+
121
+ # Adicionar medições
122
+ circuit = self._measure_qubit(circuit, alice_angle, 0) # Alice
123
+ circuit = self._measure_qubit(circuit, bob_angle, 1) # Bob
124
+
125
+ # Executar circuito
126
+ job = self.simulator.run(circuit, shots=1)
127
+ result = job.result()
128
+ counts = list(result.get_counts().keys())[0]
129
+ alice_result = int(counts[0])
130
+ bob_result = int(counts[1])
131
+
132
+ # Verificar se os ângulos são compatíveis para a chave
133
+ if alice_angle == bob_angle:
134
+ alice_key.append(alice_result)
135
+ bob_key.append(bob_result)
136
+ else:
137
+ # Usar para teste de Bell
138
+ correlation = self._calculate_correlation([alice_result], [bob_result])
139
+ correlations.append(correlation)
140
+
141
+ # Verificar violação da desigualdade de Bell
142
+ if not self._check_bell_inequality(correlations):
143
+ self.logger.error("Possível espionagem detectada - violação de Bell não observada!")
144
+ return {"alice": [], "bob": []}
145
+
146
+ # Cortar para o tamanho desejado
147
+ alice_key = alice_key[:self.key_length]
148
+ bob_key = bob_key[:self.key_length]
149
+
150
+ self.logger.info(f"Protocolo E91 concluído com sucesso. "
151
+ f"Chave final de {len(alice_key)} bits gerada.")
152
+
153
+ return {
154
+ "alice": alice_key,
155
+ "bob": bob_key
156
+ }
157
+
158
+ def get_circuit_visualization(self) -> str:
159
+ """
160
+ Retorna a visualização do circuito atual em ASCII.
161
+
162
+ Returns:
163
+ str: Representação ASCII do circuito
164
+ """
165
+ if self.current_circuit:
166
+ return circuit_drawer(self.current_circuit, output='text')
167
+ return "Nenhum circuito disponível"
src/generate.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
2
+ from qiskit_aer import Aer
3
+ from qiskit.visualization import plot_histogram
4
+ import numpy as np
5
+ import random
6
+ from typing import List, Tuple, Dict
7
+ import logging
8
+
9
+ class BB84Protocol:
10
+ def __init__(self, key_length: int = 128):
11
+ """
12
+ Inicializa o protocolo BB84 com o tamanho desejado da chave.
13
+
14
+ Args:
15
+ key_length (int): Tamanho desejado da chave final em bits
16
+ """
17
+ self.key_length = key_length
18
+ self.simulator = Aer.get_backend('qasm_simulator')
19
+
20
+ # Configuração do logging
21
+ logging.basicConfig(level=logging.INFO)
22
+ self.logger = logging.getLogger(__name__)
23
+
24
+ def _prepare_qubit(self, bit: int, basis: str) -> QuantumCircuit:
25
+ """
26
+ Prepara um único qubit no estado e base especificados.
27
+
28
+ Args:
29
+ bit (int): Bit a ser codificado (0 ou 1)
30
+ basis (str): Base de medição ('Z' para rectilinear ou 'X' para diagonal)
31
+
32
+ Returns:
33
+ QuantumCircuit: Circuito quântico preparado
34
+ """
35
+ qr = QuantumRegister(1)
36
+ cr = ClassicalRegister(1)
37
+ qc = QuantumCircuit(qr, cr)
38
+
39
+ # Prepara o estado do qubit
40
+ if bit == 1:
41
+ qc.x(qr[0])
42
+
43
+ # Aplica a transformação de base se necessário
44
+ if basis == 'X':
45
+ qc.h(qr[0])
46
+
47
+ return qc
48
+
49
+ def _measure_qubit(self, circuit: QuantumCircuit, basis: str) -> QuantumCircuit:
50
+ """
51
+ Adiciona a medição em uma base específica ao circuito.
52
+
53
+ Args:
54
+ circuit (QuantumCircuit): Circuito a ser medido
55
+ basis (str): Base de medição ('Z' ou 'X')
56
+
57
+ Returns:
58
+ QuantumCircuit: Circuito com medição adicionada
59
+ """
60
+ if basis == 'X':
61
+ circuit.h(0)
62
+ circuit.measure([0], [0])
63
+ return circuit
64
+
65
+ def generate_random_bits(self, n: int) -> List[int]:
66
+ """
67
+ Gera uma lista de bits aleatórios.
68
+
69
+ Args:
70
+ n (int): Número de bits a serem gerados
71
+
72
+ Returns:
73
+ List[int]: Lista de bits aleatórios
74
+ """
75
+ return [random.randint(0, 1) for _ in range(n)]
76
+
77
+ def generate_random_bases(self, n: int) -> List[str]:
78
+ """
79
+ Gera uma lista de bases aleatórias.
80
+
81
+ Args:
82
+ n (int): Número de bases a serem geradas
83
+
84
+ Returns:
85
+ List[str]: Lista de bases aleatórias ('Z' ou 'X')
86
+ """
87
+ return [random.choice(['Z', 'X']) for _ in range(n)]
88
+
89
+ def simulate_transmission(self, bits: List[int], bases: List[str]) -> Tuple[List[int], List[str]]:
90
+ """
91
+ Simula a transmissão dos qubits de Alice para Bob.
92
+
93
+ Args:
94
+ bits (List[int]): Bits a serem transmitidos
95
+ bases (List[str]): Bases usadas para codificação
96
+
97
+ Returns:
98
+ Tuple[List[int], List[str]]: Medições de Bob e bases escolhidas
99
+ """
100
+ bob_bases = self.generate_random_bases(len(bits))
101
+ bob_measurements = []
102
+
103
+ for i in range(len(bits)):
104
+ # Alice prepara o qubit
105
+ circuit = self._prepare_qubit(bits[i], bases[i])
106
+
107
+ # Bob mede o qubit
108
+ circuit = self._measure_qubit(circuit, bob_bases[i])
109
+
110
+ # Executa a simulação usando a nova API do Qiskit
111
+ job = self.simulator.run(circuit, shots=1)
112
+ result = job.result()
113
+ counts = result.get_counts()
114
+ measured_bit = int(list(counts.keys())[0])
115
+ bob_measurements.append(measured_bit)
116
+
117
+ return bob_measurements, bob_bases
118
+
119
+ def sift_key(self, alice_bits: List[int], alice_bases: List[str],
120
+ bob_measurements: List[int], bob_bases: List[str]) -> Tuple[List[int], List[int]]:
121
+ """
122
+ Realiza o processo de peneiramento da chave.
123
+
124
+ Args:
125
+ alice_bits (List[int]): Bits originais de Alice
126
+ alice_bases (List[str]): Bases usadas por Alice
127
+ bob_measurements (List[int]): Medições de Bob
128
+ bob_bases (List[str]): Bases usadas por Bob
129
+
130
+ Returns:
131
+ Tuple[List[int], List[int]]: Chaves peneiradas de Alice e Bob
132
+ """
133
+ alice_key = []
134
+ bob_key = []
135
+
136
+ for i in range(len(alice_bits)):
137
+ if alice_bases[i] == bob_bases[i]:
138
+ alice_key.append(alice_bits[i])
139
+ bob_key.append(bob_measurements[i])
140
+
141
+ return alice_key, bob_key
142
+
143
+ def check_eavesdropping(self, alice_key: List[int], bob_key: List[int],
144
+ sample_size: float = 0.25) -> bool:
145
+ """
146
+ Verifica a presença de um espião comparando uma amostra das chaves.
147
+
148
+ Args:
149
+ alice_key (List[int]): Chave de Alice
150
+ bob_key (List[int]): Chave de Bob
151
+ sample_size (float): Proporção da chave a ser verificada
152
+
153
+ Returns:
154
+ bool: True se não houver evidência de espionagem, False caso contrário
155
+ """
156
+ if len(alice_key) != len(bob_key):
157
+ return False
158
+
159
+ sample_length = int(len(alice_key) * sample_size)
160
+ indices = random.sample(range(len(alice_key)), sample_length)
161
+
162
+ differences = 0
163
+ for i in indices:
164
+ if alice_key[i] != bob_key[i]:
165
+ differences += 1
166
+
167
+ error_rate = differences / sample_length
168
+ self.logger.info(f"Taxa de erro na amostra: {error_rate:.2%}")
169
+
170
+ # Define um limite aceitável de erro (por exemplo, 5%)
171
+ return error_rate < 0.05
172
+
173
+ def generate_key(self) -> Dict[str, List[int]]:
174
+ """
175
+ Executa o protocolo BB84 completo para gerar uma chave compartilhada.
176
+
177
+ Returns:
178
+ Dict[str, List[int]]: Dicionário contendo as chaves finais de Alice e Bob
179
+ """
180
+ # Fase 1: Preparação
181
+ raw_bits = self.generate_random_bits(self.key_length * 4) # Geramos mais bits para compensar o peneiramento
182
+ alice_bases = self.generate_random_bases(len(raw_bits))
183
+
184
+ self.logger.info(f"Iniciando protocolo BB84 para gerar chave de {self.key_length} bits")
185
+
186
+ # Fase 2: Transmissão
187
+ bob_measurements, bob_bases = self.simulate_transmission(raw_bits, alice_bases)
188
+
189
+ # Fase 3: Peneiramento
190
+ alice_key, bob_key = self.sift_key(raw_bits, alice_bases, bob_measurements, bob_bases)
191
+
192
+ self.logger.info(f"Chave peneirada gerada com {len(alice_key)} bits")
193
+
194
+ # Fase 4: Detecção de espionagem
195
+ if not self.check_eavesdropping(alice_key, bob_key):
196
+ self.logger.error("Possível tentativa de espionagem detectada!")
197
+ return {"alice": [], "bob": []}
198
+
199
+ # Fase 5: Finalização
200
+ final_key_length = min(self.key_length, len(alice_key))
201
+ alice_final_key = alice_key[:final_key_length]
202
+ bob_final_key = bob_key[:final_key_length]
203
+
204
+ self.logger.info(f"Protocolo BB84 concluído com sucesso. Chave final de {final_key_length} bits gerada.")
205
+
206
+ return {
207
+ "alice": alice_final_key,
208
+ "bob": bob_final_key
209
+ }
210
+
211
+ # Exemplo de uso
212
+ if __name__ == "__main__":
213
+ # Criar uma instância do protocolo
214
+ bb84 = BB84Protocol(key_length=64)
215
+
216
+ # Gerar uma chave compartilhada
217
+ result = bb84.generate_key()
218
+
219
+ # Verificar se as chaves são idênticas
220
+ if result["alice"] and result["bob"]:
221
+ print("\nChave de Alice:", "".join(map(str, result["alice"])))
222
+ print("Chave de Bob: ", "".join(map(str, result["bob"])))
223
+ print("\nAs chaves são idênticas?", result["alice"] == result["bob"])
224
+ print("Tamanho da chave:", len(result["alice"]), "bits")
225
+ else:
226
+ print("Falha na geração da chave - possível tentativa de espionagem detectada.")
src/qec.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List
2
+
3
+ class QuantumErrorCorrection:
4
+ """Implementação de correção de erros quânticos."""
5
+
6
+ @staticmethod
7
+ def encode_message(bits: List[int]) -> List[int]:
8
+ """Codifica uma mensagem usando código de repetição."""
9
+ encoded = []
10
+ for bit in bits:
11
+ # Implementa código de repetição de 3 qubits
12
+ encoded.extend([bit] * 3)
13
+ return encoded
14
+
15
+ @staticmethod
16
+ def decode_message(encoded_bits: List[int]) -> List[int]:
17
+ """Decodifica uma mensagem usando voto majoritário."""
18
+ decoded = []
19
+ for i in range(0, len(encoded_bits), 3):
20
+ chunk = encoded_bits[i:i+3]
21
+ # Voto majoritário
22
+ bit = 1 if sum(chunk) > len(chunk)/2 else 0
23
+ decoded.append(bit)
24
+ return decoded