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
Maintainers
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:
EdDSAcon Ed25519 - Base64URL sin padding
- claves públicas SPKI PEM
- claves privadas PKCS#8 PEM
kid = base64url(SHA-256(SPKI DER))kides 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 testDominio JSON interoperable
Los helpers JSON v3 son deliberadamente estrictos para impedir coerciones silenciosas de JSON.stringify.
Se rechazan, entre otros:
NaN,Infinityy-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 decryptCCENC 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_unavailableEstabilidad 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 testLa 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.
