@pqc-sdk/core 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -5,9 +5,10 @@
5
5
  [![bundle size](https://img.shields.io/bundlephobia/minzip/%40pqc-sdk%2Fcore)](https://bundlephobia.com/package/@pqc-sdk/core)
6
6
  [![license](https://img.shields.io/npm/l/%40pqc-sdk%2Fcore)](./LICENSE)
7
7
 
8
- Criptografía post-cuántica para JS/TS con defaults seguros y cero configuración.
9
- **ML-KEM-768** (FIPS 203) + AES-256-GCM para cifrado híbrido, **ML-DSA-65**
10
- (FIPS 204) para firmas. Validado contra los test vectors oficiales NIST ACVP.
8
+ Post-quantum cryptography for JS/TS with safe defaults and zero configuration.
9
+ **ML-KEM-768** (FIPS 203) + AES-256-GCM for hybrid encryption, **ML-DSA-65**
10
+ (FIPS 204) for signatures. Validated against the official NIST ACVP test
11
+ vectors.
11
12
 
12
13
  ```bash
13
14
  npm install @pqc-sdk/core
@@ -17,57 +18,61 @@ npm install @pqc-sdk/core
17
18
  import { pqc } from '@pqc-sdk/core';
18
19
 
19
20
  const pair = await pqc.keys.generate();
20
- const ciphertext = await pqc.encrypt('secreto', pair.publicKey);
21
+ const ciphertext = await pqc.encrypt('secret', pair.publicKey);
21
22
  const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);
22
23
 
23
24
  const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });
24
- const signature = await pqc.sign('documento', signer.secretKey);
25
- const valid = await pqc.verify('documento', signature, signer.publicKey);
25
+ const signature = await pqc.sign('document', signer.secretKey);
26
+ const valid = await pqc.verify('document', signature, signer.publicKey);
26
27
 
27
- console.log(new TextDecoder().decode(plaintext), valid); // "secreto" true
28
+ console.log(new TextDecoder().decode(plaintext), valid); // "secret" true
28
29
  ```
29
30
 
30
- ## Compatibilidad
31
+ ## Compatibility
31
32
 
32
- | Runtime | Soporte | Notas |
33
- | ------------------ | ------- | --------------------------------------------- |
34
- | Node 20+ | ✅ | ESM y CJS |
35
- | Cloudflare Workers | ✅ | Sin `nodejs_compat`; ~20 KB gzip en el bundle |
36
- | Deno 2+ | ✅ | `npm:@pqc-sdk/core` |
37
- | Bun | ✅ | |
38
- | React Native | ✅ | Requiere `react-native-get-random-values` |
39
- | Navegadores | ✅ | Cualquier target ES2022 con WebCrypto |
33
+ | Runtime | Support | Notes |
34
+ | ------------------ | ------- | ----------------------------------------- |
35
+ | Node 20+ | ✅ | ESM and CJS |
36
+ | Cloudflare Workers | ✅ | No `nodejs_compat`; ~20 KB gzip in bundle |
37
+ | Deno 2+ | ✅ | `npm:@pqc-sdk/core` |
38
+ | Bun | ✅ | |
39
+ | React Native | ✅ | Requires `react-native-get-random-values` |
40
+ | Browsers | ✅ | Any ES2022 target with WebCrypto |
40
41
 
41
- Sin WASM ni addons nativos: TypeScript puro sobre
42
+ No WASM or native addons: pure TypeScript on top of
42
43
  [@noble/post-quantum](https://github.com/paulmillr/noble-post-quantum).
43
44
 
44
45
  ## Benchmarks
45
46
 
46
- Node 24, x86_64 (mensajes de 1 KB):
47
+ Node 24, x86_64 (1 KB messages):
47
48
 
48
- | Operación | Tiempo | Throughput |
49
+ | Operation | Time | Throughput |
49
50
  | ----------------- | ---------- | ---------- |
50
- | keygen ML-KEM-768 | 1,3 ms/op | 768 ops/s |
51
- | encrypt | 1,7 ms/op | 585 ops/s |
52
- | decrypt | 2,3 ms/op | 440 ops/s |
53
- | keygen ML-DSA-65 | 4,8 ms/op | 210 ops/s |
54
- | sign | 20,2 ms/op | 50 ops/s |
55
- | verify | 5,1 ms/op | 195 ops/s |
51
+ | keygen ML-KEM-768 | 1.3 ms/op | 768 ops/s |
52
+ | encrypt | 1.7 ms/op | 585 ops/s |
53
+ | decrypt | 2.3 ms/op | 440 ops/s |
54
+ | keygen ML-DSA-65 | 4.8 ms/op | 210 ops/s |
55
+ | sign | 20.2 ms/op | 50 ops/s |
56
+ | verify | 5.1 ms/op | 195 ops/s |
56
57
 
57
- ## Documentación
58
+ ## Documentation
58
59
 
59
- - [Quickstart de 5 minutos](https://github.com/jeloercc/pqc-sdk/tree/main/apps/docs/guide/quickstart.md)
60
- - [Cifrado híbrido KEM+AES, explicado](https://github.com/jeloercc/pqc-sdk/tree/main/apps/docs/guide/hybrid-encryption.md)
61
- - [Compatibilidad detallada](https://github.com/jeloercc/pqc-sdk/tree/main/docs/compatibility.md)
60
+ Full documentation at **[jeloercc.github.io/pqc-sdk](https://jeloercc.github.io/pqc-sdk/)**.
62
61
 
63
- ## Seguridad
62
+ - [5-minute quickstart](https://jeloercc.github.io/pqc-sdk/guide/quickstart)
63
+ - [Hybrid KEM+AES encryption, explained](https://jeloercc.github.io/pqc-sdk/guide/hybrid-encryption)
64
+ - [Detailed compatibility](https://jeloercc.github.io/pqc-sdk/compatibility)
65
+ - [API reference](https://jeloercc.github.io/pqc-sdk/api/)
64
66
 
65
- - Nunca implementamos primitivas: ML-KEM/ML-DSA vienen de `@noble/post-quantum`
66
- y AES-GCM de `@noble/ciphers`.
67
- - `@noble/post-quantum` no tiene aún auditoría independiente (self-audit
68
- 04/2026). Como todo JS, sin garantías constant-time estrictas.
69
- - Reportes de seguridad: abrí un issue privado o escribí al maintainer.
67
+ ## Security
70
68
 
71
- ## Licencia
69
+ - We never implement primitives: ML-KEM/ML-DSA come from
70
+ `@noble/post-quantum` and AES-GCM from `@noble/ciphers`.
71
+ - `@noble/post-quantum` has no independent audit yet (self-audit 04/2026).
72
+ As with all JS, there are no strict constant-time guarantees.
73
+ - Security reports: see [SECURITY.md](https://github.com/jeloercc/pqc-sdk/blob/main/SECURITY.md) —
74
+ please do not open public issues.
75
+
76
+ ## License
72
77
 
73
78
  [MIT](./LICENSE)
package/dist/index.cjs CHANGED
@@ -81,7 +81,7 @@ var ALGORITHMS = {
81
81
  function getAlgorithm(algorithm) {
82
82
  const spec = ALGORITHMS[algorithm];
83
83
  if (!spec) {
84
- throw new PqcError("UNSUPPORTED_ALGORITHM", `Algoritmo no soportado: ${algorithm}`);
84
+ throw new PqcError("UNSUPPORTED_ALGORITHM", `Unsupported algorithm: ${algorithm}`);
85
85
  }
86
86
  return spec;
87
87
  }
@@ -93,16 +93,16 @@ function requireKey(key, kind, use, operation) {
93
93
  if (spec.kind !== kind) {
94
94
  throw new PqcError(
95
95
  "WRONG_ALGORITHM",
96
- `${operation} requiere una key ${kind === "kem" ? "ML-KEM" : "ML-DSA"}, recibi\xF3 ${key.algorithm}`
96
+ `${operation} requires an ${kind === "kem" ? "ML-KEM" : "ML-DSA"} key, got ${key.algorithm}`
97
97
  );
98
98
  }
99
99
  if (key.use !== use) {
100
- throw new PqcError("WRONG_KEY_USE", `${operation} requiere la key ${use}, recibi\xF3 ${key.use}`);
100
+ throw new PqcError("WRONG_KEY_USE", `${operation} requires the ${use} key, got ${key.use}`);
101
101
  }
102
102
  if (key.bytes.length !== keyLengthFor(spec, use)) {
103
103
  throw new PqcError(
104
104
  "INVALID_KEY",
105
- `Key ${key.algorithm} ${use} con longitud inv\xE1lida: ${key.bytes.length}`
105
+ `${key.algorithm} ${use} key has invalid length: ${key.bytes.length}`
106
106
  );
107
107
  }
108
108
  return spec;
@@ -134,12 +134,15 @@ async function decrypt(ciphertext, secretKey) {
134
134
  const spec = requireKey(secretKey, "kem", "secret", "decrypt");
135
135
  const minLength = 2 + spec.ciphertextLength + NONCE_LENGTH + GCM_TAG_LENGTH;
136
136
  if (ciphertext.length < minLength) {
137
- throw new PqcError("INVALID_CIPHERTEXT", "Ciphertext truncado o no producido por pqc.encrypt");
137
+ throw new PqcError(
138
+ "INVALID_CIPHERTEXT",
139
+ "Ciphertext is truncated or was not produced by pqc.encrypt"
140
+ );
138
141
  }
139
142
  if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {
140
143
  throw new PqcError(
141
144
  "INVALID_CIPHERTEXT",
142
- "Header desconocido: el ciphertext no corresponde a esta versi\xF3n o algoritmo"
145
+ "Unknown header: the ciphertext does not match this version or algorithm"
143
146
  );
144
147
  }
145
148
  const kemCiphertext = ciphertext.subarray(2, 2 + spec.ciphertextLength);
@@ -154,7 +157,7 @@ async function decrypt(ciphertext, secretKey) {
154
157
  } catch {
155
158
  throw new PqcError(
156
159
  "DECRYPTION_FAILED",
157
- "No se pudo descifrar: ciphertext manipulado o secret key incorrecta"
160
+ "Decryption failed: tampered ciphertext or wrong secret key"
158
161
  );
159
162
  }
160
163
  }
@@ -181,7 +184,7 @@ function toBase64Url(bytes) {
181
184
  }
182
185
  function fromBase64Url(encoded) {
183
186
  if (encoded.length % 4 === 1) {
184
- throw new TypeError("base64url inv\xE1lido: longitud imposible");
187
+ throw new TypeError("Invalid base64url: impossible length");
185
188
  }
186
189
  const out = new Uint8Array(Math.floor(encoded.length * 3 / 4));
187
190
  let outIndex = 0;
@@ -190,7 +193,7 @@ function fromBase64Url(encoded) {
190
193
  for (const char of encoded) {
191
194
  const value = CHAR_TO_VALUE.get(char);
192
195
  if (value === void 0) {
193
- throw new TypeError(`base64url inv\xE1lido: car\xE1cter ${JSON.stringify(char)}`);
196
+ throw new TypeError(`Invalid base64url: character ${JSON.stringify(char)}`);
194
197
  }
195
198
  buffer = buffer << 6 | value;
196
199
  bits += 6;
@@ -214,7 +217,7 @@ function generateKeyPairFromSeed(algorithm, seed) {
214
217
  if (seed.length !== spec.seedLength) {
215
218
  throw new PqcError(
216
219
  "INVALID_KEY",
217
- `Seed de ${algorithm} debe medir ${spec.seedLength} bytes, recibi\xF3 ${seed.length}`
220
+ `${algorithm} seed must be ${spec.seedLength} bytes, got ${seed.length}`
218
221
  );
219
222
  }
220
223
  const material = spec.kind === "kem" ? spec.kem.keygen(seed) : spec.signer.keygen(seed);
@@ -227,7 +230,7 @@ function generateKeyPairFromSeed(algorithm, seed) {
227
230
  function serialize(key) {
228
231
  const spec = getAlgorithm(key.algorithm);
229
232
  if (key.bytes.length !== keyLengthFor(spec, key.use)) {
230
- throw new PqcError("INVALID_KEY", `Key ${key.algorithm} ${key.use} con longitud inv\xE1lida`);
233
+ throw new PqcError("INVALID_KEY", `${key.algorithm} ${key.use} key has invalid length`);
231
234
  }
232
235
  return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;
233
236
  }
@@ -236,13 +239,13 @@ function deserialize(serialized) {
236
239
  if (parts.length !== 4 || parts[0] !== SERIAL_PREFIX) {
237
240
  throw new PqcError(
238
241
  "INVALID_SERIALIZED_KEY",
239
- "Formato esperado: pqcv1.<algoritmo>.<uso>.<base64url>"
242
+ "Expected format: pqcv1.<algorithm>.<use>.<base64url>"
240
243
  );
241
244
  }
242
245
  const [, algorithm, use, encoded] = parts;
243
246
  const spec = getAlgorithm(algorithm);
244
247
  if (use !== "public" && use !== "secret") {
245
- throw new PqcError("INVALID_SERIALIZED_KEY", `Uso de key desconocido: ${use}`);
248
+ throw new PqcError("INVALID_SERIALIZED_KEY", `Unknown key use: ${use}`);
246
249
  }
247
250
  let bytes;
248
251
  try {
@@ -250,14 +253,14 @@ function deserialize(serialized) {
250
253
  } catch (cause) {
251
254
  throw new PqcError(
252
255
  "INVALID_SERIALIZED_KEY",
253
- cause instanceof Error ? cause.message : "base64url inv\xE1lido"
256
+ cause instanceof Error ? cause.message : "Invalid base64url"
254
257
  );
255
258
  }
256
259
  const key = { algorithm, use, bytes };
257
260
  if (bytes.length !== keyLengthFor(spec, key.use)) {
258
261
  throw new PqcError(
259
262
  "INVALID_KEY",
260
- `Key ${algorithm} ${use} debe medir ${keyLengthFor(spec, key.use)} bytes, midi\xF3 ${bytes.length}`
263
+ `${algorithm} ${use} key must be ${keyLengthFor(spec, key.use)} bytes, got ${bytes.length}`
261
264
  );
262
265
  }
263
266
  return key;
@@ -287,7 +290,7 @@ async function verify(data, signature, publicKey, options) {
287
290
  }
288
291
 
289
292
  // src/index.ts
290
- var version = "0.0.1";
293
+ var version = "0.1.2";
291
294
  var SUPPORTED_ALGORITHMS = ["ml-kem-768", "ml-dsa-65"];
292
295
  var pqc = {
293
296
  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// Injected at build time from package.json (`define` in tsup.config.ts and vitest.config.ts).\ndeclare const __PQC_CORE_VERSION__: string;\n\n/**\n * SDK version.\n *\n * @example\n * ```ts\n * import { version } from '@pqc-sdk/core';\n *\n * console.log(version); // e.g. \"0.1.0\"\n * ```\n */\nexport const version = __PQC_CORE_VERSION__;\n\n/**\n * Implemented PQC algorithms (FIPS 203 and 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 * SDK entry point: post-quantum hybrid encryption and digital signatures\n * with safe defaults, zero configuration.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * // Encryption (ML-KEM-768 + AES-256-GCM)\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('hello', pair.publicKey);\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n *\n * // Signatures (ML-DSA-65)\n * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign('document', signer.secretKey);\n * await pqc.verify('document', 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 * Hybrid encryption: encapsulates a secret with ML-KEM-768 (FIPS 203) and\n * encrypts the data with AES-256-GCM using that secret. The result is a\n * single self-contained `Uint8Array` that only {@link decrypt} can open.\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('sensitive data', 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 * Decrypts a ciphertext produced by {@link encrypt}. If the ciphertext was\n * tampered with or the key does not match, it throws {@link PqcError} with\n * code `DECRYPTION_FAILED` — it never returns corrupted data.\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(\n 'INVALID_CIPHERTEXT',\n 'Ciphertext is truncated or was not produced by pqc.encrypt',\n );\n }\n if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {\n throw new PqcError(\n 'INVALID_CIPHERTEXT',\n 'Unknown header: the ciphertext does not match this version or algorithm',\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 'Decryption failed: tampered ciphertext or wrong secret key',\n );\n }\n}\n\n/** Available KEM algorithms, exported for introspection. */\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', `Unsupported algorithm: ${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/** Validates a key's algorithm, use and length before operating with it. */\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} requires an ${kind === 'kem' ? 'ML-KEM' : 'ML-DSA'} key, got ${key.algorithm}`,\n );\n }\n if (key.use !== use) {\n throw new PqcError('WRONG_KEY_USE', `${operation} requires the ${use} key, got ${key.use}`);\n }\n if (key.bytes.length !== keyLengthFor(spec, use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `${key.algorithm} ${use} key has invalid length: ${key.bytes.length}`,\n );\n }\n return spec as K extends 'kem' ? KemSpec : SignerSpec;\n}\n","/** Error codes the SDK can emit. */\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 * Typed SDK error. Every expected failure exposes a stable `code` so it can\n * be handled programmatically without parsing messages.\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 * // tampered ciphertext or wrong key\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/** Options for {@link generate}. */\nexport interface GenerateOptions<A extends Algorithm = Algorithm> {\n /** Algorithm of the pair. Default: `'ml-kem-768'` (encryption). */\n readonly algorithm?: A;\n}\n\n/**\n * Generates a post-quantum key pair. With no options it generates ML-KEM-768,\n * ready for `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 * Deterministic generation from a seed. Internal and test use (NIST vectors).\n * Prefer {@link generate} for normal use.\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 `${algorithm} seed must be ${spec.seedLength} bytes, got ${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 * Serializes a key to a portable string: `pqcv1.<algorithm>.<use>.<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.algorithm} ${key.use} key has invalid length`);\n }\n return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;\n}\n\n/**\n * Rebuilds a key from the {@link serialize} format. Validates version,\n * algorithm, use and length; on any problem it throws {@link PqcError} with\n * code `INVALID_SERIALIZED_KEY` or `INVALID_KEY`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const publicKey = pqc.keys.deserialize(tokenReceivedFromClient);\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 'Expected format: pqcv1.<algorithm>.<use>.<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', `Unknown key use: ${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 : 'Invalid base64url',\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 `${algorithm} ${use} key must be ${keyLengthFor(spec, key.use)} bytes, got ${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/** Encodes bytes to unpadded base64url. Pure implementation, no 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/** Decodes unpadded base64url. Throws TypeError on invalid characters. */\nexport function fromBase64Url(encoded: string): Uint8Array {\n if (encoded.length % 4 === 1) {\n throw new TypeError('Invalid base64url: impossible length');\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(`Invalid base64url: character ${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 * Signs data with ML-DSA-65 (FIPS 204) in hedged mode (randomized signing,\n * the standard's default). Returns the 3309-byte signature.\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(document, 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 * Verifies an ML-DSA-65 signature. Returns `false` for invalid or malformed\n * signatures (it never throws because of a corrupted signature); it only\n * throws if the key is not ML-DSA.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const valid = await pqc.verify(document, signature, pair.publicKey);\n * if (!valid) throw new Error('invalid signature');\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
@@ -1,51 +1,51 @@
1
- /** Algoritmo de encapsulamiento de claves (cifrado híbrido). */
1
+ /** Key encapsulation algorithm (hybrid encryption). */
2
2
  type KemAlgorithm = 'ml-kem-768';
3
- /** Algoritmo de firma digital. */
3
+ /** Digital signature algorithm. */
4
4
  type SignatureAlgorithm = 'ml-dsa-65';
5
- /** Algoritmos soportados por el SDK. */
5
+ /** Algorithms supported by the SDK. */
6
6
  type Algorithm = KemAlgorithm | SignatureAlgorithm;
7
- /** Rol de una key dentro de su par. */
7
+ /** Role of a key within its pair. */
8
8
  type KeyUse = 'public' | 'secret';
9
- /** Key del SDK: bytes crudos más metadata de algoritmo y uso. */
9
+ /** SDK key: raw bytes plus algorithm and use metadata. */
10
10
  interface PqcKey<A extends Algorithm = Algorithm, U extends KeyUse = KeyUse> {
11
11
  readonly algorithm: A;
12
12
  readonly use: U;
13
13
  readonly bytes: Uint8Array;
14
14
  }
15
- /** Key pública, segura de compartir. */
15
+ /** Public key, safe to share. */
16
16
  type PublicKey<A extends Algorithm = Algorithm> = PqcKey<A, 'public'>;
17
- /** Key secreta. Nunca debe salir del entorno del dueño. */
17
+ /** Secret key. Must never leave its owner's environment. */
18
18
  type SecretKey<A extends Algorithm = Algorithm> = PqcKey<A, 'secret'>;
19
- /** Par de keys generado por `pqc.keys.generate`. */
19
+ /** Key pair produced by `pqc.keys.generate`. */
20
20
  interface KeyPair<A extends Algorithm = Algorithm> {
21
21
  readonly algorithm: A;
22
22
  readonly publicKey: PublicKey<A>;
23
23
  readonly secretKey: SecretKey<A>;
24
24
  }
25
- /** Opciones de firma/verificación (FIPS 204 §5.2, context string opcional). */
25
+ /** Signing/verification options (FIPS 204 §5.2, optional context string). */
26
26
  interface SignatureOptions {
27
- /** Context string de hasta 255 bytes. Default: vacío. */
27
+ /** Context string of up to 255 bytes. Default: empty. */
28
28
  readonly context?: Uint8Array;
29
29
  }
30
30
 
31
31
  /**
32
- * Cifrado híbrido: encapsula un secreto con ML-KEM-768 (FIPS 203) y cifra los
33
- * datos con AES-256-GCM usando ese secreto. El resultado es un único
34
- * `Uint8Array` autocontenido que solo {@link decrypt} puede abrir.
32
+ * Hybrid encryption: encapsulates a secret with ML-KEM-768 (FIPS 203) and
33
+ * encrypts the data with AES-256-GCM using that secret. The result is a
34
+ * single self-contained `Uint8Array` that only {@link decrypt} can open.
35
35
  *
36
36
  * @example
37
37
  * ```ts
38
38
  * import { pqc } from '@pqc-sdk/core';
39
39
  *
40
40
  * const pair = await pqc.keys.generate();
41
- * const ciphertext = await pqc.encrypt('dato sensible', pair.publicKey);
41
+ * const ciphertext = await pqc.encrypt('sensitive data', pair.publicKey);
42
42
  * ```
43
43
  */
44
44
  declare function encrypt(data: Uint8Array | string, publicKey: PublicKey<'ml-kem-768'>): Promise<Uint8Array>;
45
45
  /**
46
- * Descifra un ciphertext producido por {@link encrypt}. Si el ciphertext fue
47
- * manipulado o la key no corresponde, lanza {@link PqcError} con código
48
- * `DECRYPTION_FAILED` — nunca devuelve datos corruptos.
46
+ * Decrypts a ciphertext produced by {@link encrypt}. If the ciphertext was
47
+ * tampered with or the key does not match, it throws {@link PqcError} with
48
+ * code `DECRYPTION_FAILED` — it never returns corrupted data.
49
49
  *
50
50
  * @example
51
51
  * ```ts
@@ -57,14 +57,14 @@ declare function encrypt(data: Uint8Array | string, publicKey: PublicKey<'ml-kem
57
57
  */
58
58
  declare function decrypt(ciphertext: Uint8Array, secretKey: SecretKey<'ml-kem-768'>): Promise<Uint8Array>;
59
59
 
60
- /** Opciones de {@link generate}. */
60
+ /** Options for {@link generate}. */
61
61
  interface GenerateOptions<A extends Algorithm = Algorithm> {
62
- /** Algoritmo del par. Default: `'ml-kem-768'` (cifrado). */
62
+ /** Algorithm of the pair. Default: `'ml-kem-768'` (encryption). */
63
63
  readonly algorithm?: A;
64
64
  }
65
65
  /**
66
- * Genera un par de keys post-cuánticas. Sin opciones genera ML-KEM-768,
67
- * listo para `pqc.encrypt`.
66
+ * Generates a post-quantum key pair. With no options it generates ML-KEM-768,
67
+ * ready for `pqc.encrypt`.
68
68
  *
69
69
  * @example
70
70
  * ```ts
@@ -80,7 +80,7 @@ declare function generate<A extends Algorithm>(options: GenerateOptions<A> & {
80
80
  }): Promise<KeyPair<A>>;
81
81
  declare function generate(options?: GenerateOptions): Promise<KeyPair>;
82
82
  /**
83
- * Serializa una key a un string portable: `pqcv1.<algoritmo>.<uso>.<base64url>`.
83
+ * Serializes a key to a portable string: `pqcv1.<algorithm>.<use>.<base64url>`.
84
84
  *
85
85
  * @example
86
86
  * ```ts
@@ -93,53 +93,53 @@ declare function generate(options?: GenerateOptions): Promise<KeyPair>;
93
93
  */
94
94
  declare function serialize(key: PqcKey): string;
95
95
  /**
96
- * Reconstruye una key desde el formato de {@link serialize}. Valida versión,
97
- * algoritmo, uso y longitud; ante cualquier problema lanza {@link PqcError}
98
- * con código `INVALID_SERIALIZED_KEY` o `INVALID_KEY`.
96
+ * Rebuilds a key from the {@link serialize} format. Validates version,
97
+ * algorithm, use and length; on any problem it throws {@link PqcError} with
98
+ * code `INVALID_SERIALIZED_KEY` or `INVALID_KEY`.
99
99
  *
100
100
  * @example
101
101
  * ```ts
102
102
  * import { pqc } from '@pqc-sdk/core';
103
103
  *
104
- * const publicKey = pqc.keys.deserialize(tokenRecibidoDelCliente);
104
+ * const publicKey = pqc.keys.deserialize(tokenReceivedFromClient);
105
105
  * const ciphertext = await pqc.encrypt(payload, publicKey);
106
106
  * ```
107
107
  */
108
108
  declare function deserialize(serialized: string): PqcKey;
109
109
 
110
110
  /**
111
- * Firma datos con ML-DSA-65 (FIPS 204), modo hedged (firma aleatorizada,
112
- * el default del estándar). Devuelve la firma de 3309 bytes.
111
+ * Signs data with ML-DSA-65 (FIPS 204) in hedged mode (randomized signing,
112
+ * the standard's default). Returns the 3309-byte signature.
113
113
  *
114
114
  * @example
115
115
  * ```ts
116
116
  * import { pqc } from '@pqc-sdk/core';
117
117
  *
118
118
  * const pair = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });
119
- * const signature = await pqc.sign(documento, pair.secretKey);
119
+ * const signature = await pqc.sign(document, pair.secretKey);
120
120
  * ```
121
121
  */
122
122
  declare function sign(data: Uint8Array | string, secretKey: SecretKey<'ml-dsa-65'>, options?: SignatureOptions): Promise<Uint8Array>;
123
123
  /**
124
- * Verifica una firma ML-DSA-65. Devuelve `false` ante firmas inválidas o
125
- * malformadas (nunca lanza por una firma corrupta); solo lanza si la key
126
- * no es ML-DSA.
124
+ * Verifies an ML-DSA-65 signature. Returns `false` for invalid or malformed
125
+ * signatures (it never throws because of a corrupted signature); it only
126
+ * throws if the key is not ML-DSA.
127
127
  *
128
128
  * @example
129
129
  * ```ts
130
130
  * import { pqc } from '@pqc-sdk/core';
131
131
  *
132
- * const valid = await pqc.verify(documento, signature, pair.publicKey);
133
- * if (!valid) throw new Error('firma inválida');
132
+ * const valid = await pqc.verify(document, signature, pair.publicKey);
133
+ * if (!valid) throw new Error('invalid signature');
134
134
  * ```
135
135
  */
136
136
  declare function verify(data: Uint8Array | string, signature: Uint8Array, publicKey: PublicKey<'ml-dsa-65'>, options?: SignatureOptions): Promise<boolean>;
137
137
 
138
- /** Códigos de error que puede emitir el SDK. */
138
+ /** Error codes the SDK can emit. */
139
139
  type PqcErrorCode = 'UNSUPPORTED_ALGORITHM' | 'WRONG_ALGORITHM' | 'WRONG_KEY_USE' | 'INVALID_KEY' | 'INVALID_SERIALIZED_KEY' | 'INVALID_CIPHERTEXT' | 'DECRYPTION_FAILED';
140
140
  /**
141
- * Error tipado del SDK. Toda falla esperable expone un `code` estable para
142
- * manejarla programáticamente sin parsear mensajes.
141
+ * Typed SDK error. Every expected failure exposes a stable `code` so it can
142
+ * be handled programmatically without parsing messages.
143
143
  *
144
144
  * @example
145
145
  * ```ts
@@ -149,7 +149,7 @@ type PqcErrorCode = 'UNSUPPORTED_ALGORITHM' | 'WRONG_ALGORITHM' | 'WRONG_KEY_USE
149
149
  * await pqc.decrypt(ciphertext, secretKey);
150
150
  * } catch (error) {
151
151
  * if (error instanceof PqcError && error.code === 'DECRYPTION_FAILED') {
152
- * // ciphertext manipulado o key incorrecta
152
+ * // tampered ciphertext or wrong key
153
153
  * }
154
154
  * }
155
155
  * ```
@@ -160,18 +160,18 @@ declare class PqcError extends Error {
160
160
  }
161
161
 
162
162
  /**
163
- * Versión del SDK.
163
+ * SDK version.
164
164
  *
165
165
  * @example
166
166
  * ```ts
167
167
  * import { version } from '@pqc-sdk/core';
168
168
  *
169
- * console.log(version); // "0.0.1"
169
+ * console.log(version); // e.g. "0.1.0"
170
170
  * ```
171
171
  */
172
- declare const version = "0.0.1";
172
+ declare const version: string;
173
173
  /**
174
- * Algoritmos PQC implementados (FIPS 203 y FIPS 204).
174
+ * Implemented PQC algorithms (FIPS 203 and FIPS 204).
175
175
  *
176
176
  * @example
177
177
  * ```ts
@@ -183,22 +183,22 @@ declare const version = "0.0.1";
183
183
  declare const SUPPORTED_ALGORITHMS: readonly ["ml-kem-768", "ml-dsa-65"];
184
184
  type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];
185
185
  /**
186
- * Punto de entrada del SDK: cifrado híbrido post-cuántico y firmas digitales
187
- * con defaults seguros, sin configuración.
186
+ * SDK entry point: post-quantum hybrid encryption and digital signatures
187
+ * with safe defaults, zero configuration.
188
188
  *
189
189
  * @example
190
190
  * ```ts
191
191
  * import { pqc } from '@pqc-sdk/core';
192
192
  *
193
- * // Cifrado (ML-KEM-768 + AES-256-GCM)
193
+ * // Encryption (ML-KEM-768 + AES-256-GCM)
194
194
  * const pair = await pqc.keys.generate();
195
- * const ciphertext = await pqc.encrypt('hola', pair.publicKey);
195
+ * const ciphertext = await pqc.encrypt('hello', pair.publicKey);
196
196
  * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);
197
197
  *
198
- * // Firmas (ML-DSA-65)
198
+ * // Signatures (ML-DSA-65)
199
199
  * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });
200
- * const signature = await pqc.sign('documento', signer.secretKey);
201
- * await pqc.verify('documento', signature, signer.publicKey); // true
200
+ * const signature = await pqc.sign('document', signer.secretKey);
201
+ * await pqc.verify('document', signature, signer.publicKey); // true
202
202
  * ```
203
203
  */
204
204
  declare const pqc: {
package/dist/index.d.ts CHANGED
@@ -1,51 +1,51 @@
1
- /** Algoritmo de encapsulamiento de claves (cifrado híbrido). */
1
+ /** Key encapsulation algorithm (hybrid encryption). */
2
2
  type KemAlgorithm = 'ml-kem-768';
3
- /** Algoritmo de firma digital. */
3
+ /** Digital signature algorithm. */
4
4
  type SignatureAlgorithm = 'ml-dsa-65';
5
- /** Algoritmos soportados por el SDK. */
5
+ /** Algorithms supported by the SDK. */
6
6
  type Algorithm = KemAlgorithm | SignatureAlgorithm;
7
- /** Rol de una key dentro de su par. */
7
+ /** Role of a key within its pair. */
8
8
  type KeyUse = 'public' | 'secret';
9
- /** Key del SDK: bytes crudos más metadata de algoritmo y uso. */
9
+ /** SDK key: raw bytes plus algorithm and use metadata. */
10
10
  interface PqcKey<A extends Algorithm = Algorithm, U extends KeyUse = KeyUse> {
11
11
  readonly algorithm: A;
12
12
  readonly use: U;
13
13
  readonly bytes: Uint8Array;
14
14
  }
15
- /** Key pública, segura de compartir. */
15
+ /** Public key, safe to share. */
16
16
  type PublicKey<A extends Algorithm = Algorithm> = PqcKey<A, 'public'>;
17
- /** Key secreta. Nunca debe salir del entorno del dueño. */
17
+ /** Secret key. Must never leave its owner's environment. */
18
18
  type SecretKey<A extends Algorithm = Algorithm> = PqcKey<A, 'secret'>;
19
- /** Par de keys generado por `pqc.keys.generate`. */
19
+ /** Key pair produced by `pqc.keys.generate`. */
20
20
  interface KeyPair<A extends Algorithm = Algorithm> {
21
21
  readonly algorithm: A;
22
22
  readonly publicKey: PublicKey<A>;
23
23
  readonly secretKey: SecretKey<A>;
24
24
  }
25
- /** Opciones de firma/verificación (FIPS 204 §5.2, context string opcional). */
25
+ /** Signing/verification options (FIPS 204 §5.2, optional context string). */
26
26
  interface SignatureOptions {
27
- /** Context string de hasta 255 bytes. Default: vacío. */
27
+ /** Context string of up to 255 bytes. Default: empty. */
28
28
  readonly context?: Uint8Array;
29
29
  }
30
30
 
31
31
  /**
32
- * Cifrado híbrido: encapsula un secreto con ML-KEM-768 (FIPS 203) y cifra los
33
- * datos con AES-256-GCM usando ese secreto. El resultado es un único
34
- * `Uint8Array` autocontenido que solo {@link decrypt} puede abrir.
32
+ * Hybrid encryption: encapsulates a secret with ML-KEM-768 (FIPS 203) and
33
+ * encrypts the data with AES-256-GCM using that secret. The result is a
34
+ * single self-contained `Uint8Array` that only {@link decrypt} can open.
35
35
  *
36
36
  * @example
37
37
  * ```ts
38
38
  * import { pqc } from '@pqc-sdk/core';
39
39
  *
40
40
  * const pair = await pqc.keys.generate();
41
- * const ciphertext = await pqc.encrypt('dato sensible', pair.publicKey);
41
+ * const ciphertext = await pqc.encrypt('sensitive data', pair.publicKey);
42
42
  * ```
43
43
  */
44
44
  declare function encrypt(data: Uint8Array | string, publicKey: PublicKey<'ml-kem-768'>): Promise<Uint8Array>;
45
45
  /**
46
- * Descifra un ciphertext producido por {@link encrypt}. Si el ciphertext fue
47
- * manipulado o la key no corresponde, lanza {@link PqcError} con código
48
- * `DECRYPTION_FAILED` — nunca devuelve datos corruptos.
46
+ * Decrypts a ciphertext produced by {@link encrypt}. If the ciphertext was
47
+ * tampered with or the key does not match, it throws {@link PqcError} with
48
+ * code `DECRYPTION_FAILED` — it never returns corrupted data.
49
49
  *
50
50
  * @example
51
51
  * ```ts
@@ -57,14 +57,14 @@ declare function encrypt(data: Uint8Array | string, publicKey: PublicKey<'ml-kem
57
57
  */
58
58
  declare function decrypt(ciphertext: Uint8Array, secretKey: SecretKey<'ml-kem-768'>): Promise<Uint8Array>;
59
59
 
60
- /** Opciones de {@link generate}. */
60
+ /** Options for {@link generate}. */
61
61
  interface GenerateOptions<A extends Algorithm = Algorithm> {
62
- /** Algoritmo del par. Default: `'ml-kem-768'` (cifrado). */
62
+ /** Algorithm of the pair. Default: `'ml-kem-768'` (encryption). */
63
63
  readonly algorithm?: A;
64
64
  }
65
65
  /**
66
- * Genera un par de keys post-cuánticas. Sin opciones genera ML-KEM-768,
67
- * listo para `pqc.encrypt`.
66
+ * Generates a post-quantum key pair. With no options it generates ML-KEM-768,
67
+ * ready for `pqc.encrypt`.
68
68
  *
69
69
  * @example
70
70
  * ```ts
@@ -80,7 +80,7 @@ declare function generate<A extends Algorithm>(options: GenerateOptions<A> & {
80
80
  }): Promise<KeyPair<A>>;
81
81
  declare function generate(options?: GenerateOptions): Promise<KeyPair>;
82
82
  /**
83
- * Serializa una key a un string portable: `pqcv1.<algoritmo>.<uso>.<base64url>`.
83
+ * Serializes a key to a portable string: `pqcv1.<algorithm>.<use>.<base64url>`.
84
84
  *
85
85
  * @example
86
86
  * ```ts
@@ -93,53 +93,53 @@ declare function generate(options?: GenerateOptions): Promise<KeyPair>;
93
93
  */
94
94
  declare function serialize(key: PqcKey): string;
95
95
  /**
96
- * Reconstruye una key desde el formato de {@link serialize}. Valida versión,
97
- * algoritmo, uso y longitud; ante cualquier problema lanza {@link PqcError}
98
- * con código `INVALID_SERIALIZED_KEY` o `INVALID_KEY`.
96
+ * Rebuilds a key from the {@link serialize} format. Validates version,
97
+ * algorithm, use and length; on any problem it throws {@link PqcError} with
98
+ * code `INVALID_SERIALIZED_KEY` or `INVALID_KEY`.
99
99
  *
100
100
  * @example
101
101
  * ```ts
102
102
  * import { pqc } from '@pqc-sdk/core';
103
103
  *
104
- * const publicKey = pqc.keys.deserialize(tokenRecibidoDelCliente);
104
+ * const publicKey = pqc.keys.deserialize(tokenReceivedFromClient);
105
105
  * const ciphertext = await pqc.encrypt(payload, publicKey);
106
106
  * ```
107
107
  */
108
108
  declare function deserialize(serialized: string): PqcKey;
109
109
 
110
110
  /**
111
- * Firma datos con ML-DSA-65 (FIPS 204), modo hedged (firma aleatorizada,
112
- * el default del estándar). Devuelve la firma de 3309 bytes.
111
+ * Signs data with ML-DSA-65 (FIPS 204) in hedged mode (randomized signing,
112
+ * the standard's default). Returns the 3309-byte signature.
113
113
  *
114
114
  * @example
115
115
  * ```ts
116
116
  * import { pqc } from '@pqc-sdk/core';
117
117
  *
118
118
  * const pair = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });
119
- * const signature = await pqc.sign(documento, pair.secretKey);
119
+ * const signature = await pqc.sign(document, pair.secretKey);
120
120
  * ```
121
121
  */
122
122
  declare function sign(data: Uint8Array | string, secretKey: SecretKey<'ml-dsa-65'>, options?: SignatureOptions): Promise<Uint8Array>;
123
123
  /**
124
- * Verifica una firma ML-DSA-65. Devuelve `false` ante firmas inválidas o
125
- * malformadas (nunca lanza por una firma corrupta); solo lanza si la key
126
- * no es ML-DSA.
124
+ * Verifies an ML-DSA-65 signature. Returns `false` for invalid or malformed
125
+ * signatures (it never throws because of a corrupted signature); it only
126
+ * throws if the key is not ML-DSA.
127
127
  *
128
128
  * @example
129
129
  * ```ts
130
130
  * import { pqc } from '@pqc-sdk/core';
131
131
  *
132
- * const valid = await pqc.verify(documento, signature, pair.publicKey);
133
- * if (!valid) throw new Error('firma inválida');
132
+ * const valid = await pqc.verify(document, signature, pair.publicKey);
133
+ * if (!valid) throw new Error('invalid signature');
134
134
  * ```
135
135
  */
136
136
  declare function verify(data: Uint8Array | string, signature: Uint8Array, publicKey: PublicKey<'ml-dsa-65'>, options?: SignatureOptions): Promise<boolean>;
137
137
 
138
- /** Códigos de error que puede emitir el SDK. */
138
+ /** Error codes the SDK can emit. */
139
139
  type PqcErrorCode = 'UNSUPPORTED_ALGORITHM' | 'WRONG_ALGORITHM' | 'WRONG_KEY_USE' | 'INVALID_KEY' | 'INVALID_SERIALIZED_KEY' | 'INVALID_CIPHERTEXT' | 'DECRYPTION_FAILED';
140
140
  /**
141
- * Error tipado del SDK. Toda falla esperable expone un `code` estable para
142
- * manejarla programáticamente sin parsear mensajes.
141
+ * Typed SDK error. Every expected failure exposes a stable `code` so it can
142
+ * be handled programmatically without parsing messages.
143
143
  *
144
144
  * @example
145
145
  * ```ts
@@ -149,7 +149,7 @@ type PqcErrorCode = 'UNSUPPORTED_ALGORITHM' | 'WRONG_ALGORITHM' | 'WRONG_KEY_USE
149
149
  * await pqc.decrypt(ciphertext, secretKey);
150
150
  * } catch (error) {
151
151
  * if (error instanceof PqcError && error.code === 'DECRYPTION_FAILED') {
152
- * // ciphertext manipulado o key incorrecta
152
+ * // tampered ciphertext or wrong key
153
153
  * }
154
154
  * }
155
155
  * ```
@@ -160,18 +160,18 @@ declare class PqcError extends Error {
160
160
  }
161
161
 
162
162
  /**
163
- * Versión del SDK.
163
+ * SDK version.
164
164
  *
165
165
  * @example
166
166
  * ```ts
167
167
  * import { version } from '@pqc-sdk/core';
168
168
  *
169
- * console.log(version); // "0.0.1"
169
+ * console.log(version); // e.g. "0.1.0"
170
170
  * ```
171
171
  */
172
- declare const version = "0.0.1";
172
+ declare const version: string;
173
173
  /**
174
- * Algoritmos PQC implementados (FIPS 203 y FIPS 204).
174
+ * Implemented PQC algorithms (FIPS 203 and FIPS 204).
175
175
  *
176
176
  * @example
177
177
  * ```ts
@@ -183,22 +183,22 @@ declare const version = "0.0.1";
183
183
  declare const SUPPORTED_ALGORITHMS: readonly ["ml-kem-768", "ml-dsa-65"];
184
184
  type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];
185
185
  /**
186
- * Punto de entrada del SDK: cifrado híbrido post-cuántico y firmas digitales
187
- * con defaults seguros, sin configuración.
186
+ * SDK entry point: post-quantum hybrid encryption and digital signatures
187
+ * with safe defaults, zero configuration.
188
188
  *
189
189
  * @example
190
190
  * ```ts
191
191
  * import { pqc } from '@pqc-sdk/core';
192
192
  *
193
- * // Cifrado (ML-KEM-768 + AES-256-GCM)
193
+ * // Encryption (ML-KEM-768 + AES-256-GCM)
194
194
  * const pair = await pqc.keys.generate();
195
- * const ciphertext = await pqc.encrypt('hola', pair.publicKey);
195
+ * const ciphertext = await pqc.encrypt('hello', pair.publicKey);
196
196
  * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);
197
197
  *
198
- * // Firmas (ML-DSA-65)
198
+ * // Signatures (ML-DSA-65)
199
199
  * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });
200
- * const signature = await pqc.sign('documento', signer.secretKey);
201
- * await pqc.verify('documento', signature, signer.publicKey); // true
200
+ * const signature = await pqc.sign('document', signer.secretKey);
201
+ * await pqc.verify('document', signature, signer.publicKey); // true
202
202
  * ```
203
203
  */
204
204
  declare const pqc: {
package/dist/index.js CHANGED
@@ -45,7 +45,7 @@ var ALGORITHMS = {
45
45
  function getAlgorithm(algorithm) {
46
46
  const spec = ALGORITHMS[algorithm];
47
47
  if (!spec) {
48
- throw new PqcError("UNSUPPORTED_ALGORITHM", `Algoritmo no soportado: ${algorithm}`);
48
+ throw new PqcError("UNSUPPORTED_ALGORITHM", `Unsupported algorithm: ${algorithm}`);
49
49
  }
50
50
  return spec;
51
51
  }
@@ -57,16 +57,16 @@ function requireKey(key, kind, use, operation) {
57
57
  if (spec.kind !== kind) {
58
58
  throw new PqcError(
59
59
  "WRONG_ALGORITHM",
60
- `${operation} requiere una key ${kind === "kem" ? "ML-KEM" : "ML-DSA"}, recibi\xF3 ${key.algorithm}`
60
+ `${operation} requires an ${kind === "kem" ? "ML-KEM" : "ML-DSA"} key, got ${key.algorithm}`
61
61
  );
62
62
  }
63
63
  if (key.use !== use) {
64
- throw new PqcError("WRONG_KEY_USE", `${operation} requiere la key ${use}, recibi\xF3 ${key.use}`);
64
+ throw new PqcError("WRONG_KEY_USE", `${operation} requires the ${use} key, got ${key.use}`);
65
65
  }
66
66
  if (key.bytes.length !== keyLengthFor(spec, use)) {
67
67
  throw new PqcError(
68
68
  "INVALID_KEY",
69
- `Key ${key.algorithm} ${use} con longitud inv\xE1lida: ${key.bytes.length}`
69
+ `${key.algorithm} ${use} key has invalid length: ${key.bytes.length}`
70
70
  );
71
71
  }
72
72
  return spec;
@@ -98,12 +98,15 @@ async function decrypt(ciphertext, secretKey) {
98
98
  const spec = requireKey(secretKey, "kem", "secret", "decrypt");
99
99
  const minLength = 2 + spec.ciphertextLength + NONCE_LENGTH + GCM_TAG_LENGTH;
100
100
  if (ciphertext.length < minLength) {
101
- throw new PqcError("INVALID_CIPHERTEXT", "Ciphertext truncado o no producido por pqc.encrypt");
101
+ throw new PqcError(
102
+ "INVALID_CIPHERTEXT",
103
+ "Ciphertext is truncated or was not produced by pqc.encrypt"
104
+ );
102
105
  }
103
106
  if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {
104
107
  throw new PqcError(
105
108
  "INVALID_CIPHERTEXT",
106
- "Header desconocido: el ciphertext no corresponde a esta versi\xF3n o algoritmo"
109
+ "Unknown header: the ciphertext does not match this version or algorithm"
107
110
  );
108
111
  }
109
112
  const kemCiphertext = ciphertext.subarray(2, 2 + spec.ciphertextLength);
@@ -118,7 +121,7 @@ async function decrypt(ciphertext, secretKey) {
118
121
  } catch {
119
122
  throw new PqcError(
120
123
  "DECRYPTION_FAILED",
121
- "No se pudo descifrar: ciphertext manipulado o secret key incorrecta"
124
+ "Decryption failed: tampered ciphertext or wrong secret key"
122
125
  );
123
126
  }
124
127
  }
@@ -145,7 +148,7 @@ function toBase64Url(bytes) {
145
148
  }
146
149
  function fromBase64Url(encoded) {
147
150
  if (encoded.length % 4 === 1) {
148
- throw new TypeError("base64url inv\xE1lido: longitud imposible");
151
+ throw new TypeError("Invalid base64url: impossible length");
149
152
  }
150
153
  const out = new Uint8Array(Math.floor(encoded.length * 3 / 4));
151
154
  let outIndex = 0;
@@ -154,7 +157,7 @@ function fromBase64Url(encoded) {
154
157
  for (const char of encoded) {
155
158
  const value = CHAR_TO_VALUE.get(char);
156
159
  if (value === void 0) {
157
- throw new TypeError(`base64url inv\xE1lido: car\xE1cter ${JSON.stringify(char)}`);
160
+ throw new TypeError(`Invalid base64url: character ${JSON.stringify(char)}`);
158
161
  }
159
162
  buffer = buffer << 6 | value;
160
163
  bits += 6;
@@ -178,7 +181,7 @@ function generateKeyPairFromSeed(algorithm, seed) {
178
181
  if (seed.length !== spec.seedLength) {
179
182
  throw new PqcError(
180
183
  "INVALID_KEY",
181
- `Seed de ${algorithm} debe medir ${spec.seedLength} bytes, recibi\xF3 ${seed.length}`
184
+ `${algorithm} seed must be ${spec.seedLength} bytes, got ${seed.length}`
182
185
  );
183
186
  }
184
187
  const material = spec.kind === "kem" ? spec.kem.keygen(seed) : spec.signer.keygen(seed);
@@ -191,7 +194,7 @@ function generateKeyPairFromSeed(algorithm, seed) {
191
194
  function serialize(key) {
192
195
  const spec = getAlgorithm(key.algorithm);
193
196
  if (key.bytes.length !== keyLengthFor(spec, key.use)) {
194
- throw new PqcError("INVALID_KEY", `Key ${key.algorithm} ${key.use} con longitud inv\xE1lida`);
197
+ throw new PqcError("INVALID_KEY", `${key.algorithm} ${key.use} key has invalid length`);
195
198
  }
196
199
  return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;
197
200
  }
@@ -200,13 +203,13 @@ function deserialize(serialized) {
200
203
  if (parts.length !== 4 || parts[0] !== SERIAL_PREFIX) {
201
204
  throw new PqcError(
202
205
  "INVALID_SERIALIZED_KEY",
203
- "Formato esperado: pqcv1.<algoritmo>.<uso>.<base64url>"
206
+ "Expected format: pqcv1.<algorithm>.<use>.<base64url>"
204
207
  );
205
208
  }
206
209
  const [, algorithm, use, encoded] = parts;
207
210
  const spec = getAlgorithm(algorithm);
208
211
  if (use !== "public" && use !== "secret") {
209
- throw new PqcError("INVALID_SERIALIZED_KEY", `Uso de key desconocido: ${use}`);
212
+ throw new PqcError("INVALID_SERIALIZED_KEY", `Unknown key use: ${use}`);
210
213
  }
211
214
  let bytes;
212
215
  try {
@@ -214,14 +217,14 @@ function deserialize(serialized) {
214
217
  } catch (cause) {
215
218
  throw new PqcError(
216
219
  "INVALID_SERIALIZED_KEY",
217
- cause instanceof Error ? cause.message : "base64url inv\xE1lido"
220
+ cause instanceof Error ? cause.message : "Invalid base64url"
218
221
  );
219
222
  }
220
223
  const key = { algorithm, use, bytes };
221
224
  if (bytes.length !== keyLengthFor(spec, key.use)) {
222
225
  throw new PqcError(
223
226
  "INVALID_KEY",
224
- `Key ${algorithm} ${use} debe medir ${keyLengthFor(spec, key.use)} bytes, midi\xF3 ${bytes.length}`
227
+ `${algorithm} ${use} key must be ${keyLengthFor(spec, key.use)} bytes, got ${bytes.length}`
225
228
  );
226
229
  }
227
230
  return key;
@@ -251,7 +254,7 @@ async function verify(data, signature, publicKey, options) {
251
254
  }
252
255
 
253
256
  // src/index.ts
254
- var version = "0.0.1";
257
+ var version = "0.1.2";
255
258
  var SUPPORTED_ALGORITHMS = ["ml-kem-768", "ml-dsa-65"];
256
259
  var pqc = {
257
260
  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 * Hybrid encryption: encapsulates a secret with ML-KEM-768 (FIPS 203) and\n * encrypts the data with AES-256-GCM using that secret. The result is a\n * single self-contained `Uint8Array` that only {@link decrypt} can open.\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('sensitive data', 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 * Decrypts a ciphertext produced by {@link encrypt}. If the ciphertext was\n * tampered with or the key does not match, it throws {@link PqcError} with\n * code `DECRYPTION_FAILED` — it never returns corrupted data.\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(\n 'INVALID_CIPHERTEXT',\n 'Ciphertext is truncated or was not produced by pqc.encrypt',\n );\n }\n if (ciphertext[0] !== FORMAT_VERSION || ciphertext[1] !== spec.headerId) {\n throw new PqcError(\n 'INVALID_CIPHERTEXT',\n 'Unknown header: the ciphertext does not match this version or algorithm',\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 'Decryption failed: tampered ciphertext or wrong secret key',\n );\n }\n}\n\n/** Available KEM algorithms, exported for introspection. */\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', `Unsupported algorithm: ${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/** Validates a key's algorithm, use and length before operating with it. */\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} requires an ${kind === 'kem' ? 'ML-KEM' : 'ML-DSA'} key, got ${key.algorithm}`,\n );\n }\n if (key.use !== use) {\n throw new PqcError('WRONG_KEY_USE', `${operation} requires the ${use} key, got ${key.use}`);\n }\n if (key.bytes.length !== keyLengthFor(spec, use)) {\n throw new PqcError(\n 'INVALID_KEY',\n `${key.algorithm} ${use} key has invalid length: ${key.bytes.length}`,\n );\n }\n return spec as K extends 'kem' ? KemSpec : SignerSpec;\n}\n","/** Error codes the SDK can emit. */\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 * Typed SDK error. Every expected failure exposes a stable `code` so it can\n * be handled programmatically without parsing messages.\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 * // tampered ciphertext or wrong key\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/** Options for {@link generate}. */\nexport interface GenerateOptions<A extends Algorithm = Algorithm> {\n /** Algorithm of the pair. Default: `'ml-kem-768'` (encryption). */\n readonly algorithm?: A;\n}\n\n/**\n * Generates a post-quantum key pair. With no options it generates ML-KEM-768,\n * ready for `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 * Deterministic generation from a seed. Internal and test use (NIST vectors).\n * Prefer {@link generate} for normal use.\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 `${algorithm} seed must be ${spec.seedLength} bytes, got ${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 * Serializes a key to a portable string: `pqcv1.<algorithm>.<use>.<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.algorithm} ${key.use} key has invalid length`);\n }\n return `${SERIAL_PREFIX}.${key.algorithm}.${key.use}.${toBase64Url(key.bytes)}`;\n}\n\n/**\n * Rebuilds a key from the {@link serialize} format. Validates version,\n * algorithm, use and length; on any problem it throws {@link PqcError} with\n * code `INVALID_SERIALIZED_KEY` or `INVALID_KEY`.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const publicKey = pqc.keys.deserialize(tokenReceivedFromClient);\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 'Expected format: pqcv1.<algorithm>.<use>.<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', `Unknown key use: ${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 : 'Invalid base64url',\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 `${algorithm} ${use} key must be ${keyLengthFor(spec, key.use)} bytes, got ${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/** Encodes bytes to unpadded base64url. Pure implementation, no 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/** Decodes unpadded base64url. Throws TypeError on invalid characters. */\nexport function fromBase64Url(encoded: string): Uint8Array {\n if (encoded.length % 4 === 1) {\n throw new TypeError('Invalid base64url: impossible length');\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(`Invalid base64url: character ${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 * Signs data with ML-DSA-65 (FIPS 204) in hedged mode (randomized signing,\n * the standard's default). Returns the 3309-byte signature.\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(document, 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 * Verifies an ML-DSA-65 signature. Returns `false` for invalid or malformed\n * signatures (it never throws because of a corrupted signature); it only\n * throws if the key is not ML-DSA.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * const valid = await pqc.verify(document, signature, pair.publicKey);\n * if (!valid) throw new Error('invalid signature');\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// Injected at build time from package.json (`define` in tsup.config.ts and vitest.config.ts).\ndeclare const __PQC_CORE_VERSION__: string;\n\n/**\n * SDK version.\n *\n * @example\n * ```ts\n * import { version } from '@pqc-sdk/core';\n *\n * console.log(version); // e.g. \"0.1.0\"\n * ```\n */\nexport const version = __PQC_CORE_VERSION__;\n\n/**\n * Implemented PQC algorithms (FIPS 203 and 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 * SDK entry point: post-quantum hybrid encryption and digital signatures\n * with safe defaults, zero configuration.\n *\n * @example\n * ```ts\n * import { pqc } from '@pqc-sdk/core';\n *\n * // Encryption (ML-KEM-768 + AES-256-GCM)\n * const pair = await pqc.keys.generate();\n * const ciphertext = await pqc.encrypt('hello', pair.publicKey);\n * const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);\n *\n * // Signatures (ML-DSA-65)\n * const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });\n * const signature = await pqc.sign('document', signer.secretKey);\n * await pqc.verify('document', 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,7 +1,7 @@
1
1
  {
2
2
  "name": "@pqc-sdk/core",
3
- "version": "0.1.0",
4
- "description": "SDK de criptografía post-cuántica para JS/TS (ML-KEM, ML-DSA, SLH-DSA)",
3
+ "version": "0.1.2",
4
+ "description": "Post-quantum cryptography SDK for JS/TS (ML-KEM, ML-DSA, SLH-DSA)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
@@ -31,7 +31,7 @@
31
31
  "@noble/post-quantum": "^0.6.1"
32
32
  },
33
33
  "license": "MIT",
34
- "homepage": "https://github.com/jeloercc/pqc-sdk#readme",
34
+ "homepage": "https://jeloercc.github.io/pqc-sdk/",
35
35
  "bugs": "https://github.com/jeloercc/pqc-sdk/issues",
36
36
  "publishConfig": {
37
37
  "access": "public"
@@ -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
  }