npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cross-crypto-ts

v3.0.0

Published

Cross-Crypto Protocol v3: JWE RSA-OAEP-256/A256GCM y JWS Ed25519 interoperable entre browser/JavaScript y Python.

Downloads

313

Readme

cross-crypto-ts

Implementación TypeScript/browser de Cross-Crypto Protocol v3.

Estado actual: 3.0.0. Release estable de Cross-Crypto Protocol v3.

Perfil criptográfico

  • JWE JSON Flattened: RSA-OAEP-256 + A256GCM
  • JWS JSON Flattened: EdDSA con Ed25519
  • Base64URL sin padding
  • claves públicas SPKI PEM
  • claves privadas PKCS#8 PEM
  • kid = base64url(SHA-256(SPKI DER))
  • kid es identidad criptográfica, no alias libre: debe decodificar 32 bytes y corresponder a la clave usada
  • CCENC v3 para blobs/archivos grandes

El core usa Web Crypto, Uint8Array y Blob. No depende de fs, Buffer, v8, node-forge ni APIs Node dentro de src/.

Runtime

  • browsers con las primitivas Web Crypto requeridas por Protocol v3;
  • validado en Chrome/Chromium y Safari/WebKit;
  • Electron/Chromium validado como evidencia adicional;
  • Firefox/Gecko no se declara probado hasta completar su gate propio;
  • Node.js >= 20 para ejecución/test del paquete ESM.

Instalación

Cuando el RC esté publicado:

npm install [email protected]

Desde este checkout:

npm install
npm test

Dominio JSON interoperable

Los helpers JSON v3 son deliberadamente estrictos para impedir coerciones silenciosas de JSON.stringify.

Se rechazan, entre otros:

  • NaN, Infinity y -Infinity;
  • enteros no seguros (!Number.isSafeInteger(...));
  • Date, Map, instancias de clases y otros objetos no planos;
  • propiedades Symbol, accessors y propiedades no enumerables;
  • surrogates Unicode aislados;
  • estructuras con más de 64 niveles o 100,000 nodos.

Para identificadores, cantidades decimales exactas o enteros fuera del rango seguro de JavaScript, usa strings y valida el dominio en la aplicación.

JavaScript ESM

El paquete publicado contiene JavaScript ESM; TypeScript no es obligatorio para consumirlo:

import {
  encryptJson,
  decryptJson,
  generateRsaKeyPair,
} from "cross-crypto-ts";

const rsa = await generateRsaKeyPair();
const envelope = await encryptJson({ hello: "world" }, rsa.publicKey);
const value = await decryptJson(envelope, rsa.privateKey);

En React/TypeScript se usa el mismo entry point y se obtienen además las declaraciones .d.ts.

Cifrar JSON

import {
  generateRsaKeyPair,
  encryptJson,
  decryptJson,
} from "cross-crypto-ts";

const rsa = await generateRsaKeyPair();

const envelope = await encryptJson(
  { message: "hola", amount: 42 },
  rsa.publicKey,
  { aad: "route:/api/example" }
);

const value = await decryptJson(
  envelope,
  rsa.privateKey,
  {
    expectedKeyId: rsa.kid,
    expectedAad: "route:/api/example",
  }
);

El navegador sólo necesita la clave pública RSA del destinatario para cifrar. No distribuyas una clave privada estática del backend al frontend.

Firmar y verificar

import {
  generateEd25519KeyPair,
  signJson,
  verifyJson,
} from "cross-crypto-ts";

const ed = await generateEd25519KeyPair();

const signed = await signJson(
  { operation: "example" },
  ed.privateKey,
  {
    keyId: ed.kid,
    signedAt: Math.floor(Date.now() / 1000),
  }
);

const verified = await verifyJson(
  signed,
  ed.publicKey,
  {
    expectedKeyId: ed.kid,
    maxAgeSeconds: 60,
  }
);

iat, exp, kid, ccv, typ y cty forman parte del protected header firmado. Alterarlos invalida la firma.

Bytes

const envelope = await encryptBytes(bytes, rsa.publicKey);
const result = await decryptBytes(envelope, rsa.privateKey, {
  expectedKeyId: rsa.kid,
});

result.plaintext;       // Uint8Array
result.protectedHeader; // autenticado al finalizar decrypt

CCENC v3

Para datos grandes en navegador:

const encryptedBlob = await encryptBlob(file, rsa.publicKey, {
  name: file.name,
  contentType: file.type || "application/octet-stream",
});

const { blob, header } = await decryptBlob(
  encryptedBlob,
  rsa.privateKey,
  { expectedKeyId: rsa.kid }
);

También existen encryptCcencBytes() y decryptCcencBytes().

CCENC usa chunks AES-256-GCM y un marcador final autenticado para detectar manipulación, reordenamiento, truncación y bytes añadidos después del final.

API principal

Claves

  • generateRsaKeyPair(bits = 3072)
  • generateEd25519KeyPair()
  • keyIdFromPublicKey(publicKeyPem)

Cifrado

  • encryptBytes() / decryptBytes()
  • encryptJson() / decryptJson()
  • encryptText() / decryptText()

Firmas

  • signBytes() / verifyBytes()
  • signJson() / verifyJson()
  • signText() / verifyText()
  • isValidSignature()

CCENC

  • encryptBlob() / decryptBlob()
  • encryptCcencBytes() / decryptCcencBytes()
  • readCcencHeader()

readJweProtectedHeader(), readJwsProtectedHeader() y readCcencHeader() leen metadata antes de autenticarla. Úsalos sólo para inspección/selección de clave. Una decisión de confianza debe esperar a decrypt/verify.

Errores

Los errores públicos usan CrossCryptoError con códigos como:

invalid_format
invalid_encoding
unsupported_algorithm
unsupported_version
invalid_key
key_mismatch
authentication_failed
signature_invalid
expired
not_yet_valid
payload_too_large
runtime_unavailable

Estabilidad de API 3.x

La superficie pública candidata a 3.0.0 está congelada y documentada en docs/API_STABILITY.md. El núcleo portable Python ↔ TypeScript comparte semántica; los adaptadores de archivo (Python) y Blob (browser) permanecen específicos del runtime.

Seguridad

Cross-Crypto no sustituye TLS, autenticación/autorización, protección frente a XSS, almacenamiento seguro de claves ni replay protection de negocio.

Consulta la especificación y SECURITY.md del bundle v3 antes de integrar.

Tests

npm test

La suite incluye tests locales y vectores producidos por Python. Las claves de test/fixtures son públicas y sólo sirven para conformidad.

Licencia

MIT

Runtimes soportados

La matriz objetivo y la política de compatibilidad están en docs/RUNTIME_SUPPORT.md. La CI prueba múltiples versiones y mantiene separados los conceptos “compatible por metadata” y “probado por matriz”.

Release 3.0.0

La preparación del release estable está documentada en:

3.0.0 es la release estable promovida después de completar los gates de release.