Tópicos populares
#
Bonk Eco continues to show strength amid $USELESS rally
#
Pump.fun to raise $1B token sale, traders speculating on airdrop
#
Boop.Fun leading the way with a new launchpad on Solana.
Os computadores quânticos disponíveis comercialmente podem quebrar secp5k1.
Ainda estão cerca de 2 ordens de magnitude distantes... Por enquanto.

27/06/2025
Quebrando uma Chave de Curva Elíptica de 5 Bits com um Computador Quântico de 133 Qubits ⚛️
Este experimento quebra uma chave criptográfica de curva elíptica de 5 bits usando o algoritmo de Shor. Executado no ibm_torino de 133 qubits da @IBM com @qiskit, um circuito de 15 qubits, composto por 10 qubits lógicos e 5 ancillas, interfere sobre ℤ₃₂ para extrair o escalar secreto k da relação da chave pública Q = kP, sem nunca codificar k diretamente no oráculo. De 16.384 tentativas, a interferência quântica revela uma crista diagonal no espaço de resultados da QFT 32x32. O circuito quântico, com mais de 67.000 camadas de profundidade, produziu padrões de interferência válidos apesar da profundidade extrema do circuito, e o pós-processamento clássico revelou k = 7 nos 100 melhores resultados invertíveis (a, b).
Análise do Código
1. Codificação de Grupos
Restringir a atenção ao subgrupo de ordem 32 ⟨𝑃⟩ de uma curva elíptica sobre 𝐹_p.
Mapear pontos para inteiros:
0𝑃 -> 0, 1𝑃 -> 1, …, 31𝑃 -> 31.
A lei do grupo torna-se adição modular:
(𝑥𝑃) + (𝑦𝑃) = ((𝑥 + 𝑦) mod 32))𝑃.
Este experimento usa uma curva elíptica sobre F_p com um subgrupo cíclico de ordem 32, mapeando P -> 1 e Q = 7P -> 23 em ℤ₃₂. O código assume multiplicação escalar pré-computada, abstraindo coordenadas explícitas.
2. Registros Quânticos
Registro a: cinco qubits para o expoente 𝑎 ∈ {0, …, 31}.
Registro b: cinco qubits para 𝑏 ∈ {0, …, 31}.
Registro p: cinco qubits inicializados em ∣0⟩ para manter o índice do ponto.
Registro clássico c: um registro de 10 bits para registrar os valores medidos de a e b.
3. Preparação de Superposição
Aplicar Hadamards a cada qubit em a e b:
31
1/32 ∑ ∣a⟩_a ∣b⟩_b ∣0⟩_p
a, b=0
4. Construção do Oráculo U_f
O objetivo é um mapeamento reversível:
∣a⟩ ∣b⟩ ∣0⟩ -> ∣a⟩ ∣b⟩ ∣aP + bQ⟩.
Adicionar aP: para cada bit a_i (peso 2^𝑖), adicionar (2^𝑖 P) mod 32
Adicionar bQ: calcular (2^𝑖 𝑄) mod 32, depois adicionar controlado em 𝑏_𝑖.
Esses usam portas de permutação controladas de 5 qubits. Todas as constantes são derivadas do gerador P da curva elíptica e do ponto público Q.
Nenhuma porta faz referência direta ao secreto k.
5. Estado Global após o Oráculo
O estado evolui para:
1/32 ∑ ∣a⟩∣b⟩∣f(a, b)⟩, onde f(a, b) = a + kb (mod32).
a, b
6. Isolar o Registro do Ponto
O algoritmo precisa apenas da relação de fase em 𝑎, 𝑏. Uma barreira isola p.
7. Transformada de Fourier Quântica (QFT)
QFT 31
∣a⟩ -> 1/√32 ∑ e^((2πi)/32 au) ∣u⟩,
u=0
QFT 31
∣b⟩ -> 1/√32 ∑ e^((2πi)/32 bv) ∣v⟩.
v=0
8. Padrão de Interferência
A amplitude conjunta para observar (u, v) é:
1/32 ∑_(a, b) e^((2πi/32)(au + bv)) δ_(a + kb ≡ 0) = 1/32 δ_(u + kv ≡ 0 (mod 32)), que forma uma crista diagonal na grade de resultados 32x32.
9. Medição
Medir todos os dez qubits lógicos. Os resultados se concentram nos 32 pares distintos que satisfazem u + kv ≡ 0 (mod 32).
10. Pós-processamento Clássico
As cadeias de bits são invertidas e analisadas em pares (a, b). Manter apenas linhas onde gcd(b, 32) = 1, garantindo que b seja invertível. A chave candidata é computada como:
k = (-a) b^(-1) mod 32
O script então:
Extrai os 100 resultados invertíveis (a, b) com maior contagem.
Computa k para cada um.
Imprime cada par (a, b), k recuperado e contagem.
Declara sucesso se k = 7 aparecer nos 100 melhores.
11. Verificação e Armazenamento
O escalar correto k = 7 é confirmado se aparecer nos 100 melhores resultados invertíveis.
Todas as contagens de cadeias de bits brutas, layout de qubits e metadados são salvos em JSON para visualização e análise adicionais.
Resultados
2025-06-25 19:41:29,294 | INFO | Profundidade do circuito 67428, contagens de portas OrderedDict({'sx': 56613, 'cz': 34319, 'rz': 15355, 'x': 157, 'medir': 10, 'barreira': 1})
base_primitive._run:INFO:2025-06-25 19:41:29,994: Enviando trabalho usando opções {'options': {}, 'version': 2, 'support_qiskit': True}
SUCESSO — k = 7 encontrado nos 100 melhores resultados
Os 100 melhores pares invertíveis (a, b) e k recuperado:
(a= 8, b=11) → k = 8 (contagem = 63)
(a=12, b= 9) → k = 20 (contagem = 58)
(a= 0, b= 3) → k = 0 (contagem = 54)
(a= 1, b= 9) → k = 7 (contagem = 54) <<<
(a=28, b= 1) → k = 4 (contagem = 53)
(a= 0, b=11) → k = 0 (contagem = 53)
(a= 8, b= 9) → k = 24 (contagem = 53)
(a= 8, b= 3) → k = 8 (contagem = 53)
...
(a=11, b= 3) → k = 7 (contagem = 41) <<<
...
(a=25, b= 1) → k = 7 (contagem = 32) <<<
Esta execução recuperou com sucesso o escalar secreto k = 7 usando uma chave ECC de 5 bits (subgrupo de ordem 32), estendendo meu ataque anterior de 4 bits para um espaço com 1024 combinações possíveis (a, b) e φ(32) = 16 valores b invertíveis.
k = 7 aparece três vezes nos 100 melhores:
(a = 1, b = 9) -> k = 7 com 54 contagens
(a = 11, b = 3) -> k = 7 com 41 contagens
(a =25, b = 1) -> k = 7 com 32 contagens
Estes são estados de alta frequência, tornando-os vetores de ataque credíveis sob pós-processamento clássico.
As contagens exibem concentração em torno de relações modulares estruturadas: a + kb ≡ 0 mod 32. Estas aparecem como cristas diagonais no espaço de medição 32x32. Vários valores de k se repetem frequentemente (k = 0, 24, 28), mostrando a sobreposição probabilística intrínseca à interferência quântica, alguns destes são falsos positivos provenientes de ruído ou aliasing com outras equivalências modulares.
A profundidade do circuito foi de 67.428, com um total de 106.455 portas, refletindo uma rotina quântica grande e complexa para aritmética de índice modular controlada. Esta pode ser a maior quantidade de portas que já usei em um circuito.
Contagens de portas para o circuito:
sx: 56613
cz: 34319
rz: 15355
x: 157
medir: 10
barreira: 1
Total de portas: 106455
Profundidade: 67428
Largura: 133 qubits | 10 clbits
Este experimento levou 54 segundos para ser concluído no 'ibm_torino'.
O perfil de ruído é não uniforme, mas decrescente, o que significa que o sistema quântico provavelmente resolveu harmônicos dominantes na interferência, mas borrifou estruturas mais finas. A cauda da distribuição ainda contém candidatos válidos k = 7, isso apoia ataques quânticos estilo dicionário onde varreduras de resultados top-N (N = 100) são suficientes para recuperar a chave.
A Mapa de Contagem Bruta (a vs b) acima (código completo no Qwork) mostra uma grade 32x32 que representa as contagens observadas para cada par (a, b) após a execução do circuito de Shor. O mapa de calor mostra uma distribuição em faixas e desigual, indicando cristas de interferência, não ruído. Certas linhas (valores de a) têm concentração visivelmente maior, sugerindo interferência construtiva ao longo de soluções específicas a + kb ≡ 0 mod 32.
O Histograma de Valores k Recuperados acima (código completo no Qwork) agrega as contagens totais para cada chave escalar recuperada k ∈ Z₃₂, derivadas via k = −ab^(−1) mod 32. Um grande pico em k = 0 e outro em torno de k = 24 são dominantes. A chave correta k = 7 não é a mais alta, mas está bem representada (~54 + 41 + 32 = 127 contagens em múltiplos pares (a, b)). Isso mostra que hackers podem atacar dicionários com uma quantidade maior de resultados.
O Rank de Cadeia de Bits vs Contagem (Escala Logarítmica) acima (código completo no Qwork) mostra um gráfico de rank tipo Zipf de todas as cadeias de bits por contagem decrescente. O eixo y em escala logarítmica mostra uma cauda exponencial, a maioria dos resultados ocorre <10 vezes. A cabeça (top ~50) das cadeias de bits tem probabilidade muito mais alta, indicando picos de interferência construtiva. Você poderia construir um ataque quântico heurístico de dicionário que colhe apenas as N cadeias de bits principais com retorno exponencial sobre o sinal. Isso valida que a estrutura de sinal-para-ruído quântica ainda está intacta mesmo com circuitos mais longos (67428 de profundidade).
As Localizações de (a, b) Decodificando para k = 7 acima (código completo no Qwork) mostram que cada ponto é um par (a, b) que decodificou para k = 7. A intensidade da cor é igual ao número de vezes que este par ocorreu. O gráfico mostra uma distribuição relativamente uniforme em (a, b), mas com picos locais em (1, 9), (11, 3), (25, 1). Múltiplas combinações (a, b) convergem para k = 7 com multiplicidade não uniforme. De um ponto de vista criptoanalítico, isso valida que o algoritmo de Shor pode quebrar chaves ECC de forma confiável, mesmo quando o k correto não é o resultado número 1.
A Máscara de Invertibilidade para o Registro b acima (código completo no Qwork) mostra um gráfico de barras das contagens para cada b ∈ {0, …, 31} que são coprimos com 32 (gcd(b, 32) = 1, apenas estes são invertíveis módulo 32 e úteis para recuperar k via:
k = (−a)b^(−1) mod 32. Os b invertíveis estão bem populados, mostrando que o circuito produziu candidatos recuperáveis. Mais uniformidade aqui aumentaria o poder do pós-processamento, idealmente, estes seriam planos.
O Mapa de Frequência do Inverso Modular: b vs b^(−1) mod 32 acima (código completo no Qwork) mostra um mapa de calor de quão frequentemente cada b invertível mapeia para cada inverso modular correspondente b^(−1) mod 32, ponderado pelas contagens de resultados. A maioria dos pontos cai em uma linha bijetiva limpa, cada b mapeia claramente para um único b^(−1), confirmando a correção da inversão modular. Regiões mais brilhantes (perto do canto inferior esquerdo ou superior direito) mostram b's favorecidos pela amostragem quântica. Sem ruído ou agrupamento fora da diagonal, bom sinal de estrutura modular limpa preservada.
O Mapa a + 7b mod 32 acima (código completo no Qwork) assume k = 7 e plota o valor de (a + 7b) mod 32 em todos os resultados. A distribuição é quase uniforme. Isso sugere que não há crista de interferência acentuada como no caso de 4 bits. Por quê? O circuito de 5 bits (com 10 qubits lógicos) espalha a amplitude mais fina em 1024 resultados, reduzindo o contraste. No entanto, a chave correta ainda era recuperável, indicando muitos caminhos fracamente construtivos, em vez de alguns dominantes.
A Eficiência do Ataque ECC: b Válido vs Inválido acima (código completo no Qwork) mostra contagens totais de amostras com b invertível (útil para recuperação de chave) vs. b não invertível (inútil). Mais da metade dos resultados são desperdiçados em valores b inválidos (gcd(b, 32) != 1). O próximo design para uma quebra de 6 bits poderia usar mascaramento de oráculo ou filtragem de pós-seleção em domínios b válidos.
O Mapa de Calor: (a, b) com b Invertível (mod 32) acima (código completo no Qwork) foca apenas em pares (a, b) onde b é invertível módulo 32, uma condição necessária para recuperar k. Ele mostra onde a interferência quântica está se concentrando dentro do espaço de 1024 pontos. As regiões de alta intensidade revelam caminhos de interferência preferidos, sugerindo que o estado quântico evoluiu de forma não uniforme, possivelmente favorecendo certas órbitas sob multiplicação modular. Isso confirma que a coerência do sinal é forte o suficiente em algumas regiões para isolar candidatos válidos.
A Distribuição de Ângulos de Crista de Fase acima (código completo no Qwork) agrupa os ângulos formados pelos vetores (-a, b) no plano, módulo π, que correspondem aproximadamente a cristas de fase no espaço QFT. Picos no histograma indicam fortes alinhamentos, ressonâncias, da forma u + kv ≡ 0, significando que o circuito codificou com sucesso k no padrão de interferência, mesmo que o espaço de estado completo seja vasto. Os múltiplos ângulos dominantes sugerem que harmônicos do deslocamento oculto estão presentes.
O Mapa de Resíduo de a + 7b mod 32 acima (código completo no Qwork) visualiza o resíduo de saída para a chave alvo específica k = 7, em todo o espaço (a, b). Quaisquer faixas ou simetrias consistentes aqui indicam quão bem a interferência amplificou soluções válidas (onde este valor é igual a 0). Você pode observar quais regiões da rede 1024 correspondem a a + 7b ≡ 0, validando que a estrutura do oráculo levou a uma impressão de chave bem-sucedida.
O Ruído: Variância da Contagem em b para a fixa acima (código completo no Qwork) mostra quão ruidosas ou estáveis foram as contagens de saída para cada a fixa enquanto variamos b. Alta variância significa que alguns valores de b levam a forte amplificação enquanto outros não, implicando sensibilidade do circuito ou ruído de backend para aquela linha a. Regiões suaves implicam coerência quântica, enquanto picos podem apontar para decoerência ou propagação de erro durante a avaliação do oráculo.
No final, este experimento quebrou com sucesso uma chave de curva elíptica de 5 bits usando o algoritmo de Shor executado no processador quântico de 133 qubits da IBM, estendendo o resultado anterior de 4 bits para um espaço de interferência significativamente maior (32x32 = 1024 resultados). Este circuito codificou o oráculo sobre ℤ₃₂ sem nunca referenciar o escalar secreto k, e aproveitou a aritmética de grupo modular para entrelaçar o escalar na interferência de fase. O circuito quântico, com mais de 67.000 camadas de profundidade, produziu padrões de interferência válidos apesar da profundidade extrema do circuito, e o pós-processamento clássico revelou k = 7 nos 100 melhores resultados invertíveis (a, b). Através de visualizações, este experimento confirmou estruturas de crista diagonal, máscaras de invertibilidade e alinhamento harmônico de cristas de interferência, validando que a coerência quântica permaneceu forte o suficiente para amplificar a relação modular correta. Isso estabelece que o algoritmo de Shor continua a escalar sob regimes de circuito mais profundos e que estratégias de recuperação de chave baseadas em dicionário (enumeração dos 100 melhores) permanecem viáveis à medida que o comprimento dos bits aumenta, mostrando clara vantagem quântica mesmo sob condições reais ruidosas.
Código
# Circuito principal
# Importações
import logging, json
from math import gcd
import numpy as np
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile
from qiskit.circuit.library import UnitaryGate, QFT
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2
import pandas as pd
# IBMQ
TOKEN = "YOUR_IBMQ_API_KEY"
INSTANCE = "YOUR_IBMQ_CRN"
BACKEND = "ibm_torino"
CAL_CSV = "/Users/steventippeconnic/Downloads/ibm_torino_calibrations_2025-06-26T02_21_07Z.csv"
SHOTS = 16384
# Parâmetros da curva de brinquedo (subgrupo de ordem 32 de E(F_p))
ORDER = 32 # |E(F_p)| = 32
P_IDX = 1 # Gerador P -> índice 1
Q_IDX = 23 # Ponto público Q = kP, aqui “23 mod 32” para k = 7
# Helper de logging
logging.basicConfig(level=logging .INFO,
format="%(asctime)s | %(levelname)s | %(message)s")
log = logging.getLogger(__name__)
# Seleção de qubit baseada em calibração
def best_qubits(csv_path: str, n: int) -> list[int]:
df = pd .read_csv(csv_path)
df.columns = df.columns.str.strip()
winners = (
df.sort_values(["√x (sx) error", "T1 (us)", "T2 (us)"],
ascending=[True, False, False])
["Qubit"].head(n).tolist()
)
log .info("Melhores qubits físicos: %s", winners)
return winners
N_Q = 5
N_Q_TOTAL = N_Q * 3 # a, b, ponto
PHYSICAL = best_qubits(CAL_CSV, N_Q_TOTAL)
# Adicionador constante módulo 32 como uma porta reutilizável
def add_const_mod32_gate(c: int) -> UnitaryGate:
"""Retorna uma porta de 5 qubits que mapeia |x⟩ ↦ |x+c (mod 32)⟩."""
mat = np.zeros((32, 32))
for x in range(32):
mat[(x + c) % 32, x] = 1
return UnitaryGate(mat, label=f"+{c}")
ADDERS = {c: add_const_mod32_gate(c) for c in range(1, 32)}
def controlled_add(qc: QuantumCircuit, ctrl_qubit, point_reg, constant):
"""Aplica |x⟩ → |x+constant (mod 32)⟩ controlado por um qubit."""
qc.append(ADDERS[constant].control(), [ctrl_qubit, *point_reg])
# Oráculo U_f : |a⟩|b⟩|0⟩ ⟶ |a⟩|b⟩|aP + bQ⟩ (aritmética de índice mod 32)
def ecdlp_oracle(qc, a_reg, b_reg, point_reg):
for i in range(N_Q):
constant = (P_IDX * (1 << i)) % ORDER
if constant:
controlled_add(qc, a_reg[i], point_reg, constant)
for i in range(N_Q):
constant = (Q_IDX * (1 << i)) % ORDER
if constant:
controlled_add(qc, b_reg[i], point_reg, constant)
# Construir o circuito completo de Shor
def shor_ecdlp_circuit() -> QuantumCircuit:
a = QuantumRegister(N_Q, "a")
b = QuantumRegister(N_Q, "b")
p = QuantumRegister(N_Q, "p")
c = ClassicalRegister(N_Q * 2, "c")
qc = QuantumCircuit(a, b, p, c, name="ECDLP_32pts")
qc.h(a)
qc.h(b)
ecdlp_oracle(qc, a, b, p)
qc.barrier()
qc.append(QFT(N_Q, do_swaps=False), a)
qc.append(QFT(N_Q, do_swaps=False), b)
qc.measure(a, c[:N_Q])
qc.measure(b, c[N_Q:])
return qc
# Execução do IBM Runtime
service = QiskitRuntimeService(channel="ibm_cloud",
token=TOKEN,
instance=INSTANCE)
backend = service.backend(BACKEND)
log .info("Backend → %s", backend .name)
qc_raw = shor_ecdlp_circuit()
trans = transpile(qc_raw,
backend=backend,
initial_layout=PHYSICAL,
optimization_level=3)
log .info("Profundidade do circuito %d, contagens de portas %s", trans.depth(), trans.count_ops())
sampler = SamplerV2(mode=backend)
job = sampler .run([trans], shots=SHOTS)
result = job.result()
# Pós-processamento clássico
creg_name = trans.cregs[0].name
counts_raw = result[0].data.__getattribute__(creg_name).get_counts()
def bits_to_int(bs): return int(bs[::-1], 2)
counts = {(bits_to_int(k[N_Q:]), bits_to_int(k[:N_Q])): v
for k, v in counts_raw.items()}
top = sorted(counts.items(), key=lambda kv: kv[1], reverse=True)
# Critérios de sucesso. Verifique as 100 melhores linhas invertíveis para k = 7
top_invertibles = []
for (a_val, b_val), freq in top:
if gcd(b_val, ORDER) != 1:
continue
inv_b = pow(b_val, -1, ORDER)
k_candidate = (-a_val * inv_b) % ORDER
top_invertibles.append(((a_val, b_val), k_candidate, freq))
if len(top_invertibles) == 100:
break
# Verifique o sucesso e imprima os resultados
found_k7 = any(k == 7 for (_, k, _) in top_invertibles)
if found_k7:
print("\nSUCESSO — k = 7 encontrado nos 100 melhores resultados\n")
else:
print("\nAVISO — k = 7 NÃO encontrado nos 100 melhores resultados\n")
print("Os 100 melhores pares invertíveis (a, b) e k recuperado:")
for (a, b), k, count in top_invertibles:
tag = " <<<" if k == 7 else ""
print(f" (a={a:2}, b={b:2}) → k = {k:2} (contagem = {count}){tag}")
# Salvar dados brutos
out = {
"experimento": "ECDLP_32pts_Shors",
"backend": backend .name,
"qubits_físicos": PHYSICAL,
"shots": SHOTS,
"contagens": counts_raw
}
JSON_PATH = "/Users/steventippeconnic/Documents/QC/Shors_ECC_5_Bit_Key_0.json"
with open(JSON_PATH, "w") as fp:
json.dump(out, fp, indent=4)
log .info("Resultados salvos → %s", JSON_PATH)
# Fim
Código completo para todas as visualizações usando dados de execução no Qwork.




9,77K
Top
Classificação
Favoritos