crypto.subtle es la interfaz criptográfica estándar de la plataforma web. Las mismas llamadas —generateKey, importKey, sign, verify, exportKey— funcionan en Chromium, Firefox y WebKit y en entornos de ejecución de servidor como Node.js, lo que la convierte en la opción natural para el código que debe ejecutarse en ambos lados. Solo existe en contextos seguros: en una página servida por http simple, crypto.subtle es undefined.
La especificación fija el formato de firma ECDSA en r‖s en bruto, 64 bytes en P-256, y la comprobación encontró exactamente eso en los cuatro motores. Eso coincide con JWS y JWT, así que los tokens ES256 no necesitan conversión, pero no coincide con OpenSSL, el SHA256withECDSA de Java, el SignASN1 de Go ni node:crypto, que usan todos DER ASN.1. Como una firma DER pasada a verify() devuelve un simple false en lugar de un error, la discrepancia parece una falsificación; convierte la firma con el conversor DER ⇄ en bruto o comprueba ambas formas en el verificador de firmas.
Las claves son la otra fuente habitual de fricción. importKey("spki") recibe bytes DER, nunca texto PEM; "raw" recibe el punto SEC1, y el punto comprimido lo aceptan Node.js, Chromium y Firefox pero lo rechaza WebKit, así que envía el punto sin comprimir si quieres código portable. Las claves privadas solo se importan como PKCS#8 DER o JWK: los archivos SEC1 EC PRIVATE KEY que OpenSSL escribe por defecto deben convertirse antes a PKCS#8, por ejemplo con el conversor de JWK.
La lista de curvas se limita a P-256, P-384 y P-521: secp256k1 y Brainpool lanzan NotSupportedError en todas partes, así que las claves de Bitcoin y Ethereum necesitan una biblioteca como @noble/curves. Ed25519 funciona en los cuatro motores; Ed448, solo en Node.js. La compatibilidad poscuántica es desigual: Node.js 24.22 implementa ML-DSA y ML-KEM con una advertencia de función experimental, Chromium 156 acepta ML-DSA y ML-KEM-768/1024 pero no ML-KEM-512, y Firefox 157 y WebKit 27.2 no tienen ninguno de los dos; detecta la compatibilidad antes de depender de ellos y prueba los algoritmos en la herramienta de firmas poscuánticas.
El ejemplo muestra el patrón portable: indica el hash en el objeto del algoritmo, importa las claves PEM de otros sistemas decodificándolas antes a DER y recuerda que la salida de 64 bytes debe envolverse en DER antes de que un verificador al estilo de OpenSSL pueda leerla.