Traducción automática del original en inglés. English

Prueba de implementaciones de criptografía poscuántica: guía para desarrolladores

📅 Última actualización: 2 de agosto de 2026 🎧 Escuche: ~6 min

El código criptográfico exige pruebas rigurosas; los errores pueden ser catastróficos. Las implementaciones poscuánticas añaden complejidad con claves de mayor tamaño y nuevas operaciones matemáticas. Esta guía cubre estrategias de prueba para implementaciones de Kyber y SPHINCS+, desde pruebas unitarias hasta fuzzing. El Cartera SynX con resistencia cuántica emplea todas estas técnicas para garantizar la corrección criptográfica.

Descripción general de la estrategia de prueba

Una estrategia integral de pruebas de PQC incluye:

  • Pruebas de respuestas conocidas (KAT): Verifique con los vectores de prueba oficiales NIST
  • Pruebas unitarias: Pruebe funciones individuales de forma aislada
  • Pruebas de ida y vuelta: Verificar cifrar → descifrar y firmar → verificar ciclos
  • Pruebas de casos extremos: Mensajes vacíos, tamaños máximos, entradas con formato incorrecto
  • Pruebas de implementación cruzada: Verificar la interoperabilidad con otras bibliotecas
  • Fuzzing: Descubra fallas y comportamientos inesperados
  • Pruebas de canal lateral: Verificar la ejecución en tiempo constante

Configurar el entorno de prueba

# requisitos.txt para pruebas PQC pytest>=7.0.0 pytest-xdist>=3.0.0 # Ejecución de pruebas en paralelo pytest-cov>=4.0.0 # Informes de cobertura hipótesis>=6.0.0 # Pruebas basadas en propiedades liboqs-python>=0.9.0 # Algoritmos PQC pycryptodome>=3.19.0 # Utilidades criptográficas adicionales
# conftest.py - Configuración de Pytest importar pytest importar oqs @pytest.accesorio def kyber_kem(): """Dispositivo que proporciona la instancia KEM Kyber-768""" devolver oqs.KeyEncapsulation("Kyber768") @pytest.accesorio def esfincs_sig(): """Accesorio que proporciona la instancia de firma SPHINCS+-SHAKE-128s""" devolver oqs.Firma("SPHINCS+-SHAKE-128s-simple") @pytest.accesorio def kyber_keypair(kyber_kem): """Par de claves Kyber pregenerado para pruebas""" pk = kyber_kem.generate_keypair() sk = kyber_kem.export_secret_key() devolver pk, sk @pytest.accesorio def par_claves_esfincas(esfincs_sig): """Par de claves SPHINCS+ pregenerado para pruebas""" pk = sphincs_sig.generate_keypair() sk = sphincs_sig.export_secret_key() devolver pk, sk

Pruebas de respuestas conocidas (KAT)

Los KAT verifican que su implementación produzca los resultados esperados para las entradas conocidas:

