claim169 0.1.0-alpha
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 +392 -0
- package/dist/index.d.ts +319 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +582 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +476 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +29 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
- package/wasm/README.md +264 -0
- package/wasm/claim169_wasm.d.ts +99 -0
- package/wasm/claim169_wasm.js +9 -0
- package/wasm/claim169_wasm_bg.js +822 -0
- package/wasm/claim169_wasm_bg.wasm +0 -0
- package/wasm/claim169_wasm_bg.wasm.d.ts +36 -0
- package/wasm/package.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# claim169
|
|
2
|
+
|
|
3
|
+
> **Alpha Software**: This library is under active development. APIs may change without notice. Not recommended for production use without thorough testing.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/claim169)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
A TypeScript/JavaScript library for decoding MOSIP Claim 169 QR codes. Built on Rust/WebAssembly for performance and security.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install claim169
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Overview
|
|
17
|
+
|
|
18
|
+
MOSIP Claim 169 defines a standard for encoding identity data in QR codes using:
|
|
19
|
+
- CBOR encoding with numeric keys for compactness
|
|
20
|
+
- CWT (CBOR Web Token) for standard claims
|
|
21
|
+
- COSE_Sign1 for digital signatures
|
|
22
|
+
- COSE_Encrypt0 for optional encryption
|
|
23
|
+
- zlib compression + Base45 encoding for QR-friendly output
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Builder Pattern (Recommended)
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { Decoder } from 'claim169';
|
|
31
|
+
|
|
32
|
+
// Decode with Ed25519 signature verification (recommended)
|
|
33
|
+
const publicKey = new Uint8Array(32); // Your 32-byte public key
|
|
34
|
+
const result = new Decoder(qrText)
|
|
35
|
+
.verifyWithEd25519(publicKey)
|
|
36
|
+
.decode();
|
|
37
|
+
|
|
38
|
+
console.log(`ID: ${result.claim169.id}`);
|
|
39
|
+
console.log(`Name: ${result.claim169.fullName}`);
|
|
40
|
+
console.log(`Issuer: ${result.cwtMeta.issuer}`);
|
|
41
|
+
console.log(`Verified: ${result.verificationStatus}`); // "verified"
|
|
42
|
+
|
|
43
|
+
// Decode without verification (testing only)
|
|
44
|
+
const result = new Decoder(qrText)
|
|
45
|
+
.allowUnverified()
|
|
46
|
+
.decode();
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### `decode()` Convenience Function
|
|
50
|
+
|
|
51
|
+
> **Security note**: `decode()` requires a verification key unless you explicitly set `allowUnverified: true` (testing only). Use the `Decoder` builder API in production.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { decode, type DecodeOptions } from 'claim169';
|
|
55
|
+
|
|
56
|
+
// Simple decode (testing only)
|
|
57
|
+
const result = decode(qrText, { allowUnverified: true });
|
|
58
|
+
|
|
59
|
+
// With options
|
|
60
|
+
const options: DecodeOptions = {
|
|
61
|
+
maxDecompressedBytes: 32768, // 32KB limit
|
|
62
|
+
skipBiometrics: true, // Skip biometric parsing
|
|
63
|
+
validateTimestamps: false, // Disabled by default in WASM
|
|
64
|
+
allowUnverified: true, // Explicit opt-out (testing only)
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const result = decode(qrText, options);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Decoder Class
|
|
71
|
+
|
|
72
|
+
The `Decoder` class provides a fluent builder API:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { Decoder } from 'claim169';
|
|
76
|
+
|
|
77
|
+
// Decode with Ed25519 verification
|
|
78
|
+
const result = new Decoder(qrText)
|
|
79
|
+
.verifyWithEd25519(publicKey)
|
|
80
|
+
.decode();
|
|
81
|
+
|
|
82
|
+
// Decode with ECDSA P-256 verification
|
|
83
|
+
const result = new Decoder(qrText)
|
|
84
|
+
.verifyWithEcdsaP256(publicKey) // 33 or 65 bytes SEC1 encoded
|
|
85
|
+
.decode();
|
|
86
|
+
|
|
87
|
+
// Decrypt then verify (for encrypted credentials)
|
|
88
|
+
const result = new Decoder(qrText)
|
|
89
|
+
.decryptWithAes256(aesKey)
|
|
90
|
+
.verifyWithEd25519(publicKey)
|
|
91
|
+
.decode();
|
|
92
|
+
|
|
93
|
+
// With additional options
|
|
94
|
+
const result = new Decoder(qrText)
|
|
95
|
+
.verifyWithEd25519(publicKey)
|
|
96
|
+
.skipBiometrics() // Skip biometric data
|
|
97
|
+
.withTimestampValidation() // Enable timestamp validation
|
|
98
|
+
.clockSkewTolerance(60) // 60 seconds tolerance
|
|
99
|
+
.maxDecompressedBytes(32768) // 32KB max size
|
|
100
|
+
.decode();
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Decoder Methods
|
|
104
|
+
|
|
105
|
+
| Method | Description |
|
|
106
|
+
|--------|-------------|
|
|
107
|
+
| `verifyWithEd25519(publicKey)` | Verify with Ed25519 (32 bytes) |
|
|
108
|
+
| `verifyWithEcdsaP256(publicKey)` | Verify with ECDSA P-256 (33 or 65 bytes) |
|
|
109
|
+
| `decryptWithAes256(key)` | Decrypt with AES-256-GCM (32 bytes) |
|
|
110
|
+
| `decryptWithAes128(key)` | Decrypt with AES-128-GCM (16 bytes) |
|
|
111
|
+
| `allowUnverified()` | Skip verification (testing only) |
|
|
112
|
+
| `skipBiometrics()` | Skip biometric data parsing |
|
|
113
|
+
| `withTimestampValidation()` | Enable exp/nbf validation |
|
|
114
|
+
| `clockSkewTolerance(seconds)` | Set clock skew tolerance |
|
|
115
|
+
| `maxDecompressedBytes(bytes)` | Set max decompressed size |
|
|
116
|
+
| `decode()` | Execute the decode operation |
|
|
117
|
+
|
|
118
|
+
## Encoding
|
|
119
|
+
|
|
120
|
+
The `Encoder` class creates MOSIP Claim 169 QR code data from identity information.
|
|
121
|
+
In production, keys should be provisioned and managed externally (HSM/KMS or secure key management). The examples below assume you already have key material.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { Encoder, Decoder, Claim169Input, CwtMetaInput, generateNonce } from 'claim169';
|
|
125
|
+
|
|
126
|
+
// Create identity data
|
|
127
|
+
const claim169: Claim169Input = {
|
|
128
|
+
id: "123456789",
|
|
129
|
+
fullName: "John Doe",
|
|
130
|
+
dateOfBirth: "1990-01-15",
|
|
131
|
+
gender: 1, // Male
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Create CWT metadata
|
|
135
|
+
const cwtMeta: CwtMetaInput = {
|
|
136
|
+
issuer: "https://issuer.example.com",
|
|
137
|
+
expiresAt: 1800000000,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Encode with Ed25519 signature
|
|
141
|
+
const privateKey = new Uint8Array(32); // Your 32-byte private key
|
|
142
|
+
const qrData = new Encoder(claim169, cwtMeta)
|
|
143
|
+
.signWithEd25519(privateKey)
|
|
144
|
+
.encode();
|
|
145
|
+
|
|
146
|
+
// Encode with signature and AES-256 encryption
|
|
147
|
+
const aesKey = new Uint8Array(32); // Your 32-byte AES key
|
|
148
|
+
const qrData = new Encoder(claim169, cwtMeta)
|
|
149
|
+
.signWithEd25519(privateKey)
|
|
150
|
+
.encryptWithAes256(aesKey)
|
|
151
|
+
.encode();
|
|
152
|
+
|
|
153
|
+
// Unsigned (testing only)
|
|
154
|
+
const qrData = new Encoder(claim169, cwtMeta)
|
|
155
|
+
.allowUnsigned()
|
|
156
|
+
.encode();
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Encoder Methods
|
|
160
|
+
|
|
161
|
+
| Method | Description |
|
|
162
|
+
|--------|-------------|
|
|
163
|
+
| `signWithEd25519(privateKey)` | Sign with Ed25519 |
|
|
164
|
+
| `signWithEcdsaP256(privateKey)` | Sign with ECDSA P-256 |
|
|
165
|
+
| `encryptWithAes256(key)` | Encrypt with AES-256-GCM |
|
|
166
|
+
| `encryptWithAes128(key)` | Encrypt with AES-128-GCM |
|
|
167
|
+
| `allowUnsigned()` | Allow unsigned (testing only) |
|
|
168
|
+
| `skipBiometrics()` | Skip biometric fields |
|
|
169
|
+
| `encode()` | Produce the QR string |
|
|
170
|
+
|
|
171
|
+
### generateNonce()
|
|
172
|
+
|
|
173
|
+
Generate a cryptographically secure random nonce for encryption:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { generateNonce } from 'claim169';
|
|
177
|
+
|
|
178
|
+
const nonce = generateNonce(); // Returns 12-byte Uint8Array
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Data Model
|
|
182
|
+
|
|
183
|
+
### DecodeResult
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
interface DecodeResult {
|
|
187
|
+
claim169: Claim169; // Identity data
|
|
188
|
+
cwtMeta: CwtMeta; // Token metadata
|
|
189
|
+
verificationStatus: VerificationStatus; // "verified" | "skipped" | "failed"
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Claim169
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
interface Claim169 {
|
|
197
|
+
// Demographics
|
|
198
|
+
id?: string; // Unique identifier
|
|
199
|
+
fullName?: string; // Full name
|
|
200
|
+
firstName?: string; // First name
|
|
201
|
+
middleName?: string; // Middle name
|
|
202
|
+
lastName?: string; // Last name
|
|
203
|
+
dateOfBirth?: string; // ISO 8601 format
|
|
204
|
+
gender?: number; // 1=Male, 2=Female, 3=Other
|
|
205
|
+
address?: string; // Address
|
|
206
|
+
email?: string; // Email address
|
|
207
|
+
phone?: string; // Phone number
|
|
208
|
+
nationality?: string; // Nationality code
|
|
209
|
+
maritalStatus?: number; // Marital status code
|
|
210
|
+
guardian?: string; // Guardian name
|
|
211
|
+
|
|
212
|
+
// Additional fields
|
|
213
|
+
version?: string; // Claim version
|
|
214
|
+
language?: string; // Primary language code
|
|
215
|
+
secondaryFullName?: string; // Secondary full name
|
|
216
|
+
secondaryLanguage?: string; // Secondary language code
|
|
217
|
+
locationCode?: string; // Location code
|
|
218
|
+
legalStatus?: string; // Legal status
|
|
219
|
+
countryOfIssuance?: string; // Country of issuance
|
|
220
|
+
|
|
221
|
+
// Photo
|
|
222
|
+
photo?: Uint8Array; // Photo data
|
|
223
|
+
photoFormat?: number; // Photo format code
|
|
224
|
+
|
|
225
|
+
// Biometrics (when present)
|
|
226
|
+
face?: Biometric[]; // Face biometrics
|
|
227
|
+
rightThumb?: Biometric[]; // Right thumb fingerprint
|
|
228
|
+
// ... (all finger/iris/palm biometrics)
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### CwtMeta
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
interface CwtMeta {
|
|
236
|
+
issuer?: string; // Token issuer
|
|
237
|
+
subject?: string; // Token subject
|
|
238
|
+
expiresAt?: number; // Expiration timestamp (Unix seconds)
|
|
239
|
+
notBefore?: number; // Not-before timestamp
|
|
240
|
+
issuedAt?: number; // Issued-at timestamp
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Biometric
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
interface Biometric {
|
|
248
|
+
data: Uint8Array; // Raw biometric data
|
|
249
|
+
format: number; // Biometric format code
|
|
250
|
+
subFormat?: number; // Sub-format code
|
|
251
|
+
issuer?: string; // Issuer identifier
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Error Handling
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { decode, Claim169Error } from 'claim169';
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
const result = decode(qrText, { allowUnverified: true });
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (error instanceof Claim169Error) {
|
|
264
|
+
// Handle decode error
|
|
265
|
+
console.error("Decode failed:", error.message);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Error messages indicate the specific failure:
|
|
271
|
+
- `Base45Decode`: Invalid Base45 encoding
|
|
272
|
+
- `Decompress`: zlib decompression failed
|
|
273
|
+
- `CoseParse`: Invalid COSE structure
|
|
274
|
+
- `CwtParse`: Invalid CWT structure
|
|
275
|
+
- `Claim169NotFound`: Missing claim 169
|
|
276
|
+
- `SignatureError`: Signature verification failed
|
|
277
|
+
- `DecryptionError`: Decryption failed
|
|
278
|
+
|
|
279
|
+
## Notes
|
|
280
|
+
|
|
281
|
+
### Timestamp Validation
|
|
282
|
+
|
|
283
|
+
Timestamp validation is disabled by default because WebAssembly does not have reliable access to system time. Enable it explicitly if your environment provides accurate time:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
const result = new Decoder(qrText)
|
|
287
|
+
.verifyWithEd25519(publicKey)
|
|
288
|
+
.withTimestampValidation()
|
|
289
|
+
.clockSkewTolerance(60) // Allow 60 seconds clock drift
|
|
290
|
+
.decode();
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Secure by Default
|
|
294
|
+
|
|
295
|
+
The decoder requires explicit verification configuration. You must call one of:
|
|
296
|
+
- `verifyWithEd25519(publicKey)` - Verify with Ed25519
|
|
297
|
+
- `verifyWithEcdsaP256(publicKey)` - Verify with ECDSA P-256
|
|
298
|
+
- `allowUnverified()` - Explicitly skip verification (testing only)
|
|
299
|
+
|
|
300
|
+
This prevents accidentally processing unverified credentials.
|
|
301
|
+
|
|
302
|
+
## Browser Usage
|
|
303
|
+
|
|
304
|
+
```html
|
|
305
|
+
<script type="module">
|
|
306
|
+
import { Decoder } from './node_modules/claim169/dist/index.js';
|
|
307
|
+
|
|
308
|
+
// Your issuer's public key (32 bytes for Ed25519)
|
|
309
|
+
const publicKey = new Uint8Array([/* ... */]);
|
|
310
|
+
|
|
311
|
+
const qrText = "6BF5YZB2...";
|
|
312
|
+
const result = new Decoder(qrText)
|
|
313
|
+
.verifyWithEd25519(publicKey)
|
|
314
|
+
.decode();
|
|
315
|
+
|
|
316
|
+
if (result.verificationStatus === "verified") {
|
|
317
|
+
console.log("Verified:", result.claim169.fullName);
|
|
318
|
+
}
|
|
319
|
+
</script>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Bundler Configuration
|
|
323
|
+
|
|
324
|
+
### Vite
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// vite.config.ts
|
|
328
|
+
import { defineConfig } from 'vite';
|
|
329
|
+
import wasm from 'vite-plugin-wasm';
|
|
330
|
+
import topLevelAwait from 'vite-plugin-top-level-await';
|
|
331
|
+
|
|
332
|
+
export default defineConfig({
|
|
333
|
+
plugins: [wasm(), topLevelAwait()],
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Webpack
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
// webpack.config.js
|
|
341
|
+
module.exports = {
|
|
342
|
+
experiments: {
|
|
343
|
+
asyncWebAssembly: true,
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Utility Functions
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import { version, isLoaded } from 'claim169';
|
|
352
|
+
|
|
353
|
+
// Get library version
|
|
354
|
+
console.log(version()); // "0.1.0"
|
|
355
|
+
|
|
356
|
+
// Check if WASM module is loaded
|
|
357
|
+
console.log(isLoaded()); // true
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Development
|
|
361
|
+
|
|
362
|
+
### Building from Source
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
# Install dependencies
|
|
366
|
+
npm install
|
|
367
|
+
|
|
368
|
+
# Build WASM (requires Rust and wasm-pack)
|
|
369
|
+
npm run build:wasm
|
|
370
|
+
|
|
371
|
+
# Build TypeScript
|
|
372
|
+
npm run build:ts
|
|
373
|
+
|
|
374
|
+
# Or build everything
|
|
375
|
+
npm run build
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Running Tests
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
npm test
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Prerequisites
|
|
385
|
+
|
|
386
|
+
- Node.js 18+
|
|
387
|
+
- Rust toolchain (for building WASM)
|
|
388
|
+
- wasm-pack (`cargo install wasm-pack`)
|
|
389
|
+
|
|
390
|
+
## License
|
|
391
|
+
|
|
392
|
+
MIT License - See LICENSE file for details.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MOSIP Claim 169 QR Code library for TypeScript/JavaScript.
|
|
3
|
+
*
|
|
4
|
+
* This library provides classes to encode and decode MOSIP Claim 169 identity
|
|
5
|
+
* credentials from QR codes. It uses WebAssembly for high-performance binary
|
|
6
|
+
* parsing and cryptographic operations.
|
|
7
|
+
*
|
|
8
|
+
* ## Installation
|
|
9
|
+
*
|
|
10
|
+
* ```bash
|
|
11
|
+
* npm install claim169
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* ## Decoding with Verification (Recommended)
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { Decoder } from 'claim169';
|
|
18
|
+
*
|
|
19
|
+
* // Decode with Ed25519 signature verification
|
|
20
|
+
* const result = new Decoder(qrText)
|
|
21
|
+
* .verifyWithEd25519(publicKey)
|
|
22
|
+
* .decode();
|
|
23
|
+
*
|
|
24
|
+
* // Access identity data
|
|
25
|
+
* console.log(result.claim169.fullName);
|
|
26
|
+
* console.log(result.claim169.dateOfBirth);
|
|
27
|
+
*
|
|
28
|
+
* // Access metadata
|
|
29
|
+
* console.log(result.cwtMeta.issuer);
|
|
30
|
+
* console.log(result.cwtMeta.expiresAt);
|
|
31
|
+
*
|
|
32
|
+
* // Check verification status
|
|
33
|
+
* console.log(result.verificationStatus); // "verified"
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ## Decoding without Verification (Testing Only)
|
|
37
|
+
*
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const result = new Decoder(qrText)
|
|
40
|
+
* .allowUnverified() // Explicit opt-out required
|
|
41
|
+
* .decode();
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* ## Decoding Encrypted Credentials
|
|
45
|
+
*
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const result = new Decoder(qrText)
|
|
48
|
+
* .decryptWithAes256(aesKey)
|
|
49
|
+
* .verifyWithEd25519(publicKey)
|
|
50
|
+
* .decode();
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* ## Encoding Credentials
|
|
54
|
+
*
|
|
55
|
+
* ```typescript
|
|
56
|
+
* import { Encoder } from 'claim169';
|
|
57
|
+
*
|
|
58
|
+
* const qrData = new Encoder(claim169, cwtMeta)
|
|
59
|
+
* .signWithEd25519(privateKey)
|
|
60
|
+
* .encode();
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* ## Error Handling
|
|
64
|
+
*
|
|
65
|
+
* ```typescript
|
|
66
|
+
* import { Decoder, Claim169Error } from 'claim169';
|
|
67
|
+
*
|
|
68
|
+
* try {
|
|
69
|
+
* const result = new Decoder(qrText)
|
|
70
|
+
* .verifyWithEd25519(publicKey)
|
|
71
|
+
* .decode();
|
|
72
|
+
* } catch (error) {
|
|
73
|
+
* if (error instanceof Claim169Error) {
|
|
74
|
+
* console.error('Decoding failed:', error.message);
|
|
75
|
+
* }
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* ## Notes
|
|
80
|
+
*
|
|
81
|
+
* - **Timestamp validation**: Disabled by default because WASM doesn't have
|
|
82
|
+
* reliable access to system time. Enable with `.withTimestampValidation()`.
|
|
83
|
+
*
|
|
84
|
+
* @module claim169
|
|
85
|
+
*/
|
|
86
|
+
export type { Biometric, Claim169, Claim169Input, CwtMeta, CwtMetaInput, DecodeResult, IDecoder, IEncoder, VerificationStatus, } from "./types.js";
|
|
87
|
+
export { Claim169Error } from "./types.js";
|
|
88
|
+
import type { Claim169Input, CwtMetaInput, DecodeResult, IDecoder, IEncoder } from "./types.js";
|
|
89
|
+
/**
|
|
90
|
+
* Get the library version
|
|
91
|
+
*/
|
|
92
|
+
export declare function version(): string;
|
|
93
|
+
/**
|
|
94
|
+
* Check if the WASM module is loaded correctly
|
|
95
|
+
*/
|
|
96
|
+
export declare function isLoaded(): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Convert a hex string to bytes.
|
|
99
|
+
*
|
|
100
|
+
* Accepts optional `0x` prefix and ignores whitespace.
|
|
101
|
+
*
|
|
102
|
+
* @throws {Claim169Error} If the input is not valid hex
|
|
103
|
+
*/
|
|
104
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
105
|
+
/**
|
|
106
|
+
* Convert bytes to a lowercase hex string.
|
|
107
|
+
*/
|
|
108
|
+
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
109
|
+
/**
|
|
110
|
+
* Builder-pattern decoder for Claim 169 QR codes.
|
|
111
|
+
*
|
|
112
|
+
* Provides a fluent API for configuring decoding options and executing the decode.
|
|
113
|
+
* Supports signature verification with Ed25519 and ECDSA P-256, as well as
|
|
114
|
+
* AES-GCM decryption for encrypted credentials.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* // With verification (recommended for production)
|
|
119
|
+
* const result = new Decoder(qrText)
|
|
120
|
+
* .verifyWithEd25519(publicKey)
|
|
121
|
+
* .decode();
|
|
122
|
+
*
|
|
123
|
+
* // Without verification (testing only)
|
|
124
|
+
* const result = new Decoder(qrText)
|
|
125
|
+
* .allowUnverified()
|
|
126
|
+
* .skipBiometrics()
|
|
127
|
+
* .decode();
|
|
128
|
+
*
|
|
129
|
+
* // With decryption and verification
|
|
130
|
+
* const result = new Decoder(qrText)
|
|
131
|
+
* .decryptWithAes256(aesKey)
|
|
132
|
+
* .verifyWithEd25519(publicKey)
|
|
133
|
+
* .decode();
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export declare class Decoder implements IDecoder {
|
|
137
|
+
private wasmDecoder;
|
|
138
|
+
/**
|
|
139
|
+
* Create a new Decoder instance.
|
|
140
|
+
* @param qrText - The QR code text content (Base45 encoded)
|
|
141
|
+
*/
|
|
142
|
+
constructor(qrText: string);
|
|
143
|
+
/**
|
|
144
|
+
* Verify signature with Ed25519 public key.
|
|
145
|
+
* @param publicKey - 32-byte Ed25519 public key
|
|
146
|
+
* @returns The decoder instance for chaining
|
|
147
|
+
* @throws {Claim169Error} If the public key is invalid
|
|
148
|
+
*/
|
|
149
|
+
verifyWithEd25519(publicKey: Uint8Array): Decoder;
|
|
150
|
+
/**
|
|
151
|
+
* Verify signature with ECDSA P-256 public key.
|
|
152
|
+
* @param publicKey - SEC1-encoded P-256 public key (33 or 65 bytes)
|
|
153
|
+
* @returns The decoder instance for chaining
|
|
154
|
+
* @throws {Claim169Error} If the public key is invalid
|
|
155
|
+
*/
|
|
156
|
+
verifyWithEcdsaP256(publicKey: Uint8Array): Decoder;
|
|
157
|
+
/**
|
|
158
|
+
* Allow decoding without signature verification.
|
|
159
|
+
* WARNING: Unverified credentials cannot be trusted. Use for testing only.
|
|
160
|
+
* @returns The decoder instance for chaining
|
|
161
|
+
*/
|
|
162
|
+
allowUnverified(): Decoder;
|
|
163
|
+
/**
|
|
164
|
+
* Decrypt with AES-256-GCM.
|
|
165
|
+
* @param key - 32-byte AES-256 key
|
|
166
|
+
* @returns The decoder instance for chaining
|
|
167
|
+
* @throws {Claim169Error} If the key is invalid
|
|
168
|
+
*/
|
|
169
|
+
decryptWithAes256(key: Uint8Array): Decoder;
|
|
170
|
+
/**
|
|
171
|
+
* Decrypt with AES-128-GCM.
|
|
172
|
+
* @param key - 16-byte AES-128 key
|
|
173
|
+
* @returns The decoder instance for chaining
|
|
174
|
+
* @throws {Claim169Error} If the key is invalid
|
|
175
|
+
*/
|
|
176
|
+
decryptWithAes128(key: Uint8Array): Decoder;
|
|
177
|
+
/**
|
|
178
|
+
* Skip biometric data during decoding.
|
|
179
|
+
* Useful when only demographic data is needed for faster parsing.
|
|
180
|
+
* @returns The decoder instance for chaining
|
|
181
|
+
*/
|
|
182
|
+
skipBiometrics(): Decoder;
|
|
183
|
+
/**
|
|
184
|
+
* Enable timestamp validation.
|
|
185
|
+
* When enabled, expired or not-yet-valid credentials will throw an error.
|
|
186
|
+
* Disabled by default because WASM doesn't have reliable access to system time.
|
|
187
|
+
* @returns The decoder instance for chaining
|
|
188
|
+
*/
|
|
189
|
+
withTimestampValidation(): Decoder;
|
|
190
|
+
/**
|
|
191
|
+
* Set clock skew tolerance in seconds.
|
|
192
|
+
* Allows credentials to be accepted when clocks are slightly out of sync.
|
|
193
|
+
* Only applies when timestamp validation is enabled.
|
|
194
|
+
* @param seconds - The tolerance in seconds
|
|
195
|
+
* @returns The decoder instance for chaining
|
|
196
|
+
*/
|
|
197
|
+
clockSkewTolerance(seconds: number): Decoder;
|
|
198
|
+
/**
|
|
199
|
+
* Set maximum decompressed size in bytes.
|
|
200
|
+
* Protects against decompression bomb attacks.
|
|
201
|
+
* @param bytes - The maximum size in bytes (default: 65536)
|
|
202
|
+
* @returns The decoder instance for chaining
|
|
203
|
+
*/
|
|
204
|
+
maxDecompressedBytes(bytes: number): Decoder;
|
|
205
|
+
/**
|
|
206
|
+
* Decode the QR code with the configured options.
|
|
207
|
+
* Requires either a verifier (verifyWithEd25519/verifyWithEcdsaP256) or
|
|
208
|
+
* explicit allowUnverified() to be called first.
|
|
209
|
+
* @returns The decoded result
|
|
210
|
+
* @throws {Claim169Error} If decoding fails or no verification method specified
|
|
211
|
+
*/
|
|
212
|
+
decode(): DecodeResult;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Options for the `decode()` convenience function.
|
|
216
|
+
*
|
|
217
|
+
* Notes:
|
|
218
|
+
* - If you don't provide a verification key, you must explicitly set `allowUnverified: true` (testing only).
|
|
219
|
+
* - Timestamp validation is disabled by default in WASM; set `validateTimestamps: true` to enable it.
|
|
220
|
+
*/
|
|
221
|
+
export interface DecodeOptions {
|
|
222
|
+
verifyWithEd25519?: Uint8Array;
|
|
223
|
+
verifyWithEcdsaP256?: Uint8Array;
|
|
224
|
+
decryptWithAes256?: Uint8Array;
|
|
225
|
+
decryptWithAes128?: Uint8Array;
|
|
226
|
+
allowUnverified?: boolean;
|
|
227
|
+
skipBiometrics?: boolean;
|
|
228
|
+
validateTimestamps?: boolean;
|
|
229
|
+
clockSkewToleranceSeconds?: number;
|
|
230
|
+
maxDecompressedBytes?: number;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Decode a Claim 169 QR string.
|
|
234
|
+
*
|
|
235
|
+
* This is a convenience wrapper around the `Decoder` builder.
|
|
236
|
+
* Security:
|
|
237
|
+
* - If you do not pass a verification key, you must set `allowUnverified: true` (testing only).
|
|
238
|
+
*/
|
|
239
|
+
export declare function decode(qrText: string, options?: DecodeOptions): DecodeResult;
|
|
240
|
+
/**
|
|
241
|
+
* Builder-pattern encoder for Claim 169 QR codes.
|
|
242
|
+
*
|
|
243
|
+
* Provides a fluent API for configuring encoding options and generating QR data.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* // Signed credential (recommended)
|
|
248
|
+
* const qrData = new Encoder(claim169, cwtMeta)
|
|
249
|
+
* .signWithEd25519(privateKey)
|
|
250
|
+
* .encode();
|
|
251
|
+
*
|
|
252
|
+
* // Signed and encrypted
|
|
253
|
+
* const qrData = new Encoder(claim169, cwtMeta)
|
|
254
|
+
* .signWithEd25519(privateKey)
|
|
255
|
+
* .encryptWithAes256(aesKey)
|
|
256
|
+
* .encode();
|
|
257
|
+
*
|
|
258
|
+
* // Unsigned (testing only)
|
|
259
|
+
* const qrData = new Encoder(claim169, cwtMeta)
|
|
260
|
+
* .allowUnsigned()
|
|
261
|
+
* .encode();
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
export declare class Encoder implements IEncoder {
|
|
265
|
+
private wasmEncoder;
|
|
266
|
+
/**
|
|
267
|
+
* Create a new Encoder instance.
|
|
268
|
+
* @param claim169 - The identity claim data to encode
|
|
269
|
+
* @param cwtMeta - CWT metadata including issuer, expiration, etc.
|
|
270
|
+
*/
|
|
271
|
+
constructor(claim169: Claim169Input, cwtMeta: CwtMetaInput);
|
|
272
|
+
/**
|
|
273
|
+
* Sign with Ed25519 private key.
|
|
274
|
+
* @param privateKey - 32-byte Ed25519 private key
|
|
275
|
+
* @returns The encoder instance for chaining
|
|
276
|
+
*/
|
|
277
|
+
signWithEd25519(privateKey: Uint8Array): Encoder;
|
|
278
|
+
/**
|
|
279
|
+
* Sign with ECDSA P-256 private key.
|
|
280
|
+
* @param privateKey - 32-byte ECDSA P-256 private key (scalar)
|
|
281
|
+
* @returns The encoder instance for chaining
|
|
282
|
+
*/
|
|
283
|
+
signWithEcdsaP256(privateKey: Uint8Array): Encoder;
|
|
284
|
+
/**
|
|
285
|
+
* Encrypt with AES-256-GCM.
|
|
286
|
+
* @param key - 32-byte AES-256 key
|
|
287
|
+
* @returns The encoder instance for chaining
|
|
288
|
+
*/
|
|
289
|
+
encryptWithAes256(key: Uint8Array): Encoder;
|
|
290
|
+
/**
|
|
291
|
+
* Encrypt with AES-128-GCM.
|
|
292
|
+
* @param key - 16-byte AES-128 key
|
|
293
|
+
* @returns The encoder instance for chaining
|
|
294
|
+
*/
|
|
295
|
+
encryptWithAes128(key: Uint8Array): Encoder;
|
|
296
|
+
/**
|
|
297
|
+
* Allow encoding without a signature.
|
|
298
|
+
* WARNING: Unsigned credentials cannot be verified. Use for testing only.
|
|
299
|
+
* @returns The encoder instance for chaining
|
|
300
|
+
*/
|
|
301
|
+
allowUnsigned(): Encoder;
|
|
302
|
+
/**
|
|
303
|
+
* Skip biometric fields during encoding.
|
|
304
|
+
* @returns The encoder instance for chaining
|
|
305
|
+
*/
|
|
306
|
+
skipBiometrics(): Encoder;
|
|
307
|
+
/**
|
|
308
|
+
* Encode the credential to a Base45 QR string.
|
|
309
|
+
* @returns Base45-encoded string suitable for QR code generation
|
|
310
|
+
* @throws {Claim169Error} If encoding fails
|
|
311
|
+
*/
|
|
312
|
+
encode(): string;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Generate a random 12-byte nonce for AES-GCM encryption.
|
|
316
|
+
* @returns A 12-byte Uint8Array suitable for use as a nonce
|
|
317
|
+
*/
|
|
318
|
+
export declare function generateNonce(): Uint8Array;
|
|
319
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|