Pular para o conteúdo
ecdsa.com

P-256 vs secp256k1: curvas de 256 bits, dois ecossistemas

A curva do NIST move a web, as chaves de acesso e o hardware seguro; a curva de Koblitz move o Bitcoin, o Ethereum e o Nostr. Mesmo tamanho, mesma força, regras diferentes em torno de cada uma.

P-256 vs secp256k1 raramente é uma escolha livre: a curva costuma vir junto com o ecossistema. As duas são curvas de Weierstrass de 256 bits e ordem prima, com cerca de 128 bits de segurança e chaves e assinaturas de tamanhos idênticos, mas diferem na origem, nas plataformas que oferecem suporte a elas e nas convenções construídas por cima delas, e é na passagem de dados entre os dois mundos que os bugs aparecem.

Visão geral

P-256 (secp256r1, prime256v1)secp256k1
Especificada emNIST SP 800-186 §3.2.1.3, SEC 2 §2.4.2SEC 2 §2.4.1; permitida pelo SP 800-186, apêndice H.2, para uso em blockchain
Equaçãoy² = x³ − 3x + b sobre p = 2²⁵⁶ − 2²²⁴ + 2¹⁹² + 2⁹⁶ − 1y² = x³ + 7 sobre p = 2²⁵⁶ − 2³² − 977
Origem dos parâmetrosb derivado de uma semente SHA-1 nunca explicadaCoeficientes fixos e mínimos (estilo Koblitz)
Cofator, segurança1, cerca de 128 bits1, cerca de 128 bits
Chaves e assinaturasChave privada de 32 bytes, chave pública de 33/65 bytes, assinatura bruta de 64 bytesIguais
OID1.2.840.10045.3.1.71.3.132.0.10
JOSE / COSEES256 / −7ES256K / −47 (RFC 8812)
Node.js 26 (OpenSSL 3.6.5), assinaturas / verificações por segundocerca de 68.800 / 27.200cerca de 6.500 / 7.200
@noble/curves 2.3.0, assinaturas / verificações por segundocerca de 3.800 / 870cerca de 3.800 / 1.180
WebCrypto, TLS 1.3, WebAuthnSimNão
Secure Enclave da Apple, cartões PIV, a maioria dos HSMsSimRaramente (o AWS KMS oferece ECC_SECG_P256K1)
Usada porCertificados TLS, chaves de acesso, JWTs, identidade de dispositivosBitcoin, Ethereum, Nostr, a maioria das cadeias EVM

Medições em um núcleo de um Apple M4 Max.

Origem e confiança

A P-256 foi publicada pelo NIST em 1999 e padronizada no FIPS 186-2 (2000) e, pelo SECG, como secp256r1. O primo dela tem uma forma especial que permite uma redução rápida, e o coeficiente b foi gerado a partir de uma semente por meio do SHA-1, como prescrevia o procedimento “verificavelmente aleatório” da época. A origem da semente nunca foi explicada, o que, depois das revelações sobre o Dual_EC_DRBG, levou alguns projetistas a desconfiar das curvas do NIST. Nenhum ataque à P-256 baseado nessa semente foi encontrado até hoje, e ela continua sendo a curva mais escrutinada entre as que estão em uso.

A secp256k1 vem do SEC 2 (2000). Com a = 0 e b = 7, não há nada a esconder, e a estrutura especial dela fornece um endomorfismo de cálculo eficiente (o método GLV) que acelera a multiplicação escalar. Satoshi Nakamoto a escolheu para o Bitcoin em 2009, uma escolha incomum na época, e o Ethereum seguiu o mesmo caminho. O NIST SP 800-186 (2023) permite explicitamente a secp256k1 “em aplicações relacionadas a blockchain”.

As duas curvas têm ordem prima, então não há sutilezas de cofator, e as duas caem da mesma forma diante do algoritmo de Shor.

Suporte em plataformas e bibliotecas

Esta é a diferença real. A P-256 está embutida em tudo o que gerencia chaves para você: o WebCrypto em todos os navegadores, as pilhas TLS de todos os sistemas operacionais, o Secure Enclave e o CryptoKit da Apple, o Android Keystore, o TPM 2.0, os cartões inteligentes PIV e todos os KMS de nuvem. As chaves de acesso a usam por padrão, e os Baseline Requirements do CA/Browser Forum a permitem em certificados publicamente confiáveis.

A secp256k1 não está no WebCrypto nem no TLS 1.3 (a RFC 8422 já tinha descontinuado o identificador dela no TLS 1.2), e as bibliotecas de uso geral a tratam como algo secundário. Por isso, o software de blockchain depende de implementações dedicadas: a libsecp256k1 do Bitcoin Core, de tempo constante, e, fora dele, @noble/curves, o k256 do Rust e o go-ethereum/crypto do Go. As carteiras de hardware oferecem suporte a ela; nos HSMs corporativos isso varia, e o AWS KMS a oferece como a especificação de chave ECC_SECG_P256K1, apenas para assinatura.