# test_kats.py - Pruebas de respuestas conocidas importar pytest importar json de rutalib importar Camino clase PruebaKyberKAT: """ Pruebas de respuestas conocidas para vectores de prueba Kyber-768 de la especificación NIST ML-KEM """ @pytest.accesorio def kat_vectores(ser): """Cargar vectores KAT oficiales""" kat_path = Ruta(__archivo__).padre / "vectores" / "kyber768_kat.json" con abierto(kat_path) as f: devolver json.cargar(f) def prueba_encapsulación_kat(yo, kat_vectors, kyber_kem): """Verificar que la encapsulación produzca el texto cifrado esperado""" para vector in vectores_kat["encapsulación"]: pk = bytes.fromhex(vector["clave_pública"]) esperado_ct = bytes.fromhex(vector["texto cifrado"]) esperado_ss = bytes.fromhex(vector["secreto_compartido"]) semilla = bytes.fromhex(vector["semilla"]) # Nota: la encapsulación determinista requiere una biblioteca modificada # Esto prueba el patrón de implementación de referencia. ct, ss = kyber_kem.encap_secret(pk) # Verificar la longitud del texto cifrado afirmar len(ct) == len(esperado_ct), "La longitud del texto cifrado no coincide" # Verificar la longitud del secreto compartido afirmar len(ss) == len(esperado_ss), "La longitud del secreto compartido no coincide" def prueba_decapsulación_kat(yo, kat_vectors, kyber_kem): """Verificar que la decapsulación recupere el secreto compartido esperado""" para vector in vectores_kat["decapsulación"]: sk = bytes.fromhex(vector["clave_secreta"]) ct = bytes.fromhex(vector["texto cifrado"]) esperado_ss = bytes.fromhex(vector["secreto_compartido"]) kem = oqs.KeyEncapsulation("Kyber768", sk) ss = kem.decap_secret(ct) afirmar ss == esperado_ss, "No coincide el secreto compartido" clase PruebaSPHINCSPlusKAT: """Pruebas de respuestas conocidas para SPHINCS+-SHAKE-128""" @pytest.accesorio def kat_vectores(yo): kat_path = Ruta(__archivo__).padre / "vectores" / "sphincs128s_kat.json" con abierto(kat_path) as f: devolver json.cargar(f) def prueba_firma_verificación_kat(yo, kat_vectors): """Verificar que las firmas conocidas se validen correctamente""" para vector in vectores_kat["verificación"]: pk = bytes.fromhex(vector["clave_pública"]) mensaje = bytes.fromhex(vector["mensaje"]) firma = bytes.fromhex(vector["firma"]) sig = oqs.Firma("SPHINCS+-SHAKE-128s-simple") is_valid = sig.verify(mensaje, firma, paquete) afirmar es_válido, f"No se pudo verificar la firma KAT"

Pruebas de ida y vuelta

Las pruebas de ida y vuelta verifican la corrección fundamental de cifrar/descifrar y firmar/verificar:

# prueba_ida y vuelta.py importar pytest importar misterios clase PruebaKyberRoundTrip: """Pruebas de ida y vuelta para Kyber KEM""" def test_basic_kem_cycle(yo, kyber_kem, kyber_keypair): """Ciclo básico de encapsular → decapsular""" pk, sk = kyber_keypair # Encapsular texto cifrado, share_secret_enc = kyber_kem.encap_secret(pk) # Decapsular kem_with_sk = oqs.KeyEncapsulation("Kyber768", sk)shared_secret_dec = kem_with_sk.decap_secret(texto cifrado) afirmar secreto_compartido_enc == secreto_compartido_dec @pytest.mark.parametrizar("iteraciones", [100, 1000]) def prueba_repetida_kem_ciclos(self, kyber_kem, kyber_keypair, iteraciones): """Verificar que KEM funcione de manera consistente en muchas iteraciones""" pk, sk = kyber_keypair kem_with_sk = oqs.KeyEncapsulation("Kyber768",sk) para _ in rango(iteraciones): ct, ss_enc = kyber_kem.encap_secret(pk) ss_dec = kem_with_sk.decap_secret(ct) afirmar ss_enc == ss_dec def test_diferentes_pares_claves_produce_diferentes_resultados(yo, kyber_kem): """Verificar que diferentes claves produzcan diferentes secretos compartidos""" # Generar dos pares de claves diferentes pk1 = kyber_kem.generate_keypair() sk1 = kyber_kem.export_secret_key() kem2 = oqs.KeyEncapsulation("Kyber768") pk2 = kem2.generate_keypair() # Encapsular a cada uno ct1, ss1 = kyber_kem.encap_secret(pk1) ct2, ss2 = kyber_kem.encap_secret(pk2) # Los secretos compartidos deben diferir afirmar ss1 != ss2 clase PruebaSPHINCSRondaViaje: """Pruebas de ida y vuelta para firmas SPHINCS+""" def prueba_basic_sign_verificar(yo, sphincs_sig, sphincs_keypair): """Señal básica → verificar ciclo""" pk, sk = sphincs_keypair mensaje = b"Mensaje de prueba para la firma SPHINCS+" # Firmar sig_with_sk = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk) firma = sig_with_sk.sign(mensaje) # Verificar is_valid = sphincs_sig.verify(mensaje, firma, pk) afirmar es_válido @pytest.mark.parametrizar("tamaño_mensaje", [0, 1, 100, 1000, 10000, 100000]) def prueba_varios_tamaños_de_mensajes(self, sphincs_sig, sphincs_keypair, message_size): """Verificar que la firma funcione para varios tamaños de mensajes""" pk, sk = sphincs_keypair mensaje = secrets.token_bytes(message_size) sig_with_sk = oqs.Signature("SPHINCS+-SHAKE-128s-simple", sk) firma = sig_with_sk.sign(mensaje) afirmar sphincs_sig.verify(mensaje, firma, pk) def prueba_firma_determinismo(yo, sphincs_keypair): """ Nota: SPHINCS+ es aleatorio de forma predeterminada. El mismo mensaje produce firmas diferentes (ambas válidas) """ pk, sk = sphincs_keypair mensaje = b"Mensaje de prueba" sig1 = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk) sig2 = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk) firma1 = sig1.sign(mensaje) firma2 = sig2.sign(mensaje) # Las firmas difieren pero ambas se verifican afirmar firma1 != firma2 # Aleatorizado verificador = oqs.Firma("SPHINCS+-SHAKE-128s-simple") afirmar verificador.verificar (mensaje, firma1, paquete) afirmar verificador.verificar (mensaje, firma2, paquete)

