P-256 frente a secp256k1 rara vez es una elección libre: la curva suele venir con el ecosistema. Ambas son curvas de Weierstrass de 256 bits y orden primo, con unos 128 bits de seguridad y tamaños de clave y de firma idénticos, pero difieren en su origen, en las plataformas que las admiten y en las convenciones que se apoyan sobre ellas, y es al mover datos entre ambos mundos donde aparecen los errores.
De un vistazo
| P-256 (secp256r1, prime256v1) | secp256k1 | |
|---|---|---|
| Especificada en | NIST SP 800-186 §3.2.1.3, SEC 2 §2.4.2 | SEC 2 §2.4.1; SP 800-186, apéndice H.2, la permite para uso en cadenas de bloques |
| Ecuación | y² = x³ − 3x + b sobre p = 2²⁵⁶ − 2²²⁴ + 2¹⁹² + 2⁹⁶ − 1 | y² = x³ + 7 sobre p = 2²⁵⁶ − 2³² − 977 |
| Origen de los parámetros | b derivado de una semilla SHA-1 sin explicar | Coeficientes fijos y mínimos (al estilo de Koblitz) |
| Cofactor, seguridad | 1, unos 128 bits | 1, unos 128 bits |
| Claves y firmas | Clave privada de 32 bytes, clave pública de 33/65 bytes, firma en bruto de 64 bytes | Iguales |
| OID | 1.2.840.10045.3.1.7 | 1.3.132.0.10 |
| JOSE / COSE | ES256 / −7 | ES256K / −47 (RFC 8812) |
| Node.js 26 (OpenSSL 3.6.5), firmas / verificaciones por segundo | unas 68.800 / 27.200 | unas 6500 / 7200 |
| @noble/curves 2.3.0, firmas / verificaciones por segundo | unas 3800 / 870 | unas 3800 / 1180 |
| WebCrypto, TLS 1.3, WebAuthn | Sí | No |
| Secure Enclave de Apple, tarjetas PIV, la mayoría de los HSM | Sí | Rara vez (AWS KMS ofrece ECC_SECG_P256K1) |
| Usos habituales | Certificados TLS, llaves de acceso, JWT, identidad de dispositivos | Bitcoin, Ethereum, Nostr, la mayoría de las cadenas EVM |
Mediciones en un núcleo de un Apple M4 Max.
Origen y confianza
El NIST publicó P-256 en 1999 y la estandarizó en FIPS 186-2 (2000), y el SECG la estandarizó con el nombre secp256r1. Su número primo tiene una forma especial que permite una reducción rápida, y su coeficiente b se generó a partir de una semilla mediante SHA-1, como prescribía el procedimiento «verificablemente aleatorio» de la época. El origen de la semilla nunca se explicó, y eso, tras las revelaciones sobre Dual_EC_DRBG, llevó a algunos diseñadores a desconfiar de las curvas del NIST. Nunca se ha encontrado ningún ataque contra P-256 basado en esa semilla, y sigue siendo la curva más examinada de las que están en uso.
secp256k1 procede de SEC 2 (2000). Con a = 0 y b = 7 no hay nada que ocultar, y su estructura especial aporta un endomorfismo que se calcula de forma eficiente (el método GLV) y acelera la multiplicación escalar. Satoshi Nakamoto la eligió para Bitcoin en 2009, una elección poco habitual en aquel momento, y Ethereum siguió el mismo camino. NIST SP 800-186 (2023) permite explícitamente secp256k1 «para aplicaciones relacionadas con cadenas de bloques».
Ambas curvas tienen orden primo, así que no hay sutilezas con el cofactor, y ambas caen por igual ante el algoritmo de Shor.
Compatibilidad de plataformas y bibliotecas
Esta es la diferencia real. P-256 viene integrada en todo lo que gestiona las claves por ti: WebCrypto en todos los navegadores, las pilas TLS de todos los sistemas operativos, el Secure Enclave y CryptoKit de Apple, Android Keystore, TPM 2.0, las tarjetas inteligentes PIV y todos los KMS en la nube. Las llaves de acceso la usan de forma predeterminada, y los Baseline Requirements del CA/Browser Forum la permiten para los certificados de confianza pública.
secp256k1 no está en WebCrypto ni en TLS 1.3 (el RFC 8422 ya había declarado obsoleto su identificador en TLS 1.2), y las bibliotecas de propósito general la tratan como algo secundario. Por eso el software de cadenas de bloques se apoya en implementaciones dedicadas: libsecp256k1 de Bitcoin Core, de tiempo constante, y, en otros entornos, @noble/curves, k256 de Rust y go-ethereum/crypto de Go. Las billeteras de hardware la admiten; en los HSM empresariales depende del fabricante, y AWS KMS la ofrece como la especificación de clave ECC_SECG_P256K1, solo para firmar.
Rendimiento
Con tamaños iguales, la velocidad depende de la calidad de la implementación más que de la curva. OpenSSL incluye código ensamblador optimizado a mano para P-256 y código genérico para secp256k1, así que Node.js 26.10 (OpenSSL 3.6.5) firma unas diez veces más rápido con P-256: unas 68.800 firmas por segundo frente a 6500 en un núcleo de Apple M4 Max. En JavaScript puro el panorama se invierte ligeramente: @noble/curves 2.3.0 firma al mismo ritmo en ambas curvas y verifica secp256k1 aproximadamente un tercio más rápido, gracias al endomorfismo. libsecp256k1 es más rápida todavía. La lección: mide el rendimiento de la biblioteca que vas a distribuir, no el de la curva.
Convenciones que cambian
Las mismas matemáticas de ECDSA viajan con reglas distintas en cada mundo.
- Hash. P-256 se combina con SHA-256 (
ES256,ecdsa-with-SHA256). Bitcoin firma resúmenes de doble SHA-256; Ethereum firma resúmenes Keccak-256, que no son SHA3-256. - Codificación. X.509 y TLS usan DER; JOSE y WebCrypto usan
r‖sen bruto; Ethereum añade un byte de recuperaciónvpara un total de 65 bytes, y los mensajes firmados de Bitcoin anteponen un byte de encabezado. - Recuperación de la clave pública. Ethereum nunca envía claves públicas: la recuperación (
ecrecover) calcula la clave a partir de la firma y se compara la dirección. Los protocolos con P-256, en cambio, transmiten o certifican la clave. - Low-S. Toda firma ECDSA
(r, s)tiene una gemela(r, n − s). La política de retransmisión de Bitcoin y las reglas de transacción de Ethereum (EIP-2) solo aceptan la forma low-S; los verificadores genéricos de P-256 aceptan ambas. - Schnorr. Taproot añadió a Bitcoin las firmas Schnorr BIP-340 de 64 bytes con claves x-only de 32 bytes sobre secp256k1, que también usa Nostr. No existe ningún esquema Schnorr estándar sobre P-256.
La maleabilidad es fácil de demostrar con Node.js y su compatibilidad con secp256k1, que se apoya en OpenSSL:
import { generateKeyPairSync, sign, verify } from "node:crypto";
// Group order of secp256k1 (SEC 2 §2.4.1).
const n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n;
const { privateKey, publicKey } = generateKeyPairSync("ec", { namedCurve: "secp256k1" });
const message = Buffer.from("hello");
const raw = sign("sha256", message, { key: privateKey, dsaEncoding: "ieee-p1363" });
const r = raw.subarray(0, 32);
const s = BigInt("0x" + raw.subarray(32).toString("hex"));
const flipped = Buffer.concat([r, Buffer.from((n - s).toString(16).padStart(64, "0"), "hex")]);
const check = (sig) => verify("sha256", message, { key: publicKey, dsaEncoding: "ieee-p1363" }, sig);
console.log("(r, s) and (r, n - s) both verify:", check(raw) && check(flipped));
console.log("exactly one of them is low-S:", (s <= n / 2n) !== (n - s <= n / 2n));
(r, s) and (r, n - s) both verify: true
exactly one of them is low-S: true
OpenSSL ni produce ni exige low-S, así que las firmas generadas de esta forma deben normalizarse antes de que Bitcoin o Ethereum las acepten. El verificador de firmas de Ethereum señala los valores high-S.
Cuándo elegir cada una
- Web, TLS, llaves de acceso, JWT, claves de teléfonos y de otros dispositivos: P-256, porque las plataformas no ofrecen otra cosa en hardware.
- Bitcoin, Ethereum y cadenas EVM, Nostr: secp256k1, con las reglas de hash, codificación, recuperación y low-S de la cadena.
- Combinar ambas (por ejemplo, una billetera de contrato inteligente controlada por una llave de acceso): mantén cada curva en su carril. La actualización Fusaka de Ethereum (diciembre de 2025) añadió EIP-7951, un contrato precompilado de verificación de P-256 en la dirección
0x100que cuesta 6900 unidades de gas, y muchos rollups ofrecen el precompilado compatible RIP-7212, así que los contratos pueden verificar directamente las firmas de llaves de acceso. - Un protocolo nuevo con libertad de elección: ninguna de las dos; considera Ed25519 para claves en software o P-256 para claves respaldadas por hardware.
Notas de migración
Las claves no se pueden convertir de una curva a otra; cambiar de curva implica claves nuevas y, en las cadenas de bloques, direcciones nuevas.
- No reutilices material de clave entre curvas. Un secreto de 32 bytes es una clave privada válida en ambas curvas, pero las claves públicas resultantes no guardan ninguna relación; trátalo como una trampa, no como una ventaja.
- Al llevar la firma con secp256k1 a un HSM o un KMS, confirma que el tipo de clave existe, cuenta con una salida en DER, conviértela a
r‖sen bruto, normaliza a low-S y calcula tú mismo el ID de recuperación probando ambas paridades. - Al verificar firmas P-256 en un contrato EVM, usa una biblioteca verificada o un precompilado donde la cadena lo ofrezca; nunca implementes a mano la aritmética modular en Solidity.
- En JOSE, pasar de
ES256KaES256cambiaalg,crvy la clave; publica ambas claves con valores dekiddistintos durante la transición.
Referencias
- NIST SP 800-186, parámetros de dominio de curvas elípticas (§3.2.1.3 y apéndice H.2)
- SEC 2 v2, parámetros de dominio recomendados para curvas elípticas (§2.4.1, §2.4.2)
- FIPS 186-5, estándar de firma digital
- RFC 8812, ES256K y secp256k1 en JOSE y COSE
- BIP-340, firmas Schnorr para secp256k1
- BIP-146, LOW_S y EIP-2
- Referencia de las especificaciones de clave de AWS KMS