@pqc-sdk/core 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -287,7 +287,7 @@ async function verify(data, signature, publicKey, options) {
287
287
  }
288
288
 
289
289
  // src/index.ts
290
- var version = "0.0.1";
290
+ var version = "0.1.1";
291
291
  var SUPPORTED_ALGORITHMS = ["ml-kem-768", "ml-dsa-65"];
292
292
  var pqc = {
293
293
  keys: { generate, serialize, deserialize },
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/encrypt.ts","../src/algorithms.ts","../src/errors.ts","../src/keys.ts","../src/base64url.ts","../src/sign.ts"],"sourcesContent":["import { encrypt, decrypt } from './encrypt.js';\nimport { deserialize, generate, serialize } from './keys.js';\nimport { sign, verify } from './sign.js';\n\nexport { PqcError, type PqcErrorCode } from './errors.js';\nexport type { GenerateOptions } from './keys.js';\nexport type {\n Algorithm,\n KemAlgorithm,\n KeyPair,\n KeyUse,\n PqcKey,\n PublicKey,\n SecretKey,\n SignatureAlgorithm,\n SignatureOptions,\n} from './types.js';\nexport { encrypt, decrypt, sign, verify, generate, serialize, deserialize };\n\n/**\n * Versión del SDK.\n *\n * @example\n * ```ts\n * import { version } from '@pqc-sdk/core';\n *\n * console.log(version); // \"0.0.1\"\n * ```\n */\nexport const version = '0.0.1';\n\n/**\n * Algoritmos PQC implementados (FIPS 203 y FIPS 204).\n *\n * @example\n * ```ts\n * import { SUPPORTED_ALGORITHMS } from '@pqc-sdk/core';\n *\n * SUPPORTED_ALGORITHMS.includes('ml-kem-768'); // true\n * ```\n */\nexport const SUPPORTED_ALGORITHMS = ['ml-kem-768', 'ml-dsa-65'] as const;\n\nexport type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];\n\n/**\n * Punto de entrada del SDK: cifrado híbrido post-cuántico y firmas digitales\n * con defaults seguros, sin configuración.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * // Cifrado (ML-KEM-768 + AES-256-GCM)\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('hola', pair.publicKey);\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n *\n * // Firmas (ML-DSA-65)\n * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign('documento', signer.secretKey);\n * await pqc.verify('documento', signature, signer.publicKey); // true\n * ```\n */\nexport const pqc = {\n keys: { generate, serialize, deserialize },\n encrypt,\n decrypt,\n sign,\n verify,\n} as const;\n","import { gcm } from '@noble/ciphers/aes.js';\nimport { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { KEM_ALGORITHMS, requireKey } from './algorithms.js';\nimport { PqcError } from './errors.js';\nimport type { PublicKey, SecretKey } from './types.js';\n\nconst FORMAT_VERSION = 1;\nconst NONCE_LENGTH = 12;\nconst GCM_TAG_LENGTH = 16;\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\n/**\n * Cifrado híbrido: encapsula un secreto con ML-KEM-768 (FIPS 203) y cifra los\n * datos con AES-256-GCM usando ese secreto. El resultado es un único\n * `Uint8Array` autocontenido que solo {@link decrypt} puede abrir.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('dato sensible', pair.publicKey);\n * ```\n */\nexport async function encrypt(\n data: Uint8Array | string,\n publicKey: PublicKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(publicKey, 'kem', 'public', 'encrypt');\n const plaintext = toBytes(data);\n\n const { cipherText, sharedSecret } = spec.kem.encapsulate(publicKey.bytes);\n const nonce = randomBytes(NONCE_LENGTH);\n const sealed = gcm(sharedSecret, nonce).encrypt(plaintext);\n\n const out = new Uint8Array(2 + cipherText.length + nonce.length + sealed.length);\n out[0] = FORMAT_VERSION;\n out[1] = spec.headerId;\n out.set(cipherText, 2);\n out.set(nonce, 2 + cipherText.length);\n out.set(sealed, 2 + cipherText.length + nonce.length);\n return Promise.resolve(out);\n}\n\n/**\n * Descifra un ciphertext producido por {@link encrypt}. Si el ciphertext fue\n * manipulado o la key no corresponde, lanza {@link PqcError} con código\n * `DECRYPTION_FAILED` — nunca devuelve datos corruptos.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n * new TextDecoder().decode(plaintext);\n * ```\n */\nexport async function decrypt(\n ciphertext: Uint8Array,\n secretKey: SecretKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'kem', 'secret', 'decrypt');\n\n const minLength = 2 + spec.ciphertextLength + NONCE_LENGTH + GCM_TAG_LENGTH;\n if (ciphertext.length < minLength) {\n throw new PqcError('INVALID_CIPHERTEXT', 'Ciphertext truncado o no producido por pqc.encrypt');\n }\n if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {\n throw new PqcError(\n 'INVALID_CIPHERTEXT',\n 'Header desconocido: el ciphertext no corresponde a esta versión o algoritmo',\n );\n }\n\n const kemCiphertext = ciphertext.subarray(2, 2 + spec.ciphertextLength);\n const nonce = ciphertext.subarray(\n 2 + spec.ciphertextLength,\n 2 + spec.ciphertextLength + NONCE_LENGTH,\n );\n const sealed = ciphertext.subarray(2 + spec.ciphertextLength + NONCE_LENGTH);\n\n const sharedSecret = spec.kem.decapsulate(kemCiphertext, secretKey.bytes);\n try {\n return Promise.resolve(gcm(sharedSecret, nonce).decrypt(sealed));\n } catch {\n throw new PqcError(\n 'DECRYPTION_FAILED',\n 'No se pudo descifrar: ciphertext manipulado o secret key incorrecta',\n );\n }\n}\n\n/** Algoritmos KEM disponibles, exportado para introspección. */\nexport const KEM_NAMES = Object.keys(KEM_ALGORITHMS);\n","import { ml_dsa65 } from '@noble/post-quantum/ml-dsa.js';\nimport { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KemAlgorithm, KeyUse, PqcKey, SignatureAlgorithm } from './types.js';\n\ninterface AlgorithmSpec {\n readonly seedLength: number;\n readonly publicKeyLength: number;\n readonly secretKeyLength: number;\n}\n\nexport interface KemSpec extends AlgorithmSpec {\n readonly kind: 'kem';\n readonly headerId: number;\n readonly ciphertextLength: number;\n readonly kem: typeof ml_kem768;\n}\n\nexport interface SignerSpec extends AlgorithmSpec {\n readonly kind: 'signer';\n readonly signatureLength: number;\n readonly signer: typeof ml_dsa65;\n}\n\nexport const KEM_ALGORITHMS: Record<KemAlgorithm, KemSpec> = {\n 'ml-kem-768': {\n kind: 'kem',\n headerId: 1,\n kem: ml_kem768,\n seedLength: 64,\n publicKeyLength: 1184,\n secretKeyLength: 2400,\n ciphertextLength: 1088,\n },\n};\n\nexport const SIGNATURE_ALGORITHMS: Record<SignatureAlgorithm, SignerSpec> = {\n 'ml-dsa-65': {\n kind: 'signer',\n signer: ml_dsa65,\n seedLength: 32,\n publicKeyLength: 1952,\n secretKeyLength: 4032,\n signatureLength: 3309,\n },\n};\n\nexport const ALGORITHMS: Record<Algorithm, KemSpec | SignerSpec> = {\n ...KEM_ALGORITHMS,\n ...SIGNATURE_ALGORITHMS,\n};\n\nexport function getAlgorithm(algorithm: string): KemSpec | SignerSpec {\n const spec = (ALGORITHMS as Record<string, KemSpec | SignerSpec>)[algorithm];\n if (!spec) {\n throw new PqcError('UNSUPPORTED_ALGORITHM', `Algoritmo no soportado: ${algorithm}`);\n }\n return spec;\n}\n\nexport function keyLengthFor(spec: KemSpec | SignerSpec, use: KeyUse): number {\n return use === 'public' ? spec.publicKeyLength : spec.secretKeyLength;\n}\n\n/** Valida algoritmo, uso y longitud de una key antes de operar con ella. */\nexport function requireKey<K extends 'kem' | 'signer'>(\n key: PqcKey,\n kind: K,\n use: KeyUse,\n operation: string,\n): K extends 'kem' ? KemSpec : SignerSpec {\n const spec = getAlgorithm(key.algorithm);\n if (spec.kind !== kind) {\n throw new PqcError(\n 'WRONG_ALGORITHM',\n `${operation} requiere una key ${kind === 'kem' ? 'ML-KEM' : 'ML-DSA'}, recibió ${key.algorithm}`,\n );\n }\n if (key.use !== use) {\n throw new PqcError('WRONG_KEY_USE', `${operation} requiere la key ${use}, recibió ${key.use}`);\n }\n if (key.bytes.length !== keyLengthFor(spec, use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${key.algorithm} ${use} con longitud inválida: ${key.bytes.length}`,\n );\n }\n return spec as K extends 'kem' ? KemSpec : SignerSpec;\n}\n","/** Códigos de error que puede emitir el SDK. */\nexport type PqcErrorCode =\n | 'UNSUPPORTED_ALGORITHM'\n | 'WRONG_ALGORITHM'\n | 'WRONG_KEY_USE'\n | 'INVALID_KEY'\n | 'INVALID_SERIALIZED_KEY'\n | 'INVALID_CIPHERTEXT'\n | 'DECRYPTION_FAILED';\n\n/**\n * Error tipado del SDK. Toda falla esperable expone un `code` estable para\n * manejarla programáticamente sin parsear mensajes.\n *\n * @example\n * ```ts\n * import { PqcError, pqc } from '@pqc-sdk/core';\n *\n * try {\n * await pqc.decrypt(ciphertext, secretKey);\n * } catch (error) {\n * if (error instanceof PqcError && error.code === 'DECRYPTION_FAILED') {\n * // ciphertext manipulado o key incorrecta\n * }\n * }\n * ```\n */\nexport class PqcError extends Error {\n readonly code: PqcErrorCode;\n\n constructor(code: PqcErrorCode, message: string) {\n super(message);\n this.name = 'PqcError';\n this.code = code;\n }\n}\n","import { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { getAlgorithm, keyLengthFor } from './algorithms.js';\nimport { fromBase64Url, toBase64Url } from './base64url.js';\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KeyPair, PqcKey } from './types.js';\n\nconst SERIAL_PREFIX = 'pqcv1';\n\n/** Opciones de {@link generate}. */\nexport interface GenerateOptions<A extends Algorithm = Algorithm> {\n /** Algoritmo del par. Default: `'ml-kem-768'` (cifrado). */\n readonly algorithm?: A;\n}\n\n/**\n * Genera un par de keys post-cuánticas. Sin opciones genera ML-KEM-768,\n * listo para `pqc.encrypt`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const encryption = await pqc.keys.generate();\n * const signing = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * ```\n */\nexport async function generate(): Promise<KeyPair<'ml-kem-768'>>;\nexport async function generate<A extends Algorithm>(\n options: GenerateOptions<A> & { algorithm: A },\n): Promise<KeyPair<A>>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair> {\n const algorithm = options?.algorithm ?? 'ml-kem-768';\n const spec = getAlgorithm(algorithm);\n return Promise.resolve(generateKeyPairFromSeed(algorithm, randomBytes(spec.seedLength)));\n}\n\n/**\n * Generación determinística a partir de una seed. Uso interno y de tests\n * (vectores NIST). Para uso normal preferir {@link generate}.\n */\nexport function generateKeyPairFromSeed(algorithm: Algorithm, seed: Uint8Array): KeyPair {\n const spec = getAlgorithm(algorithm);\n if (seed.length !== spec.seedLength) {\n throw new PqcError(\n 'INVALID_KEY',\n `Seed de ${algorithm} debe medir ${spec.seedLength} bytes, recibió ${seed.length}`,\n );\n }\n const material = spec.kind === 'kem' ? spec.kem.keygen(seed) : spec.signer.keygen(seed);\n return {\n algorithm,\n publicKey: { algorithm, use: 'public', bytes: material.publicKey },\n secretKey: { algorithm, use: 'secret', bytes: material.secretKey },\n };\n}\n\n/**\n * Serializa una key a un string portable: `pqcv1.<algoritmo>.<uso>.<base64url>`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const token = pqc.keys.serialize(pair.publicKey);\n * // \"pqcv1.ml-kem-768.public.h1q3…\"\n * ```\n */\nexport function serialize(key: PqcKey): string {\n const spec = getAlgorithm(key.algorithm);\n if (key.bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError('INVALID_KEY', `Key ${key.algorithm} ${key.use} con longitud inválida`);\n }\n return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;\n}\n\n/**\n * Reconstruye una key desde el formato de {@link serialize}. Valida versión,\n * algoritmo, uso y longitud; ante cualquier problema lanza {@link PqcError}\n * con código `INVALID_SERIALIZED_KEY` o `INVALID_KEY`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const publicKey = pqc.keys.deserialize(tokenRecibidoDelCliente);\n * const ciphertext = await pqc.encrypt(payload, publicKey);\n * ```\n */\nexport function deserialize(serialized: string): PqcKey {\n const parts = serialized.split('.');\n if (parts.length !== 4 || parts[0] !== SERIAL_PREFIX) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n 'Formato esperado: pqcv1.<algoritmo>.<uso>.<base64url>',\n );\n }\n const [, algorithm, use, encoded] = parts as [string, string, string, string];\n const spec = getAlgorithm(algorithm);\n if (use !== 'public' && use !== 'secret') {\n throw new PqcError('INVALID_SERIALIZED_KEY', `Uso de key desconocido: ${use}`);\n }\n let bytes: Uint8Array;\n try {\n bytes = fromBase64Url(encoded);\n } catch (cause) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n cause instanceof Error ? cause.message : 'base64url inválido',\n );\n }\n const key: PqcKey = { algorithm: algorithm as Algorithm, use, bytes };\n if (bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${algorithm} ${use} debe medir ${keyLengthFor(spec, key.use)} bytes, midió ${bytes.length}`,\n );\n }\n return key;\n}\n","const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\nconst CHAR_TO_VALUE = new Map<string, number>([...ALPHABET].map((c, i) => [c, i]));\n\n/** Codifica bytes a base64url sin padding. Implementación pura, sin Buffer/btoa. */\nexport function toBase64Url(bytes: Uint8Array): string {\n let out = '';\n for (let i = 0; i < bytes.length; i += 3) {\n const b0 = bytes[i]!;\n const b1 = bytes[i + 1];\n const b2 = bytes[i + 2];\n out += ALPHABET[b0 >> 2]!;\n out += ALPHABET[((b0 & 0x03) << 4) | ((b1 ?? 0) >> 4)]!;\n if (b1 !== undefined) out += ALPHABET[((b1 & 0x0f) << 2) | ((b2 ?? 0) >> 6)]!;\n if (b2 !== undefined) out += ALPHABET[b2 & 0x3f]!;\n }\n return out;\n}\n\n/** Decodifica base64url sin padding. Lanza TypeError ante caracteres inválidos. */\nexport function fromBase64Url(encoded: string): Uint8Array {\n if (encoded.length % 4 === 1) {\n throw new TypeError('base64url inválido: longitud imposible');\n }\n const out = new Uint8Array(Math.floor((encoded.length * 3) / 4));\n let outIndex = 0;\n let buffer = 0;\n let bits = 0;\n for (const char of encoded) {\n const value = CHAR_TO_VALUE.get(char);\n if (value === undefined) {\n throw new TypeError(`base64url inválido: carácter ${JSON.stringify(char)}`);\n }\n buffer = (buffer << 6) | value;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out[outIndex++] = (buffer >> bits) & 0xff;\n }\n }\n return out;\n}\n","import { requireKey } from './algorithms.js';\nimport type { PublicKey, SecretKey, SignatureOptions } from './types.js';\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\nfunction toNobleOptions(options?: SignatureOptions): { context: Uint8Array } | undefined {\n return options?.context ? { context: options.context } : undefined;\n}\n\n/**\n * Firma datos con ML-DSA-65 (FIPS 204), modo hedged (firma aleatorizada,\n * el default del estándar). Devuelve la firma de 3309 bytes.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign(documento, pair.secretKey);\n * ```\n */\nexport async function sign(\n data: Uint8Array | string,\n secretKey: SecretKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'signer', 'secret', 'sign');\n return Promise.resolve(spec.signer.sign(toBytes(data), secretKey.bytes, toNobleOptions(options)));\n}\n\n/**\n * Verifica una firma ML-DSA-65. Devuelve `false` ante firmas inválidas o\n * malformadas (nunca lanza por una firma corrupta); solo lanza si la key\n * no es ML-DSA.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const valid = await pqc.verify(documento, signature, pair.publicKey);\n * if (!valid) throw new Error('firma inválida');\n * ```\n */\nexport async function verify(\n data: Uint8Array | string,\n signature: Uint8Array,\n publicKey: PublicKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<boolean> {\n const spec = requireKey(publicKey, 'signer', 'public', 'verify');\n try {\n return Promise.resolve(\n spec.signer.verify(signature, toBytes(data), publicKey.bytes, toNobleOptions(options)),\n );\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["import_utils","utf8","toBytes"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/encrypt.ts","../src/algorithms.ts","../src/errors.ts","../src/keys.ts","../src/base64url.ts","../src/sign.ts"],"sourcesContent":["import { encrypt, decrypt } from './encrypt.js';\nimport { deserialize, generate, serialize } from './keys.js';\nimport { sign, verify } from './sign.js';\n\nexport { PqcError, type PqcErrorCode } from './errors.js';\nexport type { GenerateOptions } from './keys.js';\nexport type {\n Algorithm,\n KemAlgorithm,\n KeyPair,\n KeyUse,\n PqcKey,\n PublicKey,\n SecretKey,\n SignatureAlgorithm,\n SignatureOptions,\n} from './types.js';\nexport { encrypt, decrypt, sign, verify, generate, serialize, deserialize };\n\n// Inyectada en build time desde el package.json (`define` en tsup.config.ts y vitest.config.ts).\ndeclare const __PQC_CORE_VERSION__: string;\n\n/**\n * Versión del SDK.\n *\n * @example\n * ```ts\n * import { version } from '@pqc-sdk/core';\n *\n * console.log(version); // p. ej. \"0.1.0\"\n * ```\n */\nexport const version = __PQC_CORE_VERSION__;\n\n/**\n * Algoritmos PQC implementados (FIPS 203 y FIPS 204).\n *\n * @example\n * ```ts\n * import { SUPPORTED_ALGORITHMS } from '@pqc-sdk/core';\n *\n * SUPPORTED_ALGORITHMS.includes('ml-kem-768'); // true\n * ```\n */\nexport const SUPPORTED_ALGORITHMS = ['ml-kem-768', 'ml-dsa-65'] as const;\n\nexport type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];\n\n/**\n * Punto de entrada del SDK: cifrado híbrido post-cuántico y firmas digitales\n * con defaults seguros, sin configuración.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * // Cifrado (ML-KEM-768 + AES-256-GCM)\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('hola', pair.publicKey);\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n *\n * // Firmas (ML-DSA-65)\n * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign('documento', signer.secretKey);\n * await pqc.verify('documento', signature, signer.publicKey); // true\n * ```\n */\nexport const pqc = {\n keys: { generate, serialize, deserialize },\n encrypt,\n decrypt,\n sign,\n verify,\n} as const;\n","import { gcm } from '@noble/ciphers/aes.js';\nimport { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { KEM_ALGORITHMS, requireKey } from './algorithms.js';\nimport { PqcError } from './errors.js';\nimport type { PublicKey, SecretKey } from './types.js';\n\nconst FORMAT_VERSION = 1;\nconst NONCE_LENGTH = 12;\nconst GCM_TAG_LENGTH = 16;\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\n/**\n * Cifrado híbrido: encapsula un secreto con ML-KEM-768 (FIPS 203) y cifra los\n * datos con AES-256-GCM usando ese secreto. El resultado es un único\n * `Uint8Array` autocontenido que solo {@link decrypt} puede abrir.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('dato sensible', pair.publicKey);\n * ```\n */\nexport async function encrypt(\n data: Uint8Array | string,\n publicKey: PublicKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(publicKey, 'kem', 'public', 'encrypt');\n const plaintext = toBytes(data);\n\n const { cipherText, sharedSecret } = spec.kem.encapsulate(publicKey.bytes);\n const nonce = randomBytes(NONCE_LENGTH);\n const sealed = gcm(sharedSecret, nonce).encrypt(plaintext);\n\n const out = new Uint8Array(2 + cipherText.length + nonce.length + sealed.length);\n out[0] = FORMAT_VERSION;\n out[1] = spec.headerId;\n out.set(cipherText, 2);\n out.set(nonce, 2 + cipherText.length);\n out.set(sealed, 2 + cipherText.length + nonce.length);\n return Promise.resolve(out);\n}\n\n/**\n * Descifra un ciphertext producido por {@link encrypt}. Si el ciphertext fue\n * manipulado o la key no corresponde, lanza {@link PqcError} con código\n * `DECRYPTION_FAILED` — nunca devuelve datos corruptos.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n * new TextDecoder().decode(plaintext);\n * ```\n */\nexport async function decrypt(\n ciphertext: Uint8Array,\n secretKey: SecretKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'kem', 'secret', 'decrypt');\n\n const minLength = 2 + spec.ciphertextLength + NONCE_LENGTH + GCM_TAG_LENGTH;\n if (ciphertext.length < minLength) {\n throw new PqcError('INVALID_CIPHERTEXT', 'Ciphertext truncado o no producido por pqc.encrypt');\n }\n if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {\n throw new PqcError(\n 'INVALID_CIPHERTEXT',\n 'Header desconocido: el ciphertext no corresponde a esta versión o algoritmo',\n );\n }\n\n const kemCiphertext = ciphertext.subarray(2, 2 + spec.ciphertextLength);\n const nonce = ciphertext.subarray(\n 2 + spec.ciphertextLength,\n 2 + spec.ciphertextLength + NONCE_LENGTH,\n );\n const sealed = ciphertext.subarray(2 + spec.ciphertextLength + NONCE_LENGTH);\n\n const sharedSecret = spec.kem.decapsulate(kemCiphertext, secretKey.bytes);\n try {\n return Promise.resolve(gcm(sharedSecret, nonce).decrypt(sealed));\n } catch {\n throw new PqcError(\n 'DECRYPTION_FAILED',\n 'No se pudo descifrar: ciphertext manipulado o secret key incorrecta',\n );\n }\n}\n\n/** Algoritmos KEM disponibles, exportado para introspección. */\nexport const KEM_NAMES = Object.keys(KEM_ALGORITHMS);\n","import { ml_dsa65 } from '@noble/post-quantum/ml-dsa.js';\nimport { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KemAlgorithm, KeyUse, PqcKey, SignatureAlgorithm } from './types.js';\n\ninterface AlgorithmSpec {\n readonly seedLength: number;\n readonly publicKeyLength: number;\n readonly secretKeyLength: number;\n}\n\nexport interface KemSpec extends AlgorithmSpec {\n readonly kind: 'kem';\n readonly headerId: number;\n readonly ciphertextLength: number;\n readonly kem: typeof ml_kem768;\n}\n\nexport interface SignerSpec extends AlgorithmSpec {\n readonly kind: 'signer';\n readonly signatureLength: number;\n readonly signer: typeof ml_dsa65;\n}\n\nexport const KEM_ALGORITHMS: Record<KemAlgorithm, KemSpec> = {\n 'ml-kem-768': {\n kind: 'kem',\n headerId: 1,\n kem: ml_kem768,\n seedLength: 64,\n publicKeyLength: 1184,\n secretKeyLength: 2400,\n ciphertextLength: 1088,\n },\n};\n\nexport const SIGNATURE_ALGORITHMS: Record<SignatureAlgorithm, SignerSpec> = {\n 'ml-dsa-65': {\n kind: 'signer',\n signer: ml_dsa65,\n seedLength: 32,\n publicKeyLength: 1952,\n secretKeyLength: 4032,\n signatureLength: 3309,\n },\n};\n\nexport const ALGORITHMS: Record<Algorithm, KemSpec | SignerSpec> = {\n ...KEM_ALGORITHMS,\n ...SIGNATURE_ALGORITHMS,\n};\n\nexport function getAlgorithm(algorithm: string): KemSpec | SignerSpec {\n const spec = (ALGORITHMS as Record<string, KemSpec | SignerSpec>)[algorithm];\n if (!spec) {\n throw new PqcError('UNSUPPORTED_ALGORITHM', `Algoritmo no soportado: ${algorithm}`);\n }\n return spec;\n}\n\nexport function keyLengthFor(spec: KemSpec | SignerSpec, use: KeyUse): number {\n return use === 'public' ? spec.publicKeyLength : spec.secretKeyLength;\n}\n\n/** Valida algoritmo, uso y longitud de una key antes de operar con ella. */\nexport function requireKey<K extends 'kem' | 'signer'>(\n key: PqcKey,\n kind: K,\n use: KeyUse,\n operation: string,\n): K extends 'kem' ? KemSpec : SignerSpec {\n const spec = getAlgorithm(key.algorithm);\n if (spec.kind !== kind) {\n throw new PqcError(\n 'WRONG_ALGORITHM',\n `${operation} requiere una key ${kind === 'kem' ? 'ML-KEM' : 'ML-DSA'}, recibió ${key.algorithm}`,\n );\n }\n if (key.use !== use) {\n throw new PqcError('WRONG_KEY_USE', `${operation} requiere la key ${use}, recibió ${key.use}`);\n }\n if (key.bytes.length !== keyLengthFor(spec, use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${key.algorithm} ${use} con longitud inválida: ${key.bytes.length}`,\n );\n }\n return spec as K extends 'kem' ? KemSpec : SignerSpec;\n}\n","/** Códigos de error que puede emitir el SDK. */\nexport type PqcErrorCode =\n | 'UNSUPPORTED_ALGORITHM'\n | 'WRONG_ALGORITHM'\n | 'WRONG_KEY_USE'\n | 'INVALID_KEY'\n | 'INVALID_SERIALIZED_KEY'\n | 'INVALID_CIPHERTEXT'\n | 'DECRYPTION_FAILED';\n\n/**\n * Error tipado del SDK. Toda falla esperable expone un `code` estable para\n * manejarla programáticamente sin parsear mensajes.\n *\n * @example\n * ```ts\n * import { PqcError, pqc } from '@pqc-sdk/core';\n *\n * try {\n * await pqc.decrypt(ciphertext, secretKey);\n * } catch (error) {\n * if (error instanceof PqcError && error.code === 'DECRYPTION_FAILED') {\n * // ciphertext manipulado o key incorrecta\n * }\n * }\n * ```\n */\nexport class PqcError extends Error {\n readonly code: PqcErrorCode;\n\n constructor(code: PqcErrorCode, message: string) {\n super(message);\n this.name = 'PqcError';\n this.code = code;\n }\n}\n","import { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { getAlgorithm, keyLengthFor } from './algorithms.js';\nimport { fromBase64Url, toBase64Url } from './base64url.js';\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KeyPair, PqcKey } from './types.js';\n\nconst SERIAL_PREFIX = 'pqcv1';\n\n/** Opciones de {@link generate}. */\nexport interface GenerateOptions<A extends Algorithm = Algorithm> {\n /** Algoritmo del par. Default: `'ml-kem-768'` (cifrado). */\n readonly algorithm?: A;\n}\n\n/**\n * Genera un par de keys post-cuánticas. Sin opciones genera ML-KEM-768,\n * listo para `pqc.encrypt`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const encryption = await pqc.keys.generate();\n * const signing = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * ```\n */\nexport async function generate(): Promise<KeyPair<'ml-kem-768'>>;\nexport async function generate<A extends Algorithm>(\n options: GenerateOptions<A> & { algorithm: A },\n): Promise<KeyPair<A>>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair> {\n const algorithm = options?.algorithm ?? 'ml-kem-768';\n const spec = getAlgorithm(algorithm);\n return Promise.resolve(generateKeyPairFromSeed(algorithm, randomBytes(spec.seedLength)));\n}\n\n/**\n * Generación determinística a partir de una seed. Uso interno y de tests\n * (vectores NIST). Para uso normal preferir {@link generate}.\n */\nexport function generateKeyPairFromSeed(algorithm: Algorithm, seed: Uint8Array): KeyPair {\n const spec = getAlgorithm(algorithm);\n if (seed.length !== spec.seedLength) {\n throw new PqcError(\n 'INVALID_KEY',\n `Seed de ${algorithm} debe medir ${spec.seedLength} bytes, recibió ${seed.length}`,\n );\n }\n const material = spec.kind === 'kem' ? spec.kem.keygen(seed) : spec.signer.keygen(seed);\n return {\n algorithm,\n publicKey: { algorithm, use: 'public', bytes: material.publicKey },\n secretKey: { algorithm, use: 'secret', bytes: material.secretKey },\n };\n}\n\n/**\n * Serializa una key a un string portable: `pqcv1.<algoritmo>.<uso>.<base64url>`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const token = pqc.keys.serialize(pair.publicKey);\n * // \"pqcv1.ml-kem-768.public.h1q3…\"\n * ```\n */\nexport function serialize(key: PqcKey): string {\n const spec = getAlgorithm(key.algorithm);\n if (key.bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError('INVALID_KEY', `Key ${key.algorithm} ${key.use} con longitud inválida`);\n }\n return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;\n}\n\n/**\n * Reconstruye una key desde el formato de {@link serialize}. Valida versión,\n * algoritmo, uso y longitud; ante cualquier problema lanza {@link PqcError}\n * con código `INVALID_SERIALIZED_KEY` o `INVALID_KEY`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const publicKey = pqc.keys.deserialize(tokenRecibidoDelCliente);\n * const ciphertext = await pqc.encrypt(payload, publicKey);\n * ```\n */\nexport function deserialize(serialized: string): PqcKey {\n const parts = serialized.split('.');\n if (parts.length !== 4 || parts[0] !== SERIAL_PREFIX) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n 'Formato esperado: pqcv1.<algoritmo>.<uso>.<base64url>',\n );\n }\n const [, algorithm, use, encoded] = parts as [string, string, string, string];\n const spec = getAlgorithm(algorithm);\n if (use !== 'public' && use !== 'secret') {\n throw new PqcError('INVALID_SERIALIZED_KEY', `Uso de key desconocido: ${use}`);\n }\n let bytes: Uint8Array;\n try {\n bytes = fromBase64Url(encoded);\n } catch (cause) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n cause instanceof Error ? cause.message : 'base64url inválido',\n );\n }\n const key: PqcKey = { algorithm: algorithm as Algorithm, use, bytes };\n if (bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${algorithm} ${use} debe medir ${keyLengthFor(spec, key.use)} bytes, midió ${bytes.length}`,\n );\n }\n return key;\n}\n","const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\nconst CHAR_TO_VALUE = new Map<string, number>([...ALPHABET].map((c, i) => [c, i]));\n\n/** Codifica bytes a base64url sin padding. Implementación pura, sin Buffer/btoa. */\nexport function toBase64Url(bytes: Uint8Array): string {\n let out = '';\n for (let i = 0; i < bytes.length; i += 3) {\n const b0 = bytes[i]!;\n const b1 = bytes[i + 1];\n const b2 = bytes[i + 2];\n out += ALPHABET[b0 >> 2]!;\n out += ALPHABET[((b0 & 0x03) << 4) | ((b1 ?? 0) >> 4)]!;\n if (b1 !== undefined) out += ALPHABET[((b1 & 0x0f) << 2) | ((b2 ?? 0) >> 6)]!;\n if (b2 !== undefined) out += ALPHABET[b2 & 0x3f]!;\n }\n return out;\n}\n\n/** Decodifica base64url sin padding. Lanza TypeError ante caracteres inválidos. */\nexport function fromBase64Url(encoded: string): Uint8Array {\n if (encoded.length % 4 === 1) {\n throw new TypeError('base64url inválido: longitud imposible');\n }\n const out = new Uint8Array(Math.floor((encoded.length * 3) / 4));\n let outIndex = 0;\n let buffer = 0;\n let bits = 0;\n for (const char of encoded) {\n const value = CHAR_TO_VALUE.get(char);\n if (value === undefined) {\n throw new TypeError(`base64url inválido: carácter ${JSON.stringify(char)}`);\n }\n buffer = (buffer << 6) | value;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out[outIndex++] = (buffer >> bits) & 0xff;\n }\n }\n return out;\n}\n","import { requireKey } from './algorithms.js';\nimport type { PublicKey, SecretKey, SignatureOptions } from './types.js';\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\nfunction toNobleOptions(options?: SignatureOptions): { context: Uint8Array } | undefined {\n return options?.context ? { context: options.context } : undefined;\n}\n\n/**\n * Firma datos con ML-DSA-65 (FIPS 204), modo hedged (firma aleatorizada,\n * el default del estándar). Devuelve la firma de 3309 bytes.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign(documento, pair.secretKey);\n * ```\n */\nexport async function sign(\n data: Uint8Array | string,\n secretKey: SecretKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'signer', 'secret', 'sign');\n return Promise.resolve(spec.signer.sign(toBytes(data), secretKey.bytes, toNobleOptions(options)));\n}\n\n/**\n * Verifica una firma ML-DSA-65. Devuelve `false` ante firmas inválidas o\n * malformadas (nunca lanza por una firma corrupta); solo lanza si la key\n * no es ML-DSA.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const valid = await pqc.verify(documento, signature, pair.publicKey);\n * if (!valid) throw new Error('firma inválida');\n * ```\n */\nexport async function verify(\n data: Uint8Array | string,\n signature: Uint8Array,\n publicKey: PublicKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<boolean> {\n const spec = requireKey(publicKey, 'signer', 'public', 'verify');\n try {\n return Promise.resolve(\n spec.signer.verify(signature, toBytes(data), publicKey.bytes, toNobleOptions(options)),\n );\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["import_utils","utf8","toBytes"]}
package/dist/index.d.cts CHANGED
@@ -166,10 +166,10 @@ declare class PqcError extends Error {
166
166
  * ```ts
167
167
  * import { version } from '@pqc-sdk/core';
168
168
  *
169
- * console.log(version); // "0.0.1"
169
+ * console.log(version); // p. ej. "0.1.0"
170
170
  * ```
171
171
  */
172
- declare const version = "0.0.1";
172
+ declare const version: string;
173
173
  /**
174
174
  * Algoritmos PQC implementados (FIPS 203 y FIPS 204).
175
175
  *
package/dist/index.d.ts CHANGED
@@ -166,10 +166,10 @@ declare class PqcError extends Error {
166
166
  * ```ts
167
167
  * import { version } from '@pqc-sdk/core';
168
168
  *
169
- * console.log(version); // "0.0.1"
169
+ * console.log(version); // p. ej. "0.1.0"
170
170
  * ```
171
171
  */
172
- declare const version = "0.0.1";
172
+ declare const version: string;
173
173
  /**
174
174
  * Algoritmos PQC implementados (FIPS 203 y FIPS 204).
175
175
  *
package/dist/index.js CHANGED
@@ -251,7 +251,7 @@ async function verify(data, signature, publicKey, options) {
251
251
  }
252
252
 
253
253
  // src/index.ts
254
- var version = "0.0.1";
254
+ var version = "0.1.1";
255
255
  var SUPPORTED_ALGORITHMS = ["ml-kem-768", "ml-dsa-65"];
256
256
  var pqc = {
257
257
  keys: { generate, serialize, deserialize },
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/encrypt.ts","../src/algorithms.ts","../src/errors.ts","../src/keys.ts","../src/base64url.ts","../src/sign.ts","../src/index.ts"],"sourcesContent":["import { gcm } from '@noble/ciphers/aes.js';\nimport { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { KEM_ALGORITHMS, requireKey } from './algorithms.js';\nimport { PqcError } from './errors.js';\nimport type { PublicKey, SecretKey } from './types.js';\n\nconst FORMAT_VERSION = 1;\nconst NONCE_LENGTH = 12;\nconst GCM_TAG_LENGTH = 16;\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\n/**\n * Cifrado híbrido: encapsula un secreto con ML-KEM-768 (FIPS 203) y cifra los\n * datos con AES-256-GCM usando ese secreto. El resultado es un único\n * `Uint8Array` autocontenido que solo {@link decrypt} puede abrir.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('dato sensible', pair.publicKey);\n * ```\n */\nexport async function encrypt(\n data: Uint8Array | string,\n publicKey: PublicKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(publicKey, 'kem', 'public', 'encrypt');\n const plaintext = toBytes(data);\n\n const { cipherText, sharedSecret } = spec.kem.encapsulate(publicKey.bytes);\n const nonce = randomBytes(NONCE_LENGTH);\n const sealed = gcm(sharedSecret, nonce).encrypt(plaintext);\n\n const out = new Uint8Array(2 + cipherText.length + nonce.length + sealed.length);\n out[0] = FORMAT_VERSION;\n out[1] = spec.headerId;\n out.set(cipherText, 2);\n out.set(nonce, 2 + cipherText.length);\n out.set(sealed, 2 + cipherText.length + nonce.length);\n return Promise.resolve(out);\n}\n\n/**\n * Descifra un ciphertext producido por {@link encrypt}. Si el ciphertext fue\n * manipulado o la key no corresponde, lanza {@link PqcError} con código\n * `DECRYPTION_FAILED` — nunca devuelve datos corruptos.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n * new TextDecoder().decode(plaintext);\n * ```\n */\nexport async function decrypt(\n ciphertext: Uint8Array,\n secretKey: SecretKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'kem', 'secret', 'decrypt');\n\n const minLength = 2 + spec.ciphertextLength + NONCE_LENGTH + GCM_TAG_LENGTH;\n if (ciphertext.length < minLength) {\n throw new PqcError('INVALID_CIPHERTEXT', 'Ciphertext truncado o no producido por pqc.encrypt');\n }\n if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {\n throw new PqcError(\n 'INVALID_CIPHERTEXT',\n 'Header desconocido: el ciphertext no corresponde a esta versión o algoritmo',\n );\n }\n\n const kemCiphertext = ciphertext.subarray(2, 2 + spec.ciphertextLength);\n const nonce = ciphertext.subarray(\n 2 + spec.ciphertextLength,\n 2 + spec.ciphertextLength + NONCE_LENGTH,\n );\n const sealed = ciphertext.subarray(2 + spec.ciphertextLength + NONCE_LENGTH);\n\n const sharedSecret = spec.kem.decapsulate(kemCiphertext, secretKey.bytes);\n try {\n return Promise.resolve(gcm(sharedSecret, nonce).decrypt(sealed));\n } catch {\n throw new PqcError(\n 'DECRYPTION_FAILED',\n 'No se pudo descifrar: ciphertext manipulado o secret key incorrecta',\n );\n }\n}\n\n/** Algoritmos KEM disponibles, exportado para introspección. */\nexport const KEM_NAMES = Object.keys(KEM_ALGORITHMS);\n","import { ml_dsa65 } from '@noble/post-quantum/ml-dsa.js';\nimport { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KemAlgorithm, KeyUse, PqcKey, SignatureAlgorithm } from './types.js';\n\ninterface AlgorithmSpec {\n readonly seedLength: number;\n readonly publicKeyLength: number;\n readonly secretKeyLength: number;\n}\n\nexport interface KemSpec extends AlgorithmSpec {\n readonly kind: 'kem';\n readonly headerId: number;\n readonly ciphertextLength: number;\n readonly kem: typeof ml_kem768;\n}\n\nexport interface SignerSpec extends AlgorithmSpec {\n readonly kind: 'signer';\n readonly signatureLength: number;\n readonly signer: typeof ml_dsa65;\n}\n\nexport const KEM_ALGORITHMS: Record<KemAlgorithm, KemSpec> = {\n 'ml-kem-768': {\n kind: 'kem',\n headerId: 1,\n kem: ml_kem768,\n seedLength: 64,\n publicKeyLength: 1184,\n secretKeyLength: 2400,\n ciphertextLength: 1088,\n },\n};\n\nexport const SIGNATURE_ALGORITHMS: Record<SignatureAlgorithm, SignerSpec> = {\n 'ml-dsa-65': {\n kind: 'signer',\n signer: ml_dsa65,\n seedLength: 32,\n publicKeyLength: 1952,\n secretKeyLength: 4032,\n signatureLength: 3309,\n },\n};\n\nexport const ALGORITHMS: Record<Algorithm, KemSpec | SignerSpec> = {\n ...KEM_ALGORITHMS,\n ...SIGNATURE_ALGORITHMS,\n};\n\nexport function getAlgorithm(algorithm: string): KemSpec | SignerSpec {\n const spec = (ALGORITHMS as Record<string, KemSpec | SignerSpec>)[algorithm];\n if (!spec) {\n throw new PqcError('UNSUPPORTED_ALGORITHM', `Algoritmo no soportado: ${algorithm}`);\n }\n return spec;\n}\n\nexport function keyLengthFor(spec: KemSpec | SignerSpec, use: KeyUse): number {\n return use === 'public' ? spec.publicKeyLength : spec.secretKeyLength;\n}\n\n/** Valida algoritmo, uso y longitud de una key antes de operar con ella. */\nexport function requireKey<K extends 'kem' | 'signer'>(\n key: PqcKey,\n kind: K,\n use: KeyUse,\n operation: string,\n): K extends 'kem' ? KemSpec : SignerSpec {\n const spec = getAlgorithm(key.algorithm);\n if (spec.kind !== kind) {\n throw new PqcError(\n 'WRONG_ALGORITHM',\n `${operation} requiere una key ${kind === 'kem' ? 'ML-KEM' : 'ML-DSA'}, recibió ${key.algorithm}`,\n );\n }\n if (key.use !== use) {\n throw new PqcError('WRONG_KEY_USE', `${operation} requiere la key ${use}, recibió ${key.use}`);\n }\n if (key.bytes.length !== keyLengthFor(spec, use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${key.algorithm} ${use} con longitud inválida: ${key.bytes.length}`,\n );\n }\n return spec as K extends 'kem' ? KemSpec : SignerSpec;\n}\n","/** Códigos de error que puede emitir el SDK. */\nexport type PqcErrorCode =\n | 'UNSUPPORTED_ALGORITHM'\n | 'WRONG_ALGORITHM'\n | 'WRONG_KEY_USE'\n | 'INVALID_KEY'\n | 'INVALID_SERIALIZED_KEY'\n | 'INVALID_CIPHERTEXT'\n | 'DECRYPTION_FAILED';\n\n/**\n * Error tipado del SDK. Toda falla esperable expone un `code` estable para\n * manejarla programáticamente sin parsear mensajes.\n *\n * @example\n * ```ts\n * import { PqcError, pqc } from '@pqc-sdk/core';\n *\n * try {\n * await pqc.decrypt(ciphertext, secretKey);\n * } catch (error) {\n * if (error instanceof PqcError && error.code === 'DECRYPTION_FAILED') {\n * // ciphertext manipulado o key incorrecta\n * }\n * }\n * ```\n */\nexport class PqcError extends Error {\n readonly code: PqcErrorCode;\n\n constructor(code: PqcErrorCode, message: string) {\n super(message);\n this.name = 'PqcError';\n this.code = code;\n }\n}\n","import { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { getAlgorithm, keyLengthFor } from './algorithms.js';\nimport { fromBase64Url, toBase64Url } from './base64url.js';\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KeyPair, PqcKey } from './types.js';\n\nconst SERIAL_PREFIX = 'pqcv1';\n\n/** Opciones de {@link generate}. */\nexport interface GenerateOptions<A extends Algorithm = Algorithm> {\n /** Algoritmo del par. Default: `'ml-kem-768'` (cifrado). */\n readonly algorithm?: A;\n}\n\n/**\n * Genera un par de keys post-cuánticas. Sin opciones genera ML-KEM-768,\n * listo para `pqc.encrypt`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const encryption = await pqc.keys.generate();\n * const signing = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * ```\n */\nexport async function generate(): Promise<KeyPair<'ml-kem-768'>>;\nexport async function generate<A extends Algorithm>(\n options: GenerateOptions<A> & { algorithm: A },\n): Promise<KeyPair<A>>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair> {\n const algorithm = options?.algorithm ?? 'ml-kem-768';\n const spec = getAlgorithm(algorithm);\n return Promise.resolve(generateKeyPairFromSeed(algorithm, randomBytes(spec.seedLength)));\n}\n\n/**\n * Generación determinística a partir de una seed. Uso interno y de tests\n * (vectores NIST). Para uso normal preferir {@link generate}.\n */\nexport function generateKeyPairFromSeed(algorithm: Algorithm, seed: Uint8Array): KeyPair {\n const spec = getAlgorithm(algorithm);\n if (seed.length !== spec.seedLength) {\n throw new PqcError(\n 'INVALID_KEY',\n `Seed de ${algorithm} debe medir ${spec.seedLength} bytes, recibió ${seed.length}`,\n );\n }\n const material = spec.kind === 'kem' ? spec.kem.keygen(seed) : spec.signer.keygen(seed);\n return {\n algorithm,\n publicKey: { algorithm, use: 'public', bytes: material.publicKey },\n secretKey: { algorithm, use: 'secret', bytes: material.secretKey },\n };\n}\n\n/**\n * Serializa una key a un string portable: `pqcv1.<algoritmo>.<uso>.<base64url>`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const token = pqc.keys.serialize(pair.publicKey);\n * // \"pqcv1.ml-kem-768.public.h1q3…\"\n * ```\n */\nexport function serialize(key: PqcKey): string {\n const spec = getAlgorithm(key.algorithm);\n if (key.bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError('INVALID_KEY', `Key ${key.algorithm} ${key.use} con longitud inválida`);\n }\n return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;\n}\n\n/**\n * Reconstruye una key desde el formato de {@link serialize}. Valida versión,\n * algoritmo, uso y longitud; ante cualquier problema lanza {@link PqcError}\n * con código `INVALID_SERIALIZED_KEY` o `INVALID_KEY`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const publicKey = pqc.keys.deserialize(tokenRecibidoDelCliente);\n * const ciphertext = await pqc.encrypt(payload, publicKey);\n * ```\n */\nexport function deserialize(serialized: string): PqcKey {\n const parts = serialized.split('.');\n if (parts.length !== 4 || parts[0] !== SERIAL_PREFIX) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n 'Formato esperado: pqcv1.<algoritmo>.<uso>.<base64url>',\n );\n }\n const [, algorithm, use, encoded] = parts as [string, string, string, string];\n const spec = getAlgorithm(algorithm);\n if (use !== 'public' && use !== 'secret') {\n throw new PqcError('INVALID_SERIALIZED_KEY', `Uso de key desconocido: ${use}`);\n }\n let bytes: Uint8Array;\n try {\n bytes = fromBase64Url(encoded);\n } catch (cause) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n cause instanceof Error ? cause.message : 'base64url inválido',\n );\n }\n const key: PqcKey = { algorithm: algorithm as Algorithm, use, bytes };\n if (bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${algorithm} ${use} debe medir ${keyLengthFor(spec, key.use)} bytes, midió ${bytes.length}`,\n );\n }\n return key;\n}\n","const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\nconst CHAR_TO_VALUE = new Map<string, number>([...ALPHABET].map((c, i) => [c, i]));\n\n/** Codifica bytes a base64url sin padding. Implementación pura, sin Buffer/btoa. */\nexport function toBase64Url(bytes: Uint8Array): string {\n let out = '';\n for (let i = 0; i < bytes.length; i += 3) {\n const b0 = bytes[i]!;\n const b1 = bytes[i + 1];\n const b2 = bytes[i + 2];\n out += ALPHABET[b0 >> 2]!;\n out += ALPHABET[((b0 & 0x03) << 4) | ((b1 ?? 0) >> 4)]!;\n if (b1 !== undefined) out += ALPHABET[((b1 & 0x0f) << 2) | ((b2 ?? 0) >> 6)]!;\n if (b2 !== undefined) out += ALPHABET[b2 & 0x3f]!;\n }\n return out;\n}\n\n/** Decodifica base64url sin padding. Lanza TypeError ante caracteres inválidos. */\nexport function fromBase64Url(encoded: string): Uint8Array {\n if (encoded.length % 4 === 1) {\n throw new TypeError('base64url inválido: longitud imposible');\n }\n const out = new Uint8Array(Math.floor((encoded.length * 3) / 4));\n let outIndex = 0;\n let buffer = 0;\n let bits = 0;\n for (const char of encoded) {\n const value = CHAR_TO_VALUE.get(char);\n if (value === undefined) {\n throw new TypeError(`base64url inválido: carácter ${JSON.stringify(char)}`);\n }\n buffer = (buffer << 6) | value;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out[outIndex++] = (buffer >> bits) & 0xff;\n }\n }\n return out;\n}\n","import { requireKey } from './algorithms.js';\nimport type { PublicKey, SecretKey, SignatureOptions } from './types.js';\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\nfunction toNobleOptions(options?: SignatureOptions): { context: Uint8Array } | undefined {\n return options?.context ? { context: options.context } : undefined;\n}\n\n/**\n * Firma datos con ML-DSA-65 (FIPS 204), modo hedged (firma aleatorizada,\n * el default del estándar). Devuelve la firma de 3309 bytes.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign(documento, pair.secretKey);\n * ```\n */\nexport async function sign(\n data: Uint8Array | string,\n secretKey: SecretKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'signer', 'secret', 'sign');\n return Promise.resolve(spec.signer.sign(toBytes(data), secretKey.bytes, toNobleOptions(options)));\n}\n\n/**\n * Verifica una firma ML-DSA-65. Devuelve `false` ante firmas inválidas o\n * malformadas (nunca lanza por una firma corrupta); solo lanza si la key\n * no es ML-DSA.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const valid = await pqc.verify(documento, signature, pair.publicKey);\n * if (!valid) throw new Error('firma inválida');\n * ```\n */\nexport async function verify(\n data: Uint8Array | string,\n signature: Uint8Array,\n publicKey: PublicKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<boolean> {\n const spec = requireKey(publicKey, 'signer', 'public', 'verify');\n try {\n return Promise.resolve(\n spec.signer.verify(signature, toBytes(data), publicKey.bytes, toNobleOptions(options)),\n );\n } catch {\n return false;\n }\n}\n","import { encrypt, decrypt } from './encrypt.js';\nimport { deserialize, generate, serialize } from './keys.js';\nimport { sign, verify } from './sign.js';\n\nexport { PqcError, type PqcErrorCode } from './errors.js';\nexport type { GenerateOptions } from './keys.js';\nexport type {\n Algorithm,\n KemAlgorithm,\n KeyPair,\n KeyUse,\n PqcKey,\n PublicKey,\n SecretKey,\n SignatureAlgorithm,\n SignatureOptions,\n} from './types.js';\nexport { encrypt, decrypt, sign, verify, generate, serialize, deserialize };\n\n/**\n * Versión del SDK.\n *\n * @example\n * ```ts\n * import { version } from '@pqc-sdk/core';\n *\n * console.log(version); // \"0.0.1\"\n * ```\n */\nexport const version = '0.0.1';\n\n/**\n * Algoritmos PQC implementados (FIPS 203 y FIPS 204).\n *\n * @example\n * ```ts\n * import { SUPPORTED_ALGORITHMS } from '@pqc-sdk/core';\n *\n * SUPPORTED_ALGORITHMS.includes('ml-kem-768'); // true\n * ```\n */\nexport const SUPPORTED_ALGORITHMS = ['ml-kem-768', 'ml-dsa-65'] as const;\n\nexport type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];\n\n/**\n * Punto de entrada del SDK: cifrado híbrido post-cuántico y firmas digitales\n * con defaults seguros, sin configuración.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * // Cifrado (ML-KEM-768 + AES-256-GCM)\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('hola', pair.publicKey);\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n *\n * // Firmas (ML-DSA-65)\n * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign('documento', signer.secretKey);\n * await pqc.verify('documento', signature, signer.publicKey); // true\n * ```\n */\nexport const pqc = {\n keys: { generate, serialize, deserialize },\n encrypt,\n decrypt,\n sign,\n verify,\n} as const;\n"],"mappings":"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","names":["randomBytes","randomBytes","utf8","toBytes"]}
1
+ {"version":3,"sources":["../src/encrypt.ts","../src/algorithms.ts","../src/errors.ts","../src/keys.ts","../src/base64url.ts","../src/sign.ts","../src/index.ts"],"sourcesContent":["import { gcm } from '@noble/ciphers/aes.js';\nimport { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { KEM_ALGORITHMS, requireKey } from './algorithms.js';\nimport { PqcError } from './errors.js';\nimport type { PublicKey, SecretKey } from './types.js';\n\nconst FORMAT_VERSION = 1;\nconst NONCE_LENGTH = 12;\nconst GCM_TAG_LENGTH = 16;\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\n/**\n * Cifrado híbrido: encapsula un secreto con ML-KEM-768 (FIPS 203) y cifra los\n * datos con AES-256-GCM usando ese secreto. El resultado es un único\n * `Uint8Array` autocontenido que solo {@link decrypt} puede abrir.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('dato sensible', pair.publicKey);\n * ```\n */\nexport async function encrypt(\n data: Uint8Array | string,\n publicKey: PublicKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(publicKey, 'kem', 'public', 'encrypt');\n const plaintext = toBytes(data);\n\n const { cipherText, sharedSecret } = spec.kem.encapsulate(publicKey.bytes);\n const nonce = randomBytes(NONCE_LENGTH);\n const sealed = gcm(sharedSecret, nonce).encrypt(plaintext);\n\n const out = new Uint8Array(2 + cipherText.length + nonce.length + sealed.length);\n out[0] = FORMAT_VERSION;\n out[1] = spec.headerId;\n out.set(cipherText, 2);\n out.set(nonce, 2 + cipherText.length);\n out.set(sealed, 2 + cipherText.length + nonce.length);\n return Promise.resolve(out);\n}\n\n/**\n * Descifra un ciphertext producido por {@link encrypt}. Si el ciphertext fue\n * manipulado o la key no corresponde, lanza {@link PqcError} con código\n * `DECRYPTION_FAILED` — nunca devuelve datos corruptos.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n * new TextDecoder().decode(plaintext);\n * ```\n */\nexport async function decrypt(\n ciphertext: Uint8Array,\n secretKey: SecretKey<'ml-kem-768'>,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'kem', 'secret', 'decrypt');\n\n const minLength = 2 + spec.ciphertextLength + NONCE_LENGTH + GCM_TAG_LENGTH;\n if (ciphertext.length < minLength) {\n throw new PqcError('INVALID_CIPHERTEXT', 'Ciphertext truncado o no producido por pqc.encrypt');\n }\n if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {\n throw new PqcError(\n 'INVALID_CIPHERTEXT',\n 'Header desconocido: el ciphertext no corresponde a esta versión o algoritmo',\n );\n }\n\n const kemCiphertext = ciphertext.subarray(2, 2 + spec.ciphertextLength);\n const nonce = ciphertext.subarray(\n 2 + spec.ciphertextLength,\n 2 + spec.ciphertextLength + NONCE_LENGTH,\n );\n const sealed = ciphertext.subarray(2 + spec.ciphertextLength + NONCE_LENGTH);\n\n const sharedSecret = spec.kem.decapsulate(kemCiphertext, secretKey.bytes);\n try {\n return Promise.resolve(gcm(sharedSecret, nonce).decrypt(sealed));\n } catch {\n throw new PqcError(\n 'DECRYPTION_FAILED',\n 'No se pudo descifrar: ciphertext manipulado o secret key incorrecta',\n );\n }\n}\n\n/** Algoritmos KEM disponibles, exportado para introspección. */\nexport const KEM_NAMES = Object.keys(KEM_ALGORITHMS);\n","import { ml_dsa65 } from '@noble/post-quantum/ml-dsa.js';\nimport { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KemAlgorithm, KeyUse, PqcKey, SignatureAlgorithm } from './types.js';\n\ninterface AlgorithmSpec {\n readonly seedLength: number;\n readonly publicKeyLength: number;\n readonly secretKeyLength: number;\n}\n\nexport interface KemSpec extends AlgorithmSpec {\n readonly kind: 'kem';\n readonly headerId: number;\n readonly ciphertextLength: number;\n readonly kem: typeof ml_kem768;\n}\n\nexport interface SignerSpec extends AlgorithmSpec {\n readonly kind: 'signer';\n readonly signatureLength: number;\n readonly signer: typeof ml_dsa65;\n}\n\nexport const KEM_ALGORITHMS: Record<KemAlgorithm, KemSpec> = {\n 'ml-kem-768': {\n kind: 'kem',\n headerId: 1,\n kem: ml_kem768,\n seedLength: 64,\n publicKeyLength: 1184,\n secretKeyLength: 2400,\n ciphertextLength: 1088,\n },\n};\n\nexport const SIGNATURE_ALGORITHMS: Record<SignatureAlgorithm, SignerSpec> = {\n 'ml-dsa-65': {\n kind: 'signer',\n signer: ml_dsa65,\n seedLength: 32,\n publicKeyLength: 1952,\n secretKeyLength: 4032,\n signatureLength: 3309,\n },\n};\n\nexport const ALGORITHMS: Record<Algorithm, KemSpec | SignerSpec> = {\n ...KEM_ALGORITHMS,\n ...SIGNATURE_ALGORITHMS,\n};\n\nexport function getAlgorithm(algorithm: string): KemSpec | SignerSpec {\n const spec = (ALGORITHMS as Record<string, KemSpec | SignerSpec>)[algorithm];\n if (!spec) {\n throw new PqcError('UNSUPPORTED_ALGORITHM', `Algoritmo no soportado: ${algorithm}`);\n }\n return spec;\n}\n\nexport function keyLengthFor(spec: KemSpec | SignerSpec, use: KeyUse): number {\n return use === 'public' ? spec.publicKeyLength : spec.secretKeyLength;\n}\n\n/** Valida algoritmo, uso y longitud de una key antes de operar con ella. */\nexport function requireKey<K extends 'kem' | 'signer'>(\n key: PqcKey,\n kind: K,\n use: KeyUse,\n operation: string,\n): K extends 'kem' ? KemSpec : SignerSpec {\n const spec = getAlgorithm(key.algorithm);\n if (spec.kind !== kind) {\n throw new PqcError(\n 'WRONG_ALGORITHM',\n `${operation} requiere una key ${kind === 'kem' ? 'ML-KEM' : 'ML-DSA'}, recibió ${key.algorithm}`,\n );\n }\n if (key.use !== use) {\n throw new PqcError('WRONG_KEY_USE', `${operation} requiere la key ${use}, recibió ${key.use}`);\n }\n if (key.bytes.length !== keyLengthFor(spec, use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${key.algorithm} ${use} con longitud inválida: ${key.bytes.length}`,\n );\n }\n return spec as K extends 'kem' ? KemSpec : SignerSpec;\n}\n","/** Códigos de error que puede emitir el SDK. */\nexport type PqcErrorCode =\n | 'UNSUPPORTED_ALGORITHM'\n | 'WRONG_ALGORITHM'\n | 'WRONG_KEY_USE'\n | 'INVALID_KEY'\n | 'INVALID_SERIALIZED_KEY'\n | 'INVALID_CIPHERTEXT'\n | 'DECRYPTION_FAILED';\n\n/**\n * Error tipado del SDK. Toda falla esperable expone un `code` estable para\n * manejarla programáticamente sin parsear mensajes.\n *\n * @example\n * ```ts\n * import { PqcError, pqc } from '@pqc-sdk/core';\n *\n * try {\n * await pqc.decrypt(ciphertext, secretKey);\n * } catch (error) {\n * if (error instanceof PqcError && error.code === 'DECRYPTION_FAILED') {\n * // ciphertext manipulado o key incorrecta\n * }\n * }\n * ```\n */\nexport class PqcError extends Error {\n readonly code: PqcErrorCode;\n\n constructor(code: PqcErrorCode, message: string) {\n super(message);\n this.name = 'PqcError';\n this.code = code;\n }\n}\n","import { randomBytes } from '@noble/post-quantum/utils.js';\n\nimport { getAlgorithm, keyLengthFor } from './algorithms.js';\nimport { fromBase64Url, toBase64Url } from './base64url.js';\nimport { PqcError } from './errors.js';\nimport type { Algorithm, KeyPair, PqcKey } from './types.js';\n\nconst SERIAL_PREFIX = 'pqcv1';\n\n/** Opciones de {@link generate}. */\nexport interface GenerateOptions<A extends Algorithm = Algorithm> {\n /** Algoritmo del par. Default: `'ml-kem-768'` (cifrado). */\n readonly algorithm?: A;\n}\n\n/**\n * Genera un par de keys post-cuánticas. Sin opciones genera ML-KEM-768,\n * listo para `pqc.encrypt`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const encryption = await pqc.keys.generate();\n * const signing = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * ```\n */\nexport async function generate(): Promise<KeyPair<'ml-kem-768'>>;\nexport async function generate<A extends Algorithm>(\n options: GenerateOptions<A> & { algorithm: A },\n): Promise<KeyPair<A>>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair>;\nexport async function generate(options?: GenerateOptions): Promise<KeyPair> {\n const algorithm = options?.algorithm ?? 'ml-kem-768';\n const spec = getAlgorithm(algorithm);\n return Promise.resolve(generateKeyPairFromSeed(algorithm, randomBytes(spec.seedLength)));\n}\n\n/**\n * Generación determinística a partir de una seed. Uso interno y de tests\n * (vectores NIST). Para uso normal preferir {@link generate}.\n */\nexport function generateKeyPairFromSeed(algorithm: Algorithm, seed: Uint8Array): KeyPair {\n const spec = getAlgorithm(algorithm);\n if (seed.length !== spec.seedLength) {\n throw new PqcError(\n 'INVALID_KEY',\n `Seed de ${algorithm} debe medir ${spec.seedLength} bytes, recibió ${seed.length}`,\n );\n }\n const material = spec.kind === 'kem' ? spec.kem.keygen(seed) : spec.signer.keygen(seed);\n return {\n algorithm,\n publicKey: { algorithm, use: 'public', bytes: material.publicKey },\n secretKey: { algorithm, use: 'secret', bytes: material.secretKey },\n };\n}\n\n/**\n * Serializa una key a un string portable: `pqcv1.<algoritmo>.<uso>.<base64url>`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate();\n * const token = pqc.keys.serialize(pair.publicKey);\n * // \"pqcv1.ml-kem-768.public.h1q3…\"\n * ```\n */\nexport function serialize(key: PqcKey): string {\n const spec = getAlgorithm(key.algorithm);\n if (key.bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError('INVALID_KEY', `Key ${key.algorithm} ${key.use} con longitud inválida`);\n }\n return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;\n}\n\n/**\n * Reconstruye una key desde el formato de {@link serialize}. Valida versión,\n * algoritmo, uso y longitud; ante cualquier problema lanza {@link PqcError}\n * con código `INVALID_SERIALIZED_KEY` o `INVALID_KEY`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const publicKey = pqc.keys.deserialize(tokenRecibidoDelCliente);\n * const ciphertext = await pqc.encrypt(payload, publicKey);\n * ```\n */\nexport function deserialize(serialized: string): PqcKey {\n const parts = serialized.split('.');\n if (parts.length !== 4 || parts[0] !== SERIAL_PREFIX) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n 'Formato esperado: pqcv1.<algoritmo>.<uso>.<base64url>',\n );\n }\n const [, algorithm, use, encoded] = parts as [string, string, string, string];\n const spec = getAlgorithm(algorithm);\n if (use !== 'public' && use !== 'secret') {\n throw new PqcError('INVALID_SERIALIZED_KEY', `Uso de key desconocido: ${use}`);\n }\n let bytes: Uint8Array;\n try {\n bytes = fromBase64Url(encoded);\n } catch (cause) {\n throw new PqcError(\n 'INVALID_SERIALIZED_KEY',\n cause instanceof Error ? cause.message : 'base64url inválido',\n );\n }\n const key: PqcKey = { algorithm: algorithm as Algorithm, use, bytes };\n if (bytes.length !== keyLengthFor(spec, key.use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `Key ${algorithm} ${use} debe medir ${keyLengthFor(spec, key.use)} bytes, midió ${bytes.length}`,\n );\n }\n return key;\n}\n","const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\nconst CHAR_TO_VALUE = new Map<string, number>([...ALPHABET].map((c, i) => [c, i]));\n\n/** Codifica bytes a base64url sin padding. Implementación pura, sin Buffer/btoa. */\nexport function toBase64Url(bytes: Uint8Array): string {\n let out = '';\n for (let i = 0; i < bytes.length; i += 3) {\n const b0 = bytes[i]!;\n const b1 = bytes[i + 1];\n const b2 = bytes[i + 2];\n out += ALPHABET[b0 >> 2]!;\n out += ALPHABET[((b0 & 0x03) << 4) | ((b1 ?? 0) >> 4)]!;\n if (b1 !== undefined) out += ALPHABET[((b1 & 0x0f) << 2) | ((b2 ?? 0) >> 6)]!;\n if (b2 !== undefined) out += ALPHABET[b2 & 0x3f]!;\n }\n return out;\n}\n\n/** Decodifica base64url sin padding. Lanza TypeError ante caracteres inválidos. */\nexport function fromBase64Url(encoded: string): Uint8Array {\n if (encoded.length % 4 === 1) {\n throw new TypeError('base64url inválido: longitud imposible');\n }\n const out = new Uint8Array(Math.floor((encoded.length * 3) / 4));\n let outIndex = 0;\n let buffer = 0;\n let bits = 0;\n for (const char of encoded) {\n const value = CHAR_TO_VALUE.get(char);\n if (value === undefined) {\n throw new TypeError(`base64url inválido: carácter ${JSON.stringify(char)}`);\n }\n buffer = (buffer << 6) | value;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out[outIndex++] = (buffer >> bits) & 0xff;\n }\n }\n return out;\n}\n","import { requireKey } from './algorithms.js';\nimport type { PublicKey, SecretKey, SignatureOptions } from './types.js';\n\nconst utf8 = new TextEncoder();\n\nfunction toBytes(data: Uint8Array | string): Uint8Array {\n return typeof data === 'string' ? utf8.encode(data) : data;\n}\n\nfunction toNobleOptions(options?: SignatureOptions): { context: Uint8Array } | undefined {\n return options?.context ? { context: options.context } : undefined;\n}\n\n/**\n * Firma datos con ML-DSA-65 (FIPS 204), modo hedged (firma aleatorizada,\n * el default del estándar). Devuelve la firma de 3309 bytes.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const pair = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign(documento, pair.secretKey);\n * ```\n */\nexport async function sign(\n data: Uint8Array | string,\n secretKey: SecretKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<Uint8Array> {\n const spec = requireKey(secretKey, 'signer', 'secret', 'sign');\n return Promise.resolve(spec.signer.sign(toBytes(data), secretKey.bytes, toNobleOptions(options)));\n}\n\n/**\n * Verifica una firma ML-DSA-65. Devuelve `false` ante firmas inválidas o\n * malformadas (nunca lanza por una firma corrupta); solo lanza si la key\n * no es ML-DSA.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const valid = await pqc.verify(documento, signature, pair.publicKey);\n * if (!valid) throw new Error('firma inválida');\n * ```\n */\nexport async function verify(\n data: Uint8Array | string,\n signature: Uint8Array,\n publicKey: PublicKey<'ml-dsa-65'>,\n options?: SignatureOptions,\n): Promise<boolean> {\n const spec = requireKey(publicKey, 'signer', 'public', 'verify');\n try {\n return Promise.resolve(\n spec.signer.verify(signature, toBytes(data), publicKey.bytes, toNobleOptions(options)),\n );\n } catch {\n return false;\n }\n}\n","import { encrypt, decrypt } from './encrypt.js';\nimport { deserialize, generate, serialize } from './keys.js';\nimport { sign, verify } from './sign.js';\n\nexport { PqcError, type PqcErrorCode } from './errors.js';\nexport type { GenerateOptions } from './keys.js';\nexport type {\n Algorithm,\n KemAlgorithm,\n KeyPair,\n KeyUse,\n PqcKey,\n PublicKey,\n SecretKey,\n SignatureAlgorithm,\n SignatureOptions,\n} from './types.js';\nexport { encrypt, decrypt, sign, verify, generate, serialize, deserialize };\n\n// Inyectada en build time desde el package.json (`define` en tsup.config.ts y vitest.config.ts).\ndeclare const __PQC_CORE_VERSION__: string;\n\n/**\n * Versión del SDK.\n *\n * @example\n * ```ts\n * import { version } from '@pqc-sdk/core';\n *\n * console.log(version); // p. ej. \"0.1.0\"\n * ```\n */\nexport const version = __PQC_CORE_VERSION__;\n\n/**\n * Algoritmos PQC implementados (FIPS 203 y FIPS 204).\n *\n * @example\n * ```ts\n * import { SUPPORTED_ALGORITHMS } from '@pqc-sdk/core';\n *\n * SUPPORTED_ALGORITHMS.includes('ml-kem-768'); // true\n * ```\n */\nexport const SUPPORTED_ALGORITHMS = ['ml-kem-768', 'ml-dsa-65'] as const;\n\nexport type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];\n\n/**\n * Punto de entrada del SDK: cifrado híbrido post-cuántico y firmas digitales\n * con defaults seguros, sin configuración.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * // Cifrado (ML-KEM-768 + AES-256-GCM)\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('hola', pair.publicKey);\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n *\n * // Firmas (ML-DSA-65)\n * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign('documento', signer.secretKey);\n * await pqc.verify('documento', signature, signer.publicKey); // true\n * ```\n */\nexport const pqc = {\n keys: { generate, serialize, deserialize },\n encrypt,\n decrypt,\n sign,\n verify,\n} as const;\n"],"mappings":"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","names":["randomBytes","randomBytes","utf8","toBytes"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pqc-sdk/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "SDK de criptografía post-cuántica para JS/TS (ML-KEM, ML-DSA, SLH-DSA)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -56,7 +56,7 @@
56
56
  "scripts": {
57
57
  "build": "tsup",
58
58
  "dev": "tsup --watch",
59
- "test": "vitest run",
59
+ "test": "vitest run --coverage",
60
60
  "test:watch": "vitest",
61
61
  "lint": "eslint . && tsc --noEmit"
62
62
  }