Desempenho

Com tamanhos iguais, a velocidade depende da qualidade da implementação, e não da curva. O OpenSSL tem assembly otimizado à mão para a P-256 e código genérico para a secp256k1, então o Node.js 26.10 (OpenSSL 3.6.5) assina cerca de dez vezes mais rápido com a P-256: cerca de 68.800 contra 6.500 assinaturas por segundo em um núcleo do Apple M4 Max. Em JavaScript puro, o quadro se inverte um pouco: a @noble/curves 2.3.0 assina na mesma taxa nas duas curvas e verifica a secp256k1 cerca de um terço mais rápido, graças ao endomorfismo. A libsecp256k1 é ainda mais rápida. A lição: faça o benchmark da biblioteca que você vai colocar em produção, não da curva.

Convenções que diferem

A mesma matemática do ECDSA vem acompanhada de regras diferentes em cada mundo.

  • Hash. A P-256 é combinada com SHA-256 (ES256, ecdsa-with-SHA256). O Bitcoin assina digests de SHA-256 duplo; o Ethereum assina digests Keccak-256, que não são SHA3-256.
  • Codificação. O X.509 e o TLS usam DER; o JOSE e o WebCrypto usam r‖s bruto; o Ethereum acrescenta um byte de recuperação v, chegando a 65 bytes no total, e as mensagens assinadas do Bitcoin colocam um byte de cabeçalho na frente.
  • Recuperação da chave pública. O Ethereum nunca envia chaves públicas: a recuperação (ecrecover) calcula a chave a partir da assinatura, e o endereço é comparado. Os protocolos com P-256, em vez disso, transmitem ou certificam a chave.
  • Low-S. Toda assinatura ECDSA (r, s) tem uma gêmea (r, n − s). A política de retransmissão do Bitcoin e as regras de transação do Ethereum (EIP-2) aceitam apenas a forma low-S; verificadores genéricos de P-256 aceitam as duas.
  • Schnorr. O Taproot do Bitcoin acrescentou assinaturas Schnorr BIP-340 de 64 bytes, com chaves x-only de 32 bytes, na secp256k1, também usadas pelo Nostr. Não existe um esquema Schnorr padronizado na P-256.

A maleabilidade é fácil de demonstrar com o Node.js e o suporte dele à secp256k1, baseado no OpenSSL:

Node.js 26: (r, s) e (r, n − s) passam na verificação na secp256k1
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));
Saída
(r, s) and (r, n - s) both verify: true
exactly one of them is low-S: true

O OpenSSL não produz nem exige low-S, então assinaturas feitas assim precisam ser normalizadas antes que o Bitcoin ou o Ethereum as aceitem. O verificador de assinaturas Ethereum sinaliza valores high-S.

Quando escolher cada uma

  • Web, TLS, chaves de acesso, JWTs, chaves de celulares e de dispositivos: P-256, porque as plataformas não oferecem outra coisa em hardware.
  • Bitcoin, Ethereum e cadeias EVM, Nostr: secp256k1, com as regras de hash, codificação, recuperação e low-S da cadeia.
  • Ponte entre as duas (por exemplo, uma carteira de contrato inteligente controlada por uma chave de acesso): mantenha cada curva no seu próprio mundo. A atualização Fusaka do Ethereum (dezembro de 2025) acrescentou a EIP-7951, um contrato pré-compilado de verificação de P-256 no endereço 0x100, com custo de 6.900 unidades de gás, e muitos rollups oferecem o pré-compilado compatível RIP-7212, então os contratos podem verificar assinaturas de chaves de acesso diretamente.
  • Um protocolo novo, com escolha livre: nenhuma das duas; considere o Ed25519 para chaves em software ou a P-256 para chaves protegidas por hardware.

Notas de migração

Não é possível converter chaves de uma curva para a outra; trocar de curva significa chaves novas e, nas blockchains, endereços novos.

  1. Não reutilize material de chave entre curvas. Um segredo de 32 bytes é uma chave privada válida nas duas curvas, mas as chaves públicas resultantes não têm relação entre si; trate isso como uma armadilha, não como um recurso.
  2. Ao levar a assinatura com secp256k1 para um HSM ou KMS, confirme que o tipo de chave existe, espere saída em DER, converta para r‖s bruto, normalize para low-S e calcule você mesmo o ID de recuperação testando as duas paridades.
  3. Ao verificar assinaturas P-256 em um contrato EVM, use uma biblioteca verificada ou um pré-compilado, onde a cadeia oferecer um; nunca implemente aritmética modular à mão em Solidity.
  4. No JOSE, trocar ES256K por ES256 muda alg, crv e a chave; publique as duas chaves com valores de kid distintos durante a transição.

Referências

Todas as comparações