claim169 0.2.0-alpha → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +40 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +157 -185
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +197 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +98 -9
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
- package/wasm/claim169_wasm.d.ts +19 -2
- package/wasm/claim169_wasm.js +1 -1
- package/wasm/claim169_wasm_bg.js +123 -95
- package/wasm/claim169_wasm_bg.wasm +0 -0
- package/wasm/claim169_wasm_bg.wasm.d.ts +4 -1
- package/wasm/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
*
|
|
84
84
|
* @module claim169
|
|
85
85
|
*/
|
|
86
|
-
export type { Algorithm, AlgorithmName, Biometric, CertificateHash, Claim169, Claim169Input, CwtMeta, CwtMetaInput, DecodeResult, DecryptorCallback, EncryptorCallback, IDecoder, IEncoder, SignerCallback, VerificationStatus, VerifierCallback, X509Headers, } from "./types.js";
|
|
87
|
-
export { Claim169Error } from "./types.js";
|
|
88
|
-
import type { Claim169Input, CwtMetaInput, DecodeResult, DecryptorCallback, EncryptorCallback, IDecoder, IEncoder, SignerCallback, VerifierCallback } from "./types.js";
|
|
86
|
+
export type { Algorithm, AlgorithmName, Biometric, CertificateHash, Claim169, Claim169ErrorCode, Claim169Input, CompressionMode, CoseType, CwtMeta, CwtMetaInput, DecodeResult, DetectedCompression, DecryptorCallback, EncodeResult, EncodeWarning, EncryptorCallback, IDecoder, IEncoder, InspectResult, SignerCallback, VerificationStatus, VerifierCallback, X509Headers, } from "./types.js";
|
|
87
|
+
export { BiometricFormat, Claim169Error, Gender, MaritalStatus, PhotoFormat, } from "./types.js";
|
|
88
|
+
import type { Claim169Input, CompressionMode, CwtMetaInput, DecodeResult, DecryptorCallback, EncodeResult, EncryptorCallback, IDecoder, IEncoder, InspectResult, SignerCallback, VerifierCallback } from "./types.js";
|
|
89
89
|
/**
|
|
90
90
|
* Get the library version
|
|
91
91
|
*/
|
|
@@ -200,7 +200,7 @@ export declare class Decoder implements IDecoder {
|
|
|
200
200
|
*/
|
|
201
201
|
skipBiometrics(): Decoder;
|
|
202
202
|
/**
|
|
203
|
-
*
|
|
203
|
+
* Re-enable timestamp validation (enabled by default).
|
|
204
204
|
* When enabled, expired or not-yet-valid credentials will throw an error.
|
|
205
205
|
* Implemented in the host (JavaScript) to avoid WASM runtime time limitations.
|
|
206
206
|
* @returns The decoder instance for chaining
|
|
@@ -277,6 +277,8 @@ export declare class Decoder implements IDecoder {
|
|
|
277
277
|
* Notes:
|
|
278
278
|
* - If you don't provide a verification key, you must explicitly set `allowUnverified: true` (testing only).
|
|
279
279
|
* - Timestamp validation is enabled by default in JS (host-side). Set `validateTimestamps: false` to disable.
|
|
280
|
+
* - PEM keys and custom verifier/decryptor callbacks are not supported here.
|
|
281
|
+
* Use the `Decoder` builder class directly for those features.
|
|
280
282
|
*/
|
|
281
283
|
export interface DecodeOptions {
|
|
282
284
|
verifyWithEd25519?: Uint8Array;
|
|
@@ -403,15 +405,46 @@ export declare class Encoder implements IEncoder {
|
|
|
403
405
|
*/
|
|
404
406
|
encryptWith(encryptor: EncryptorCallback, algorithm: "A256GCM" | "A128GCM"): Encoder;
|
|
405
407
|
/**
|
|
406
|
-
*
|
|
407
|
-
* @
|
|
408
|
+
* Set compression mode for encoding.
|
|
409
|
+
* @param mode - Compression mode: "zlib", "none", "adaptive", "brotli:N" (0-11), or "adaptive-brotli:N"
|
|
410
|
+
* @returns The encoder instance for chaining
|
|
411
|
+
* @throws {Claim169Error} If the mode is invalid or unsupported by the WASM build
|
|
412
|
+
*/
|
|
413
|
+
compression(mode: CompressionMode): Encoder;
|
|
414
|
+
/**
|
|
415
|
+
* Encode the credential to a QR-ready result object.
|
|
416
|
+
* @returns Encode result with QR data, compression info, and warnings
|
|
408
417
|
* @throws {Claim169Error} If encoding fails
|
|
409
418
|
*/
|
|
410
|
-
encode():
|
|
419
|
+
encode(): EncodeResult;
|
|
411
420
|
}
|
|
412
421
|
/**
|
|
413
422
|
* Generate a random 12-byte nonce for AES-GCM encryption.
|
|
414
423
|
* @returns A 12-byte Uint8Array suitable for use as a nonce
|
|
415
424
|
*/
|
|
416
425
|
export declare function generateNonce(): Uint8Array;
|
|
426
|
+
/**
|
|
427
|
+
* Inspect credential metadata without full decoding or verification.
|
|
428
|
+
*
|
|
429
|
+
* Extracts metadata (issuer, key ID, algorithm, expiration) from a QR code
|
|
430
|
+
* without verifying the signature. Useful for multi-issuer key lookup.
|
|
431
|
+
*
|
|
432
|
+
* For encrypted credentials (COSE_Encrypt0), only COSE-level headers are
|
|
433
|
+
* available; CWT-level fields (issuer, subject, expiresAt) will be `undefined`.
|
|
434
|
+
*
|
|
435
|
+
* @param qrText - The Base45-encoded QR code content
|
|
436
|
+
* @returns Metadata extracted from the credential
|
|
437
|
+
* @throws {Claim169Error} On parse errors
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* ```typescript
|
|
441
|
+
* import { inspect } from 'claim169';
|
|
442
|
+
*
|
|
443
|
+
* const meta = inspect(qrText);
|
|
444
|
+
* console.log(meta.issuer); // "https://issuer.example.com"
|
|
445
|
+
* console.log(meta.algorithm); // "EdDSA"
|
|
446
|
+
* console.log(meta.coseType); // "Sign1"
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
export declare function inspect(qrText: string): InspectResult;
|
|
417
450
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AAEH,YAAY,EACV,SAAS,EACT,aAAa,EACb,SAAS,EACT,eAAe,EACf,QAAQ,EACR,aAAa,EACb,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -83,10 +83,25 @@
|
|
|
83
83
|
*
|
|
84
84
|
* @module claim169
|
|
85
85
|
*/
|
|
86
|
-
export { Claim169Error } from "./types.js";
|
|
86
|
+
export { BiometricFormat, Claim169Error, Gender, MaritalStatus, PhotoFormat, } from "./types.js";
|
|
87
87
|
import { Claim169Error } from "./types.js";
|
|
88
88
|
// Import WASM module (auto-initialized with bundler target)
|
|
89
89
|
import * as wasm from "../wasm/claim169_wasm.js";
|
|
90
|
+
/**
|
|
91
|
+
* Wrap a WASM call so that any thrown error becomes a Claim169Error.
|
|
92
|
+
*/
|
|
93
|
+
function wrapWasmCall(fn) {
|
|
94
|
+
try {
|
|
95
|
+
return fn();
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
throw error instanceof Claim169Error
|
|
99
|
+
? error
|
|
100
|
+
: error instanceof Error
|
|
101
|
+
? new Claim169Error(error.message)
|
|
102
|
+
: new Claim169Error(String(error));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
90
105
|
/**
|
|
91
106
|
* Get the library version
|
|
92
107
|
*/
|
|
@@ -198,21 +213,39 @@ function transformX509Headers(raw) {
|
|
|
198
213
|
return headers;
|
|
199
214
|
}
|
|
200
215
|
/**
|
|
201
|
-
* Transform raw WASM result to typed DecodeResult
|
|
216
|
+
* Transform raw WASM result to typed DecodeResult.
|
|
217
|
+
* Performs runtime validation to catch malformed WASM output.
|
|
202
218
|
*/
|
|
203
219
|
function transformResult(raw) {
|
|
220
|
+
if (typeof raw !== "object" || raw === null) {
|
|
221
|
+
throw new Claim169Error("Malformed WASM output: expected object");
|
|
222
|
+
}
|
|
204
223
|
const result = raw;
|
|
224
|
+
if (typeof result.claim169 !== "object" || result.claim169 === null) {
|
|
225
|
+
throw new Claim169Error("Malformed WASM output: missing claim169");
|
|
226
|
+
}
|
|
227
|
+
if (typeof result.cwtMeta !== "object" || result.cwtMeta === null) {
|
|
228
|
+
throw new Claim169Error("Malformed WASM output: missing cwtMeta");
|
|
229
|
+
}
|
|
230
|
+
if (typeof result.verificationStatus !== "string") {
|
|
231
|
+
throw new Claim169Error("Malformed WASM output: missing verificationStatus");
|
|
232
|
+
}
|
|
233
|
+
const cwtMeta = result.cwtMeta;
|
|
205
234
|
return {
|
|
206
235
|
claim169: transformClaim169(result.claim169),
|
|
207
236
|
cwtMeta: {
|
|
208
|
-
issuer:
|
|
209
|
-
subject:
|
|
210
|
-
expiresAt:
|
|
211
|
-
notBefore:
|
|
212
|
-
issuedAt:
|
|
237
|
+
issuer: cwtMeta.issuer,
|
|
238
|
+
subject: cwtMeta.subject,
|
|
239
|
+
expiresAt: cwtMeta.expiresAt,
|
|
240
|
+
notBefore: cwtMeta.notBefore,
|
|
241
|
+
issuedAt: cwtMeta.issuedAt,
|
|
213
242
|
},
|
|
214
243
|
verificationStatus: result.verificationStatus,
|
|
215
244
|
x509Headers: transformX509Headers(result.x509Headers),
|
|
245
|
+
detectedCompression: (result.detectedCompression ?? "zlib"),
|
|
246
|
+
warnings: result.warnings ?? [],
|
|
247
|
+
keyId: safeUint8Array(result.keyId),
|
|
248
|
+
algorithm: result.algorithm,
|
|
216
249
|
};
|
|
217
250
|
}
|
|
218
251
|
/**
|
|
@@ -281,12 +314,18 @@ function transformBiometrics(raw) {
|
|
|
281
314
|
if (!raw || !Array.isArray(raw)) {
|
|
282
315
|
return undefined;
|
|
283
316
|
}
|
|
284
|
-
return raw.map((b) =>
|
|
285
|
-
data
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
317
|
+
return raw.map((b) => {
|
|
318
|
+
const data = safeUint8Array(b.data);
|
|
319
|
+
if (!data) {
|
|
320
|
+
throw new Claim169Error("Biometric entry missing data field");
|
|
321
|
+
}
|
|
322
|
+
return {
|
|
323
|
+
data,
|
|
324
|
+
format: b.format,
|
|
325
|
+
subFormat: b.subFormat,
|
|
326
|
+
issuer: b.issuer,
|
|
327
|
+
};
|
|
328
|
+
});
|
|
290
329
|
}
|
|
291
330
|
function validateTimestampsHost(cwtMeta, clockSkewToleranceSeconds) {
|
|
292
331
|
const skew = Math.max(0, Math.floor(clockSkewToleranceSeconds));
|
|
@@ -378,16 +417,8 @@ export class Decoder {
|
|
|
378
417
|
* @throws {Claim169Error} If the public key is invalid
|
|
379
418
|
*/
|
|
380
419
|
verifyWithEd25519(publicKey) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
return this;
|
|
384
|
-
}
|
|
385
|
-
catch (error) {
|
|
386
|
-
if (error instanceof Error) {
|
|
387
|
-
throw new Claim169Error(error.message);
|
|
388
|
-
}
|
|
389
|
-
throw new Claim169Error(String(error));
|
|
390
|
-
}
|
|
420
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEd25519(publicKey));
|
|
421
|
+
return this;
|
|
391
422
|
}
|
|
392
423
|
/**
|
|
393
424
|
* Verify signature with ECDSA P-256 public key.
|
|
@@ -396,16 +427,8 @@ export class Decoder {
|
|
|
396
427
|
* @throws {Claim169Error} If the public key is invalid
|
|
397
428
|
*/
|
|
398
429
|
verifyWithEcdsaP256(publicKey) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
return this;
|
|
402
|
-
}
|
|
403
|
-
catch (error) {
|
|
404
|
-
if (error instanceof Error) {
|
|
405
|
-
throw new Claim169Error(error.message);
|
|
406
|
-
}
|
|
407
|
-
throw new Claim169Error(String(error));
|
|
408
|
-
}
|
|
430
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEcdsaP256(publicKey));
|
|
431
|
+
return this;
|
|
409
432
|
}
|
|
410
433
|
/**
|
|
411
434
|
* Verify signature with Ed25519 public key in PEM format.
|
|
@@ -415,16 +438,8 @@ export class Decoder {
|
|
|
415
438
|
* @throws {Claim169Error} If the PEM is invalid
|
|
416
439
|
*/
|
|
417
440
|
verifyWithEd25519Pem(pem) {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
return this;
|
|
421
|
-
}
|
|
422
|
-
catch (error) {
|
|
423
|
-
if (error instanceof Error) {
|
|
424
|
-
throw new Claim169Error(error.message);
|
|
425
|
-
}
|
|
426
|
-
throw new Claim169Error(String(error));
|
|
427
|
-
}
|
|
441
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEd25519Pem(pem));
|
|
442
|
+
return this;
|
|
428
443
|
}
|
|
429
444
|
/**
|
|
430
445
|
* Verify signature with ECDSA P-256 public key in PEM format.
|
|
@@ -434,16 +449,8 @@ export class Decoder {
|
|
|
434
449
|
* @throws {Claim169Error} If the PEM is invalid
|
|
435
450
|
*/
|
|
436
451
|
verifyWithEcdsaP256Pem(pem) {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
return this;
|
|
440
|
-
}
|
|
441
|
-
catch (error) {
|
|
442
|
-
if (error instanceof Error) {
|
|
443
|
-
throw new Claim169Error(error.message);
|
|
444
|
-
}
|
|
445
|
-
throw new Claim169Error(String(error));
|
|
446
|
-
}
|
|
452
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEcdsaP256Pem(pem));
|
|
453
|
+
return this;
|
|
447
454
|
}
|
|
448
455
|
/**
|
|
449
456
|
* Allow decoding without signature verification.
|
|
@@ -462,16 +469,8 @@ export class Decoder {
|
|
|
462
469
|
* @throws {Claim169Error} If the key is invalid
|
|
463
470
|
*/
|
|
464
471
|
decryptWithAes256(key) {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
return this;
|
|
468
|
-
}
|
|
469
|
-
catch (error) {
|
|
470
|
-
if (error instanceof Error) {
|
|
471
|
-
throw new Claim169Error(error.message);
|
|
472
|
-
}
|
|
473
|
-
throw new Claim169Error(String(error));
|
|
474
|
-
}
|
|
472
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.decryptWithAes256(key));
|
|
473
|
+
return this;
|
|
475
474
|
}
|
|
476
475
|
/**
|
|
477
476
|
* Decrypt with AES-128-GCM.
|
|
@@ -480,16 +479,8 @@ export class Decoder {
|
|
|
480
479
|
* @throws {Claim169Error} If the key is invalid
|
|
481
480
|
*/
|
|
482
481
|
decryptWithAes128(key) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
return this;
|
|
486
|
-
}
|
|
487
|
-
catch (error) {
|
|
488
|
-
if (error instanceof Error) {
|
|
489
|
-
throw new Claim169Error(error.message);
|
|
490
|
-
}
|
|
491
|
-
throw new Claim169Error(String(error));
|
|
492
|
-
}
|
|
482
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.decryptWithAes128(key));
|
|
483
|
+
return this;
|
|
493
484
|
}
|
|
494
485
|
/**
|
|
495
486
|
* Skip biometric data during decoding.
|
|
@@ -501,7 +492,7 @@ export class Decoder {
|
|
|
501
492
|
return this;
|
|
502
493
|
}
|
|
503
494
|
/**
|
|
504
|
-
*
|
|
495
|
+
* Re-enable timestamp validation (enabled by default).
|
|
505
496
|
* When enabled, expired or not-yet-valid credentials will throw an error.
|
|
506
497
|
* Implemented in the host (JavaScript) to avoid WASM runtime time limitations.
|
|
507
498
|
* @returns The decoder instance for chaining
|
|
@@ -557,16 +548,8 @@ export class Decoder {
|
|
|
557
548
|
* ```
|
|
558
549
|
*/
|
|
559
550
|
verifyWith(verifier) {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
return this;
|
|
563
|
-
}
|
|
564
|
-
catch (error) {
|
|
565
|
-
if (error instanceof Error) {
|
|
566
|
-
throw new Claim169Error(error.message);
|
|
567
|
-
}
|
|
568
|
-
throw new Claim169Error(String(error));
|
|
569
|
-
}
|
|
551
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWith(verifier));
|
|
552
|
+
return this;
|
|
570
553
|
}
|
|
571
554
|
/**
|
|
572
555
|
* Decrypt with a custom decryptor callback.
|
|
@@ -586,16 +569,8 @@ export class Decoder {
|
|
|
586
569
|
* ```
|
|
587
570
|
*/
|
|
588
571
|
decryptWith(decryptor) {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
return this;
|
|
592
|
-
}
|
|
593
|
-
catch (error) {
|
|
594
|
-
if (error instanceof Error) {
|
|
595
|
-
throw new Claim169Error(error.message);
|
|
596
|
-
}
|
|
597
|
-
throw new Claim169Error(String(error));
|
|
598
|
-
}
|
|
572
|
+
this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.decryptWith(decryptor));
|
|
573
|
+
return this;
|
|
599
574
|
}
|
|
600
575
|
/**
|
|
601
576
|
* Decode the QR code with the configured options.
|
|
@@ -605,7 +580,7 @@ export class Decoder {
|
|
|
605
580
|
* @throws {Claim169Error} If decoding fails or no verification method specified
|
|
606
581
|
*/
|
|
607
582
|
decode() {
|
|
608
|
-
|
|
583
|
+
return wrapWasmCall(() => {
|
|
609
584
|
const result = this.wasmDecoder.decode();
|
|
610
585
|
const transformed = transformResult(result);
|
|
611
586
|
// Validate date format (YYYY-MM-DD)
|
|
@@ -614,13 +589,7 @@ export class Decoder {
|
|
|
614
589
|
validateTimestampsHost(transformed.cwtMeta, this.clockSkewToleranceSeconds);
|
|
615
590
|
}
|
|
616
591
|
return transformed;
|
|
617
|
-
}
|
|
618
|
-
catch (error) {
|
|
619
|
-
if (error instanceof Error) {
|
|
620
|
-
throw new Claim169Error(error.message);
|
|
621
|
-
}
|
|
622
|
-
throw new Claim169Error(String(error));
|
|
623
|
-
}
|
|
592
|
+
});
|
|
624
593
|
}
|
|
625
594
|
}
|
|
626
595
|
/**
|
|
@@ -695,15 +664,7 @@ export class Encoder {
|
|
|
695
664
|
* @param cwtMeta - CWT metadata including issuer, expiration, etc.
|
|
696
665
|
*/
|
|
697
666
|
constructor(claim169, cwtMeta) {
|
|
698
|
-
|
|
699
|
-
this.wasmEncoder = new wasm.WasmEncoder(claim169, cwtMeta);
|
|
700
|
-
}
|
|
701
|
-
catch (error) {
|
|
702
|
-
if (error instanceof Error) {
|
|
703
|
-
throw new Claim169Error(error.message);
|
|
704
|
-
}
|
|
705
|
-
throw new Claim169Error(String(error));
|
|
706
|
-
}
|
|
667
|
+
this.wasmEncoder = wrapWasmCall(() => new wasm.WasmEncoder(claim169, cwtMeta));
|
|
707
668
|
}
|
|
708
669
|
/**
|
|
709
670
|
* Sign with Ed25519 private key.
|
|
@@ -711,16 +672,8 @@ export class Encoder {
|
|
|
711
672
|
* @returns The encoder instance for chaining
|
|
712
673
|
*/
|
|
713
674
|
signWithEd25519(privateKey) {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
return this;
|
|
717
|
-
}
|
|
718
|
-
catch (error) {
|
|
719
|
-
if (error instanceof Error) {
|
|
720
|
-
throw new Claim169Error(error.message);
|
|
721
|
-
}
|
|
722
|
-
throw new Claim169Error(String(error));
|
|
723
|
-
}
|
|
675
|
+
this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.signWithEd25519(privateKey));
|
|
676
|
+
return this;
|
|
724
677
|
}
|
|
725
678
|
/**
|
|
726
679
|
* Sign with ECDSA P-256 private key.
|
|
@@ -728,16 +681,8 @@ export class Encoder {
|
|
|
728
681
|
* @returns The encoder instance for chaining
|
|
729
682
|
*/
|
|
730
683
|
signWithEcdsaP256(privateKey) {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
return this;
|
|
734
|
-
}
|
|
735
|
-
catch (error) {
|
|
736
|
-
if (error instanceof Error) {
|
|
737
|
-
throw new Claim169Error(error.message);
|
|
738
|
-
}
|
|
739
|
-
throw new Claim169Error(String(error));
|
|
740
|
-
}
|
|
684
|
+
this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.signWithEcdsaP256(privateKey));
|
|
685
|
+
return this;
|
|
741
686
|
}
|
|
742
687
|
/**
|
|
743
688
|
* Encrypt with AES-256-GCM.
|
|
@@ -745,16 +690,8 @@ export class Encoder {
|
|
|
745
690
|
* @returns The encoder instance for chaining
|
|
746
691
|
*/
|
|
747
692
|
encryptWithAes256(key) {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
return this;
|
|
751
|
-
}
|
|
752
|
-
catch (error) {
|
|
753
|
-
if (error instanceof Error) {
|
|
754
|
-
throw new Claim169Error(error.message);
|
|
755
|
-
}
|
|
756
|
-
throw new Claim169Error(String(error));
|
|
757
|
-
}
|
|
693
|
+
this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.encryptWithAes256(key));
|
|
694
|
+
return this;
|
|
758
695
|
}
|
|
759
696
|
/**
|
|
760
697
|
* Encrypt with AES-128-GCM.
|
|
@@ -762,16 +699,8 @@ export class Encoder {
|
|
|
762
699
|
* @returns The encoder instance for chaining
|
|
763
700
|
*/
|
|
764
701
|
encryptWithAes128(key) {
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
return this;
|
|
768
|
-
}
|
|
769
|
-
catch (error) {
|
|
770
|
-
if (error instanceof Error) {
|
|
771
|
-
throw new Claim169Error(error.message);
|
|
772
|
-
}
|
|
773
|
-
throw new Claim169Error(String(error));
|
|
774
|
-
}
|
|
702
|
+
this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.encryptWithAes128(key));
|
|
703
|
+
return this;
|
|
775
704
|
}
|
|
776
705
|
/**
|
|
777
706
|
* Allow encoding without a signature.
|
|
@@ -809,19 +738,11 @@ export class Encoder {
|
|
|
809
738
|
* ```
|
|
810
739
|
*/
|
|
811
740
|
signWith(signer, algorithm, keyId) {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
return this;
|
|
818
|
-
}
|
|
819
|
-
catch (error) {
|
|
820
|
-
if (error instanceof Error) {
|
|
821
|
-
throw new Claim169Error(error.message);
|
|
822
|
-
}
|
|
823
|
-
throw new Claim169Error(String(error));
|
|
824
|
-
}
|
|
741
|
+
// Wrap the callback so callers can optionally provide a keyId even if the
|
|
742
|
+
// underlying WASM bindings don't expose key-id configuration yet.
|
|
743
|
+
const signerWithKeyId = (alg, wasmKeyId, data) => signer(alg, keyId ?? wasmKeyId, data);
|
|
744
|
+
this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.signWith(signerWithKeyId, algorithm));
|
|
745
|
+
return this;
|
|
825
746
|
}
|
|
826
747
|
/**
|
|
827
748
|
* Encrypt with a custom encryptor callback.
|
|
@@ -842,32 +763,33 @@ export class Encoder {
|
|
|
842
763
|
* ```
|
|
843
764
|
*/
|
|
844
765
|
encryptWith(encryptor, algorithm) {
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
766
|
+
this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.encryptWith(encryptor, algorithm));
|
|
767
|
+
return this;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Set compression mode for encoding.
|
|
771
|
+
* @param mode - Compression mode: "zlib", "none", "adaptive", "brotli:N" (0-11), or "adaptive-brotli:N"
|
|
772
|
+
* @returns The encoder instance for chaining
|
|
773
|
+
* @throws {Claim169Error} If the mode is invalid or unsupported by the WASM build
|
|
774
|
+
*/
|
|
775
|
+
compression(mode) {
|
|
776
|
+
this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.compression(mode));
|
|
777
|
+
return this;
|
|
855
778
|
}
|
|
856
779
|
/**
|
|
857
|
-
* Encode the credential to a
|
|
858
|
-
* @returns
|
|
780
|
+
* Encode the credential to a QR-ready result object.
|
|
781
|
+
* @returns Encode result with QR data, compression info, and warnings
|
|
859
782
|
* @throws {Claim169Error} If encoding fails
|
|
860
783
|
*/
|
|
861
784
|
encode() {
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
}
|
|
785
|
+
return wrapWasmCall(() => {
|
|
786
|
+
const raw = this.wasmEncoder.encode();
|
|
787
|
+
return {
|
|
788
|
+
qrData: raw.qrData,
|
|
789
|
+
compressionUsed: raw.compressionUsed,
|
|
790
|
+
warnings: raw.warnings ?? [],
|
|
791
|
+
};
|
|
792
|
+
});
|
|
871
793
|
}
|
|
872
794
|
}
|
|
873
795
|
/**
|
|
@@ -877,4 +799,54 @@ export class Encoder {
|
|
|
877
799
|
export function generateNonce() {
|
|
878
800
|
return new Uint8Array(wasm.generateNonce());
|
|
879
801
|
}
|
|
802
|
+
/**
|
|
803
|
+
* Transform raw WASM inspect result to typed InspectResult.
|
|
804
|
+
*/
|
|
805
|
+
function transformInspectResult(raw) {
|
|
806
|
+
if (typeof raw !== "object" || raw === null) {
|
|
807
|
+
throw new Claim169Error("Malformed WASM output: expected object");
|
|
808
|
+
}
|
|
809
|
+
const result = raw;
|
|
810
|
+
if (typeof result.coseType !== "string") {
|
|
811
|
+
throw new Claim169Error("Malformed WASM output: missing coseType");
|
|
812
|
+
}
|
|
813
|
+
return {
|
|
814
|
+
issuer: result.issuer,
|
|
815
|
+
subject: result.subject,
|
|
816
|
+
keyId: safeUint8Array(result.keyId),
|
|
817
|
+
algorithm: result.algorithm,
|
|
818
|
+
x509Headers: transformX509Headers(result.x509Headers),
|
|
819
|
+
expiresAt: result.expiresAt,
|
|
820
|
+
coseType: result.coseType,
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Inspect credential metadata without full decoding or verification.
|
|
825
|
+
*
|
|
826
|
+
* Extracts metadata (issuer, key ID, algorithm, expiration) from a QR code
|
|
827
|
+
* without verifying the signature. Useful for multi-issuer key lookup.
|
|
828
|
+
*
|
|
829
|
+
* For encrypted credentials (COSE_Encrypt0), only COSE-level headers are
|
|
830
|
+
* available; CWT-level fields (issuer, subject, expiresAt) will be `undefined`.
|
|
831
|
+
*
|
|
832
|
+
* @param qrText - The Base45-encoded QR code content
|
|
833
|
+
* @returns Metadata extracted from the credential
|
|
834
|
+
* @throws {Claim169Error} On parse errors
|
|
835
|
+
*
|
|
836
|
+
* @example
|
|
837
|
+
* ```typescript
|
|
838
|
+
* import { inspect } from 'claim169';
|
|
839
|
+
*
|
|
840
|
+
* const meta = inspect(qrText);
|
|
841
|
+
* console.log(meta.issuer); // "https://issuer.example.com"
|
|
842
|
+
* console.log(meta.algorithm); // "EdDSA"
|
|
843
|
+
* console.log(meta.coseType); // "Sign1"
|
|
844
|
+
* ```
|
|
845
|
+
*/
|
|
846
|
+
export function inspect(qrText) {
|
|
847
|
+
return wrapWasmCall(() => {
|
|
848
|
+
const raw = wasm.inspect(qrText);
|
|
849
|
+
return transformInspectResult(raw);
|
|
850
|
+
});
|
|
851
|
+
}
|
|
880
852
|
//# sourceMappingURL=index.js.map
|