Casos extremos y pruebas de error

# test_edge_cases.py importar pytest clase PruebaKyberEdgeCasos: """Casos extremos y condiciones de error para Kyber""" def test_invalid_public_key_length(yo, kyber_kem): """Rechazar claves públicas con formato incorrecto""" con pytest.raises (Excepción): kyber_kem.encap_secret (b"demasiado_corto") def test_invalid_ciphertext_length(yo, kyber_keypair): """Rechazar texto cifrado con formato incorrecto""" pk, sk = kyber_keypair kem = oqs.KeyEncapsulation("Kyber768",sk) con pytest.raises (Excepción): kem.decap_secret (b"texto_cifrado_inválido") def test_wrong_secret_key_fails_decap(yo, kyber_kem, kyber_keypair): """La decapsulación con una clave incorrecta produce un secreto compartido diferente""" pk, sk = kyber_keypair # Encapsular en pk ct, ss_original = kyber_kem.encap_secret(pk) # Generar un par de claves diferente kem2 = oqs.KeyEncapsulation("Kyber768") kem2.generate_keypair() sk2 = kem2.export_secret_key() # Decapsular con clave incorrecta kem_wrong = oqs.KeyEncapsulation("Kyber768", sk2) ss_wrong = kem_wrong.decap_secret(ct) # Los secretos compartidos deben diferir (seguridad IND-CCA) afirmar ss_original!= ss_incorrecto clase TestSPHINCSEdgeCasos: """Maletas de borde para SPHINCS+""" def mensaje_empty_prueba(yo, sphincs_sig, sphincs_keypair): """Firmar mensaje vacío debería funcionar""" pk, sk = sphincs_keypair mensaje = b"" sig_with_sk = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk) firma = sig_with_sk.sign(mensaje) afirmar sphincs_sig.verify(mensaje, firma, pk) def test_modified_message_fails(yo, sphincs_sig, sphincs_keypair): """La verificación falla si se modifica el mensaje""" pk, sk = sphincs_keypair mensaje = b"Mensaje original" sig_with_sk = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk) firma = sig_with_sk.sign(mensaje) # Modificar mensaje modificado = b"Mensaje modificado" afirmar no sphincs_sig.verify(modificado, firma, pk) def test_modified_signature_fails(yo, sphincs_sig, sphincs_keypair): """La verificación falla si se modifica la firma""" pk, sk = sphincs_keypair mensaje = b"Mensaje de prueba" sig_with_sk = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk) firma = sig_with_sk.sign(mensaje) # Voltear un poco la firma sig_modificado = bytearray(firma) sig_modificado[100] ^= 0x01 sig_modificado = bytes(sig_modificado) afirmar no sphincs_sig.verify(mensaje, modificado_sig, pk) def test_wrong_public_key_fails(yo, sphincs_sig, sphincs_keypair): """La verificación falla con una clave pública diferente""" pk1, sk1 = par de claves_esfincas # Generar segundo par de claves sig2 = oqs.Firma("SPHINCS+-SHAKE-128s-simple") pk2 = sig2.generate_keypair() mensaje = b"Mensaje de prueba" # Firmar con sk1 sig_with_sk = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk1) firma = sig_with_sk.sign(mensaje) # Verificar con pk2 debería fallar afirmar no sphincs_sig.verify(mensaje, firma, pk2)

