
Solucionador cuántico para el Problema del Logaritmo Discreto en Curva Elíptica utilizando el algoritmo de Shor, implementando múltiples estrategias de oráculo para recuperar claves privadas ECC en hardware cuántico real.
Solucionador cuántico para el Problema del Logaritmo Discreto de Curva Elíptica (ECDLP), construido para el Q-Day Prize Challenge por Project Eleven. El objetivo: recuperar claves privadas ECC en hardware cuántico real usando el algoritmo de Shor.
Todas las curvas del desafío usan y^2 = x^3 + 7 sobre F_p (a = 0, b = 7), coincidiendo con la familia secp256k1. El solucionador implementa la variante de dos registros del algoritmo de Shor para ECDLP:
La clave privada d se recupera recolectando múltiples muestras (j, k) que satisfacen la misma relación lineal módulo el orden del grupo n. El solucionador admite seis estrategias de oráculo para las sumas de puntos controladas, seleccionadas automáticamente según el tamaño de la curva o manualmente mediante --oracle.
Usada para curvas con orden de grupo hasta ~6 bits. Implementada en projecteleven.py.
Cada suma de puntos controlada "añadir S" se representa como una matriz de permutación de 2^(n+1) x 2^(n+1) aplicada mediante qc.unitary(). La matriz codifica la acción completa del grupo: el bloque superior izquierdo es identidad (control=0), el bloque inferior derecho permuta los estados base según el mapa P -> P+S (control=1).
Usada para curvas más grandes. Implementada en quantum_arithmetic.py.
En lugar de construir matrices densas, cada permutación "añadir S" se descompone en ciclos como transposiciones. Cada transposición (intercambio de dos estados base |a> <-> |b>) se implementa con:
La MCX usa descomposición en cadena-V con (n-2) qubits ancilla dedicados, dando O(n) puertas Toffoli por MCX en lugar de O(n^2) sin ancillas. Cada suma controlada se construye como un subcircuito aislado y se añade como una única puerta opaca, evitando el crecimiento cuadrático del DAG en Qiskit.
--oracle coordinate)Disponible para curvas de hasta ~6 bits. Implementada en quantum_oracle.py.
En lugar de codificar puntos como índices de grupo, el registro cuántico contiene las coordenadas (x, y) de elementos de campo en binario más un indicador de identidad. La disposición del registro del punto es:
x_reg: f_bits qubits (f_bits = ceil(log2(p)))y_reg: f_bits qubitsid_flag: 1 qubit (1 = punto en el infinito)Cada suma controlada "añadir S" se calcula a partir de la fórmula de suma de EC sobre todas las codificaciones de coordenadas válidas, produciendo una permutación en el registro de coordenadas. Esta permutación se descompone en ciclos como transposiciones usando la misma infraestructura de reducción CNOT + MCX que la Estrategia 2.
--oracle arithmetic)Marco para suma de puntos con escalado polinómico. Implementada en quantum_oracle.py y quantum_arithmetic.py.
Usa codificación de coordenadas (igual que la Estrategia 3) con primitivas aritméticas modulares basadas en QFT como componentes para la suma de puntos completamente aritmética. El código incluye implementaciones probadas de:
Las primitivas aritméticas logran un escalado O(n^3) por suma de puntos frente a O(N*n) para el enfoque de permutación. Sin embargo, las operaciones basadas en QFT tienen un factor constante ~150 veces mayor, lo que hace que el enfoque aritmético sea más eficiente solo para curvas con orden de grupo superior a ~20 bits. Para los tamaños de desafío actuales (hasta 12 bits), el sumador basado en permutaciones sigue siendo más rápido y se usa por defecto.
--oracle google)Implementada en google_semiclassical.py. Inspirada en la técnica de estimación de fase con reciclaje de qubits de Griffiths & Niu (1996), aplicada a escala en Babbush et al. (2026) para estimaciones de recursos ECDLP en secp256k1. El artículo de Babbush et al. se publicó el 30 de marzo de 2026.
Reemplaza los dos registros de conteo multiqubit (j, k) y el QFT inverso masivo con dos qubits reciclados individuales y correcciones de fase condicionadas clásicamente. Cada bit del registro de conteo se procesa secuencialmente: preparar en |+>, aplicar suma de puntos controlada, corregir fase basándose en todos los bits medidos previamente, luego medir. Las primitivas de circuito dinámico reset e if_test en Qiskit permiten esto en hardware IBM Quantum.
El oráculo para sumas de puntos controladas se delega en la infraestructura existente (unitaria densa para <= 6 bits, permutación eficiente para > 6 bits), por lo que el ahorro de qubits proviene únicamente de eliminar los registros de conteo.
--oracle ripple)Implementada en ripple_carry_shor.py. Usa sumadores con acarreo en cascada CDKM (Cuccaro et al. 2004) para las sumas de puntos controladas, reemplazando tanto las matrices unitarias densas como los circuitos de transposición descompuestos en ciclos.
En la codificación por índice de grupo, el punto P = kG se representa por su índice k en el grupo cíclico. Sumar S = sG se convierte en suma modular de la constante clásica s (mod n). La idea clave: cada suma de puntos controlada se reduce a una única suma modular controlada de una constante conocida, implementada mediante CDKMRippleCarryAdder e IntegerComparator de Qiskit.
El oráculo consiste en 2m sumas modulares controladas (m por registro de conteo), donde cada suma modular controlada realiza:
No se utiliza conocimiento de la clave privada d en la construcción del circuito. Los índices de grupo para las potencias de G se calculan como 2^i mod n (público). Los índices de grupo para las potencias de Q se derivan de la enumeración pública del grupo cíclico generado por G — el punto Q se busca en esta enumeración.
El código incluye componentes modulares basados en QFT (sumadores Beauregard/Draper, multiplicación modular cuántico-cuántico, inversa/negación modular) como base para una codificación de coordenadas completamente aritmética a 256 bits. Estas primitivas se han verificado como correctas mediante simulación Statevector para primos hasta p=13.
Se recuperaron con éxito claves privadas en hardware IBM Quantum para curvas del desafío de hasta 17 bits:
Todas las ejecuciones se realizaron en el plan de instancia abierta de IBM Quantum, que otorga 10 minutos de computación cuántica gratuita al mes. Los registros completos de ejecución se encuentran en la carpeta executions/.
La estrategia de acarreo en cascada (Estrategia 6) permitió un gran salto: de 10 bits (40 qubits, 2M puertas) a 17 bits (69 qubits, 112K puertas) — un aumento de 7 bits en el tamaño de clave con una reducción de 18x en el recuento de puertas de dos qubits. La estructura de puertas de vecino más cercano del sumador CDKM se mapea eficientemente a la topología heavy-hex de IBM, manteniendo la sobrecarga de enrutamiento cerca de 1x.
La estrategia semiclásica (--oracle google) recuperó con éxito claves a 4, 6 y 7 bits usando circuitos dinámicos (reset en medio del circuito, puertas p condicionadas clásicamente mediante if_test) en procesadores IBM Heron r2. A 7 bits, el circuito usa solo 14 qubits (frente a 26 para el enfoque de permutación estándar) mientras produce recuentos de puertas 2Q comparables después de la transpilación.
A 8 bits y superiores, el enfoque semiclásico se vuelve impracticable en el hardware actual de IBM. Aunque if_else y reset son compatibles en Heron r2 (confirmado mediante inspección del backend objetivo), cada punto de realimentación clásica requiere una sincronización completa de la QPU — los 156 qubits físicos deben estar inactivos mientras el controlador clásico procesa la condicional para los ~16 qubits activos. Con ~295K puertas CZ distribuidas en 16+ puntos de realimentación, la sobrecarga de ejecución por disparo hace que los trabajos superen el presupuesto de tiempo de la QPU. El enfoque de permutación estándar, que ejecuta el mismo recuento de puertas en un único lote continuo sin circuitos dinámicos, se completa con éxito a esta escala.
Una truncación aproximada del QFT (parámetro max_corrections) reduce el número de bloques if_else de O(n^2) a O(n) reteniendo solo las correcciones de fase más cercanas k por paso de medición (los ángulos más allá de k contribuyen < pi/2^{k+1}, por debajo del piso de ruido del hardware). Con max_corrections=1, el circuito de 8 bits tiene 16 bloques if_else — aún suficientes para causar tiempo de espera agotado en hardware IBM con este recuento de puertas.
Suponiendo una fidelidad típica de puerta de dos qubits (CX) de ~99.5% en IBM Quantum, la fidelidad estimada del circuito disminuye exponencialmente con el recuento de puertas:
La fidelidad del circuito se calcula como F ≈ (0.995)^{CX_count}. Para todo más allá de 4 bits, la fidelidad estimada es astronómicamente pequeña — la distribución de salida está abrumadoramente dominada por el ruido.
Para 8 bits y superiores, cada disparo produce una cadena de bits casi única (8,128 resultados únicos de 8,192 disparos a 8 bits; los 20,000 únicos a 16 y 17 bits). La salida es indistinguible de un muestreo aleatorio uniforme a nivel de cadena de bits. Sin embargo, el algoritmo aún recupera la clave privada correcta.
La idea clave es que el posprocesamiento de Shor es robusto al ruido de una manera que el análisis de cadenas de bits en bruto no lo es. Cada disparo produce un triple de medición (j, k, r). La extracción calcula d_cand = (r - j) · k^{-1} mod n y verifica mediante d_cand · G == Q. Solo el verdadero d pasa la verificación EC, por lo que incluso un solo candidato correcto entre miles de disparos ruidosos es suficiente.
Un triple (j, k, r) puramente aleatorio produce el d_cand correcto con probabilidad ~1/n. Con S disparos, el número esperado de aciertos verificados solo del ruido es ~S/n. A 17 bits (n=65,173, S=20,000), esto da ~0.3 aciertos de ruido esperados — cualquier recuperación exitosa a esta escala proporciona evidencia de señal cuántica más allá del piso de ruido clásico.
Para las curvas más pequeñas donde disparos >> n (por ejemplo, 10 bits con n=547 y 1,024 disparos), el piso de ruido es ~1,024/547 ≈ 1.9 votos por candidato. Incluso un puñado de disparos portadores de señal empuja el d correcto por encima del piso de ruido. Esto explica cómo el algoritmo tiene éxito a pesar de fidelidades de circuito que harían parecer imposible la computación.
A escala de juguete, el paso de verificación de la extracción (d_cand * G == Q) actúa como un filtro que acepta solo el d verdadero. Esto significa que incluso triples (j, k, r) puramente aleatorios producirán candidatos válidos a una tasa de aproximadamente disparos / n por ejecución. Cuando disparos >> n, el ruido aleatorio por sí solo puede recuperar d con alta probabilidad.
Para probar si el circuito cuántico contribuye señal más allá de este piso de ruido clásico, ejecutamos el desafío de 6 bits (n=31) con solo 8 disparos (muy por debajo del orden del grupo) 10 veces en ibm_kingston:
Resultado: 4/10 éxitos (40%) frente a una línea base de ruido clásico de ~20% (calculada mediante simulación Monte Carlo: 8 cadenas de bits aleatorias con (r-j)*k_inv mod 31 filtradas por verificación). Prueba binomial unilateral: P(X >= 4 | n=10, p=0.20) = 0.121, lo que indica una mejora de 2x sobre el piso de ruido. Aunque no es estadísticamente significativo individualmente a p < 0.05 (que requeriría 5+ éxitos), la tasa observada es consistente con una señal cuántica que contribuye aproximadamente 1-2 pares (j, k) válidos adicionales por ejecución más allá de lo que proporciona el azar.
Este resultado se sitúa entre el piso de ruido clásico y el régimen de ventaja cuántica teórica. En tamaños de curva más grandes donde n >> disparos, la línea base de ruido cae por debajo del 1% y cualquier recuperación exitosa de clave se convierte en evidencia sólida de computación cuántica.
git clone https://github.com/GiancarloLelli/quantum.git cd quantum
python -m venv . Scripts\Activate.ps1 # For Windows only
pip install -r requirements.txt
### Cómo ejecutar
Necesitas una cuenta de [IBM Quantum](https://quantum.ibm.com/). Proporciona tu API token en la primera ejecución y se guardará localmente:```bash
# Solve the 4-bit challenge curve:
python projecteleven.py --challenge 4 --token YOUR_IBM_TOKEN --backend ibm_marrakesh
# Subsequent runs (token already saved):
python projecteleven.py --challenge 4 --backend ibm_marrakesh
# Use the coordinate-based quantum oracle:
python projecteleven.py --challenge 4 --oracle coordinate --backend ibm_marrakesh
# Use the arithmetic oracle (coordinate encoding + QFT primitives):
python projecteleven.py --challenge 4 --oracle arithmetic --backend ibm_marrakesh
# Use ripple-carry modular addition (CDKM — best for 8-bit+):
python projecteleven.py --challenge 16 --oracle ripple --backend ibm_fez --shots 20000
# Use Google semiclassical phase estimation (qubit-recycled):
python projecteleven.py --challenge 4 --oracle google --backend ibm_marrakesh
# Use a specific IBM Quantum instance:
python projecteleven.py --challenge 4 --instance ibm-q/open/main --backend ibm_marrakesh
# Verify curve parameters without quantum execution:
python projecteleven.py --curve curve_4 --verify-only
projecteleven.py # Shor solver — dense unitary approach + CLI entry point quantum_arithmetic.py # Efficient permutation decomposition + QFT arithmetic primitives quantum_oracle.py # Coordinate-based oracle + arithmetic oracle framework google_semiclassical.py # Google semiclassical PE — qubit-recycled phase estimation ripple_carry_shor.py # Ripple-carry modular addition oracle (CDKM) — best for 8-bit+ input_curves.json # Challenge curves (4-bit to 30-bit) problem/curves.py # Curve generation utility requirements.txt # qiskit, qiskit-ibm-runtime
## Referencias
- P. Shor, ["Algorithms for Quantum Computation: Discrete Logarithms and Factoring"](https://arxiv.org/abs/quant-ph/9508027) (1994)
- S. Beauregard, ["Circuit for Shor's algorithm using 2n+3 qubits"](https://arxiv.org/abs/quant-ph/0205095) (2003)
- S. A. Cuccaro, T. G. Draper, S. A. Kutin, D. P. Moulton, ["A new quantum ripple-carry addition circuit"](https://arxiv.org/abs/quant-ph/0410184) (2004)
- M. Roetteler, M. Naehrig, K. Svore, K. Lauter, ["Quantum resource estimates for computing elliptic curve discrete logarithms"](https://arxiv.org/abs/1706.06752) (2017)
- R. Griffiths, C.-S. Niu, ["Semiclassical Fourier Transform for Quantum Computation"](https://arxiv.org/abs/quant-ph/9511007) (1996)
- R. Babbush et al., ["Securing Elliptic Curve Cryptocurrencies against Quantum Vulnerabilities: Resource Estimates and Mitigations"](https://quantumai.google/static/site-assets/downloads/cryptocurrency-whitepaper.pdf) (2026)
## Licencia
Este proyecto es una presentación para el Q-Day Prize Challenge publicado bajo [LICENCIA MIT](https://github.com/yuvadm/quantumslop/blob/HEAD/LICENSE)
| Tamaño de curva | Qubits estándar | Qubits semiclásicos | Ahorro | Verificado en hardware |
|---|
| 4 bits (n=7) | 11 | 5 | 55% | Sí |
| 6 bits (n=31) | 17 | 7 | 59% | Sí |
| 7 bits (n=79) | 26 + anc | 14 | 46% | Sí |
| 8 bits (n=139) | 25 + anc | 10 + anc | 60% | No (sobrecarga de sincronización QPU) |
| 10 bits (n=547) | 31 + anc | 12 + anc | 61% | No (sobrecarga de sincronización QPU) |
| Tamaño de curva | Qubits | Puertas 2Q (transpiladas) | Verificado en hardware |
|---|
| 4 bits (n=7) | 17 | 1,824 | Sí (simulación) |
| 8 bits (n=139) | 37 | 11,224 | — |
| 10 bits (n=547) | 45 | 17,204 | — |
| 12 bits (n=2143) | 53 | 24,304 | — |
| 16 bits (n=32497) | 65 | 98,049 | Sí |
| 17 bits (n=65173) | 69 | 111,816 | Sí |
| Métrica | Unitaria Densa | Permutación Eficiente | Oráculo de Coordenadas | Oráculo Aritmético | EP Semiclásica | Acarreo en Cascada |
|---|
| Codificación de puntos | Índice de grupo | Índice de grupo | (x, y, id_flag) | (x, y, id_flag) | Índice de grupo | Índice de grupo |
| Escalado por suma | O(4^n) descomp. | O(N * n) | O(N * f_bits) | O(n^3) asintótico | O(N * n) | O(m^2) |
| Qubits (4 bits) | 11 | 13 | 24 | 24 | 5 | 17 |
| Qubits (6 bits) | 17 | 21 | 36 | 36 | 9 | 25 |
| Puertas 2Q (4 bits) | 774 | ~1,200 | 6,449 | 6,449 | ~1,200 | 1,824 |
| Puertas 2Q (6 bits) | 23,471 | ~38,000 | 95,254 | 95,254 | ~38,000 | 4,582 |
| Rango práctico | <= 6 bits | <= ~16 bits | <= 6 bits | >= 20 bits (futuro) | <= ~16 bits | <= ~20 bits |
| Desafío | p | n | Estrategia | Qubits | Puertas 2Q | Profundidad transpilada | Disparos | Backend | d recuperado | ID de trabajo |
|---|
| 4 bits | 13 | 7 | Unitaria densa | 11 | 774 | 2,425 | 8,192 | ibm_torino | 6 | d73u28kvllmc73anvi90 |
| 4 bits | 13 | 7 | Oráculo de coordenadas | 24 | 6,449 | 13,125 | 8,192 | ibm_kingston | 6 | d74ht798qmgc73fm32c0 |
| 4 bits | 13 | 7 | Oráculo aritmético | 24 | 6,477 | 13,452 | 8,192 | ibm_torino | 6 | d75648lbjrds73ec0eng |
| 4 bits | 13 | 7 | EP semiclásica | 5 | 747 | 2,522 | 256 | ibm_kingston | 6 | d75p1ftbjrds73ecne3g |
| 6 bits | 43 | 31 | Unitaria densa | 17 | 23,471 | 72,475 | 8,192 | ibm_torino | 18 | d73u2l5koquc73e24u8g |
| 6 bits | 43 | 31 | Oráculo de coordenadas | 36 | 95,254 | 169,766 | 8,192 | ibm_kingston | 18 | d74hu918qmgc73fm33g0 |
| 6 bits | 43 | 31 | EP semiclásica | 7 | 23,256 | 73,183 | 256 | ibm_kingston | 18 | d75p1unq1anc738cmr6g |
| 7 bits | 67 | 79 | EP semiclásica | 14 | 127,918 | 266,122 | 256 | ibm_kingston | 56 | d75p3sq3qcgc73fs2fpg |
| 8 bits | 163 | 139 | Permutación eficiente | 32 | 294,628 | 599,517 | 8,192 | ibm_kingston | 103 | d73ui15koquc73e25e4g |
| 9 bits | 349 | 313 | Permutación eficiente | 36 | 887,544 | 1,764,266 | 8,192 | ibm_torino | 135 | d73ua2h8qmgc73flei9g |
| 10 bits | 547 | 547 | Permutación eficiente | 40 | 2,049,138 | 3,948,250 | 1,024 | ibm_torino | 165 | d752vfu8faus73evhovg |
| 16 bits | 32,803 | 32,497 | Acarreo en cascada | 65 | 98,049 | 202,994 | 20,000 | ibm_fez | 20,248 | d790j2hq1efs73d2979g |
| 17 bits | 65,647 | 65,173 | Acarreo en cascada | 69 | 111,816 | 231,475 | 20,000 | ibm_fez | 1,441 | d790krrc6das739idasg |
| Desafío | Estrategia | Puertas 2Q | Fidelidad estimada del circuito | Resultados únicos | Disparos totales | Régimen de señal |
|---|
| 4 bits | Densa | 774 | ~2.1% | 1,869 / 2,048 | 8,192 | Señal débil |
| 6 bits | Densa | 23,471 | ~10^{-51} | 3,776 / 131,072 | 8,192 | Dominado por ruido |
| 8 bits | Permutación | 294,628 | ~10^{-644} | 8,128 / 4.3B | 8,192 | Dominado por ruido |
| 9 bits | Permutación | 887,544 | ~10^{-1,939} | 8,168 / 68.7B | 8,192 | Dominado por ruido |
| 10 bits | Permutación | 2,049,138 | ~10^{-4,477} | 1,024 / 1.1T | 1,024 | Dominado por ruido |
| 16 bits | Acarreo en cascada | 98,049 | ~10^{-214} | 20,000 / 2^65 | 20,000 | Dominado por ruido |
| 17 bits | Acarreo en cascada | 111,816 | ~10^{-244} | 20,000 / 2^69 | 20,000 | Dominado por ruido |
| Ejecución | ID de trabajo | Resultado |
|---|
| 1 | d75qrrq3qcgc73fs4hn0 | FALLO |
| 2 | d75qs3e8faus73f0ep6g | FALLO |
| 3 | d75qsafq1anc738coujg | FALLO |
| 4 | d75qsie8faus73f0eplg | d = 18 |
| 5 | d75qsq23qcgc73fs4ing | d = 18 |
| 6 | d75qt168faus73f0eq50 | FALLO |
| 7 | d75qt7vq1anc738covf0 | d = 18 |
| 8 | d75qthu8faus73f0eqmg | FALLO |
| 9 | d75qtodbjrds73ecpk80 | d = 18 |
| 10 | d75qtvi3qcgc73fs4jsg | FALLO |
| Indicador | Descripción | Por defecto |
|---|
--challenge N | Resuelve la curva de desafío de N bits desde input_curves.json | — |
--curve NAME | Usa una curva de prueba incorporada (curve_4) | — |
--token TOKEN | Token de la API de IBM Quantum (guardado localmente en el primer uso) | — |
--backend NAME | Backend de IBM Quantum | ibm_marrakesh |
--instance ID | Instancia de IBM Quantum | open-instance |
--shots N | Número de disparos de medición | 8192 |
--oracle TYPE | Estrategia de oráculo: dense, permutation, coordinate, arithmetic, google o ripple | auto |
--optimization-level N | Nivel de optimización de transpilación de Qiskit (0-3) | 3 |
--d N | Clave secreta conocida para pruebas (con --curve) | — |
--verify-only | Valida los parámetros de la curva y sale | — |