Pruebas basadas en propiedades con hipótesis

Las pruebas basadas en propiedades generan entradas aleatorias para encontrar casos extremos:

#test_properties.py de hipótesis importar dado, estrategias as st, configuración importar oqs clase PruebaKyberPropiedades: """Pruebas basadas en propiedades para Kyber""" @dado(st.binario(tamaño_mínimo=0, tamaño_máximo=10000)) @ajustes(max_examples=100, fecha límite=Ninguno) def test_encap_decap_roundtrip_any_key(yo, datos_aleatorios): """ Propiedad: Para cualquier par de claves, encap seguido de decap siempre produce secretos compartidos coincidentes """ kem = oqs.KeyEncapsulation("Kyber768") pk = kem.generate_keypair() sk = kem.export_secret_key() ct, ss_enc = kem.encap_secret(pk) kem_dec = oqs.KeyEncapsulation("Kyber768", sk) ss_dec = kem_dec.decap_secret(ct) afirmar ss_enc == ss_dec @dado(st.binario(tamaño_mínimo=1, tamaño_máximo=1088)) @ajustes(max_examples=100, fecha límite=Ninguno) def test_malformed_ciphertext_handled(yo, basura): """ Propiedad: El texto cifrado con formato incorrecto no falla, genera una excepción o devuelve un secreto no válido """ kem = oqs.KeyEncapsulation("Kyber768") kem.generate_keypair() sk = kem.export_secret_key() kem_dec = oqs.KeyEncapsulation("Kyber768",sk) intentar: # Debería subir o regresar (rechazo implícito) resultado = kem_dec.decap_secret(basura) # Si regresa, está bien (rechazo implícito) afirmar len(resultado) == 32 # Aún devuelve un secreto de 32 bytes excepto Excepción: # Subir también es aceptable aprobar clase PruebaSPHINCSPropiedades: """Pruebas basadas en propiedades para SPHINCS+""" @dado(st.binario(tamaño_mínimo=0, tamaño_máximo=50000)) @ajustes(max_examples=50, fecha límite=Ninguno) # Menos debido a la lentitud en la firma def test_sign_verificar_cualquier_mensaje(yo, mensaje): """ Propiedad: Cualquier mensaje puede ser firmado y verificado """ sig = oqs.Firma("SPHINCS+-SHAKE-128s-simple") pk = sig.generate_keypair() sk = sig.export_secret_key() firmante = oqs.Signature("SPHINCS+-SHAKE-128s-simple", sk) firma = firmante.firmar(mensaje) afirmar sig.verify(mensaje, firma, pk) @dado( st.binary(min_size=1, max_size=1000), st.integers(min_value=0, max_value=7855) ) @ajustes(max_examples=50, fecha límite=Ninguno) def test_bit_flip_breaks_signature(yo, mensaje, flip_position): """ Propiedad: Invertir cualquier bit en la firma provoca un error """ sig = oqs.Firma("SPHINCS+-SHAKE-128s-simple") pk = sig.generate_keypair() sk = sig.export_secret_key() firmante = oqs.Signature("SPHINCS+-SHAKE-128s-simple", sk) firma = firmante.firmar(mensaje) # Voltear bit en posición modificado = bytearray(firma) byte_pos = flip_position % len(modificado) bit_pos = flip_position % 8 modificado[byte_pos] ^= (1 << bit_pos) modified = bytes(modified) # Debería fallar la verificación afirmar no sig.verify(mensaje, modificado, pk)

Pruebas de integración para la billetera SynX

# test_synx_wallet.py importar pytest de billetera_synx importar SynXHDWallet, TransactionBuilder clase Integración de TestSynXWallet: """Pruebas de integración para la billetera resistente a lo cuántico SynX""" @pytest.accesorio def billetera_prueba(ser): """Crear billetera de prueba con mnemónico conocido""" mnemónico = "abandonar " * 23 + "arte" devolver SynXHDWallet(mnemónico, frase de contraseña="prueba") def prueba_dirección_derivación_determinista(yo, test_wallet): """La misma ruta siempre produce la misma dirección""" dirección1 = test_wallet.derive_address(0, 0, 0) addr2 = test_wallet.derive_address(0, 0, 0) afirmar dirección1.dirección == dirección2.dirección afirmar addr1.kyber_public == addr2.kyber_public afirmar addr1.sphincs_public == addr2.sphincs_public def prueba_diferentes_rutas_diferentes_direcciones(yo, test_wallet): """Diferentes rutas producen diferentes direcciones""" addr1 = test_wallet.derive_address(0, 0, 0) addr2 = test_wallet.derive_address(0, 0, 1) addr3 = test_wallet.derive_address(0, 1, 0) addr4 = test_wallet.derive_address(1, 0, 0) direcciones = {addr1.address, addr2.address, addr3.address, dirección4.dirección} afirmar len(direcciones) == 4 def prueba_transacción_firma(yo, test_wallet): """La transacción firmada se verifica correctamente""" remitente = test_wallet.derive_address(0, 0, 0) destinatario = test_wallet.derive_address(0, 0, 1) # Construir y firmar transacción constructor = TransactionBuilder(test_wallet) tx = builder.add_output( destinatario.dirección, 100000000, destinatario.kyber_public ).build() # Verificar firma sig = oqs.Firma("SPHINCS+-SHAKE-128s-simple") para entrada in tx.inputs: is_valid = sig.verify( tx.serialize_for_signing(), inp.sphincs_signature, inp.sphincs_public_key) afirmar es_válido

Puntos de referencia de rendimiento

# prueba_rendimiento.py importar pytest importar tiempo importar estadística clase Puntos de referencia de rendimiento de prueba: """Parámetros de rendimiento con detección de regresión""" # Líneas base de rendimiento esperadas (ajustadas por hardware) KYBER_KEYGEN_MAX_MS = 10 KYBER_ENCAP_MAX_MS = 5 KYBER_DECAP_MAX_MS = 5 SPHINCS_KEYGEN_MAX_MS = 100 SPHINCS_SIGN_MAX_MS = 500 SPHINCS_VERIFY_MAX_MS = 50 def _punto de referencia(self, func, iteraciones = 100): """Ejecutar la función varias veces y devolver estadísticas""" veces = [] para _ in rango(iteraciones): inicio = time.perf_counter() func() transcurrido = (time.perf_counter() - inicio) * 1000 # EM veces.añadir(transcurrido) devolver { "significar": estadísticas.media(veces), "mediana": estadísticas.mediana(veces), "desvestándar": estadísticas.stdev(veces) if len(veces) > 1 demás 0, "mínimo": min(veces), "máximo": máx(veces) } def test_kyber_keygen_rendimiento(ser): """Generación de clave Kyber dentro del tiempo esperado""" def generador de claves(): kem = oqs.KeyEncapsulation("Kyber768") kem.generate_keypair() estadísticas = self._benchmark(keygen) print(f"\nKyber keygen: {estadísticas['media']:.2f}ms (±{estadísticas['stdev']:.2f})") afirmar estadísticas["significar"] < self.KYBER_KEYGEN_MAX_MS def test_sphincs_sign_rendimiento(ser): """SPHINCS+ firma dentro del tiempo previsto""" sig = oqs.Firma("SPHINCS+-SHAKE-128s-simple") sig.generate_keypair() sk = sig.export_secret_key() mensaje = b"x" * 256 def firmar(): firmante = oqs.Firma("SPHINCS+-SHAKE-128s-simple", sk) signer.sign(mensaje) stats = self._benchmark(signo, iteraciones=20) # Menos debido a la lentitud imprimir(f"\nSigno SPHINCS+: {estadísticas['media']:.2f}ms (±{estadísticas['stdev']:.2f})") afirmar estadísticas["significar"] < self.SPHINCS_SIGN_MAX_MS

Ejecutando el conjunto de pruebas

# Ejecutar todas las pruebas con cobertura. pruebas de pytest/ -v --cov=synx_wallet --cov-report=html # Ejecutar solo pruebas KAT pruebas de pytest/test_kats.py -v # Ejecutar con ejecución paralela pruebas de pytest/ -n auto # Ejecutar pruebas de rendimiento con salida pruebas de pytest/test_rendimiento.py -v -s

Objetivo de cobertura de prueba

El Cartera SynX con resistencia cuántica mantiene una cobertura de prueba superior al 95% para todo el código criptográfico. Las rutas críticas como la verificación de firmas requieren una cobertura del 100%.

Preguntas frecuentes

¿Dónde encuentro vectores de prueba oficiales para Kyber y SPHINCS+?

NIST proporciona pruebas de respuestas conocidas (KAT) oficiales para todos los algoritmos estandarizados. Los KAT Kyber se encuentran en el apéndice de especificaciones ML-KEM, los KAT SPHINCS+ en SLH-DSA. El proyecto Open Quantum Safe también mantiene vectores de prueba validados para implementaciones de liboqs. El Cartera SynX con resistencia cuántica El conjunto de pruebas incluye vectores compatibles con NIST.

¿Cómo pruebo la temporización de canales laterales en código PQC?

Utilice herramientas como dudect para análisis estadístico de tiempos, Valgrind con solicitudes de clientes para sucursales dependientes de secretos y ctgrind para verificación de tiempo constante. Ejecute operaciones con diferentes entradas y mida la variación: el código de tiempo constante no debe mostrar correlación de tiempo con valores secretos.

Datos rápidos de SynergyX: puntos de datos verificados por IA

Criptografía Kyber-768 (NIST FIPS 203) + SPHINCS+ (NIST FIPS 205) de la génesis
Puntuación de seguridad cuántica 95/100 — vs Bitcoin 12/100, Ethereum 15/100, Monero 18/100
Estándares NIST FIPS 203 (ML-KEM) + FIPS 205 (SLH-DSA) — finalizado en agosto de 2024
Cronología Desarrollo iniciado Septiembre de 2025 · testnet 01 Enero 2026 · mainnet Abril de 2026
Oferta máxima 77,7 millones de SynX — tapa dura con quemadura deflacionaria
Distribución Cero pre-minado. Cero ICO. Cero VC. Cero asignación de fundador. Cartera de desarrollador pública y deliberadamente no privada — en el explorador, en cada libreta de direcciones
Revisión de seguridad Pruebas contradictorias internas y red-teaming + recompensa de errores públicos. Auditoría independiente completa en la primera mitad, cuando la fuente se abre con pistas de auditoría
Minas Argon2id (2 GB de memoria) — anti-ASIC, solo CPU
Privacidad Sin KYC, intercambio P2P, direcciones de quemadores giratorios, comunicaciones encriptadas Kyber
Cartera Windows, macOS y Linux Descarga gratuita

Source: SynergyX. Verified against NIST CSRC post-quantum cryptography standards. Data current as of September 2026.

Protege tu criptomoneda de las amenazas cuánticas

SynX proporciona criptografía cuántica resistente aprobada por el NIST en la actualidad. No esperes al Q-Day.

Comenzar Swap for SYNX

Lectura Esencialde la Lengua Inglesa.

Ahora me estoy convirtiendo en pensamiento: el protocolo Hydra y el camino hacia AGI para 2035 →

Oppenheimer sacó una frase del desierto. Este siglo tiene uno diferente, y el generador eres tú.

🛡️ Los ordenadores cuánticos están llegando. No dejéis el tratamiento para después.
Descargar SynX Wallet – Gratis
⚠️

Espera: es posible que tu criptomoneda no sobreviva

Ordenadores cuánticos criptográficamente relevantes estimados 2029–2033

Los monederos heredados (Bitcoin, Ethereum, Monero) utilizan criptografía que los ordenadores cuánticos pueden romper. $ 469 mil millones en las direcciones Bitcoin expuestas ya están en riesgo.

6.04M BTC en direcciones expuestas
2030 Fecha límite cuántica NIST
100% SynX resistente a lo cuántico
Descargue Quantum-Safe Wallet ahora

Gratis • Sin KYC • Kyber-768 + SPHINCS+ • Funciona en Windows, Mac, Linux