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/wasm/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # claim169-wasm
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
+ [![npm](https://img.shields.io/npm/v/claim169.svg)](https://www.npmjs.com/package/claim169)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ WebAssembly bindings for the MOSIP Claim 169 QR code decoder.
9
+
10
+ This crate compiles the `claim169-core` library to WebAssembly, enabling Claim 169 decoding in browsers and Node.js environments.
11
+
12
+ ## Installation
13
+
14
+ This package is typically consumed through the [TypeScript SDK](../../sdks/typescript). For direct WASM usage:
15
+
16
+ ```bash
17
+ npm install claim169
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Builder Pattern (Recommended)
23
+
24
+ ```typescript
25
+ import init, { Decoder } from 'claim169';
26
+
27
+ // Initialize WASM module
28
+ await init();
29
+
30
+ // Decode with Ed25519 signature verification (recommended)
31
+ const publicKey = new Uint8Array(32); // Your 32-byte public key
32
+ const result = new Decoder(qrText)
33
+ .verifyWithEd25519(publicKey)
34
+ .decode();
35
+
36
+ console.log(result.claim169.fullName);
37
+ console.log(result.verificationStatus); // "verified"
38
+
39
+ // Decode encrypted credential with verification
40
+ const result = new Decoder(qrText)
41
+ .decryptWithAes256(aesKey)
42
+ .verifyWithEd25519(publicKey)
43
+ .decode();
44
+
45
+ // Decode without verification (testing only)
46
+ const result = new Decoder(qrText)
47
+ .allowUnverified()
48
+ .decode();
49
+ ```
50
+
51
+ ### Encoding
52
+
53
+ ```javascript
54
+ import init, { Encoder, Decoder, generateNonce } from 'claim169';
55
+
56
+ await init();
57
+
58
+ // Create identity data
59
+ const claim169 = {
60
+ id: "123456789",
61
+ fullName: "John Doe",
62
+ dateOfBirth: "1990-01-15",
63
+ gender: 1,
64
+ };
65
+
66
+ // Create CWT metadata
67
+ const cwtMeta = {
68
+ issuer: "https://issuer.example.com",
69
+ expiresAt: 1800000000,
70
+ };
71
+
72
+ // Encode with Ed25519 signature
73
+ // (keys should be provisioned externally in production)
74
+ const privateKey = new Uint8Array(32);
75
+ const qrData = new Encoder(claim169, cwtMeta)
76
+ .signWithEd25519(privateKey)
77
+ .encode();
78
+
79
+ // Encode with signature and encryption
80
+ const aesKey = new Uint8Array(32);
81
+ const qrData = new Encoder(claim169, cwtMeta)
82
+ .signWithEd25519(privateKey)
83
+ .encryptWithAes256(aesKey)
84
+ .encode();
85
+ ```
86
+
87
+ ## API
88
+
89
+ ### Decoder
90
+
91
+ Builder-pattern class for decoding Claim 169 QR codes.
92
+
93
+ ```javascript
94
+ const decoder = new Decoder(qrText);
95
+
96
+ // Verification methods (one required)
97
+ decoder.verifyWithEd25519(publicKey); // Verify with Ed25519 (32 bytes)
98
+ decoder.verifyWithEcdsaP256(publicKey); // Verify with ECDSA P-256 (33 or 65 bytes)
99
+ decoder.allowUnverified(); // Skip verification (testing only)
100
+
101
+ // Decryption methods (optional)
102
+ decoder.decryptWithAes256(key); // Decrypt with AES-256-GCM (32 bytes)
103
+ decoder.decryptWithAes128(key); // Decrypt with AES-128-GCM (16 bytes)
104
+
105
+ // Configuration methods (chainable)
106
+ decoder.skipBiometrics(); // Skip biometric data parsing
107
+ decoder.withTimestampValidation(); // Enable timestamp validation
108
+ decoder.clockSkewTolerance(60); // Set clock skew tolerance (seconds)
109
+ decoder.maxDecompressedBytes(32768); // Set max decompressed size
110
+
111
+ // Execute decode
112
+ const result = decoder.decode();
113
+ ```
114
+
115
+ | Method | Description |
116
+ |--------|-------------|
117
+ | `verifyWithEd25519(publicKey)` | Verify with Ed25519 (32 bytes) |
118
+ | `verifyWithEcdsaP256(publicKey)` | Verify with ECDSA P-256 (33 or 65 bytes SEC1) |
119
+ | `allowUnverified()` | Skip verification (testing only) |
120
+ | `decryptWithAes256(key)` | Decrypt with AES-256-GCM (32 bytes) |
121
+ | `decryptWithAes128(key)` | Decrypt with AES-128-GCM (16 bytes) |
122
+ | `skipBiometrics()` | Skip biometric data parsing |
123
+ | `withTimestampValidation()` | Enable exp/nbf validation |
124
+ | `clockSkewTolerance(seconds)` | Set clock skew tolerance |
125
+ | `maxDecompressedBytes(bytes)` | Set max decompressed size |
126
+ | `decode()` | Execute the decode operation |
127
+
128
+ ### Encoder
129
+
130
+ Builder-pattern class for encoding Claim 169 credentials.
131
+
132
+ | Method | Description |
133
+ |--------|-------------|
134
+ | `signWithEd25519(privateKey)` | Sign with Ed25519 (32 bytes) |
135
+ | `signWithEcdsaP256(privateKey)` | Sign with ECDSA P-256 (32 bytes) |
136
+ | `encryptWithAes256(key)` | Encrypt with AES-256-GCM (32 bytes) |
137
+ | `encryptWithAes128(key)` | Encrypt with AES-128-GCM (16 bytes) |
138
+ | `allowUnsigned()` | Allow unsigned (testing only) |
139
+ | `skipBiometrics()` | Skip biometric fields |
140
+ | `encode()` | Produce the QR string |
141
+
142
+ ### Utility Functions
143
+
144
+ | Function | Description |
145
+ |----------|-------------|
146
+ | `generateNonce()` | Generate a cryptographically secure 12-byte nonce |
147
+ | `version()` | Get library version |
148
+ | `isLoaded()` | Check if WASM module is ready |
149
+
150
+ ## Notes
151
+
152
+ ### Timestamp Validation
153
+
154
+ Timestamp validation is disabled by default because WebAssembly doesn't have reliable access to system time. Enable it explicitly if your environment provides accurate time:
155
+
156
+ ```javascript
157
+ const result = new Decoder(qrText)
158
+ .verifyWithEd25519(publicKey)
159
+ .withTimestampValidation()
160
+ .clockSkewTolerance(60)
161
+ .decode();
162
+ ```
163
+
164
+ ### Secure by Default
165
+
166
+ The decoder requires explicit verification configuration. You must call one of:
167
+ - `verifyWithEd25519(publicKey)` - Verify with Ed25519
168
+ - `verifyWithEcdsaP256(publicKey)` - Verify with ECDSA P-256
169
+ - `allowUnverified()` - Explicitly skip verification (testing only)
170
+
171
+ This prevents accidentally processing unverified credentials.
172
+
173
+ ## Building from Source
174
+
175
+ ### Prerequisites
176
+
177
+ - Rust 1.70+
178
+ - wasm-pack (`cargo install wasm-pack`)
179
+
180
+ ### Build
181
+
182
+ ```bash
183
+ # Build for bundler (recommended for npm packages)
184
+ wasm-pack build --target bundler --release
185
+
186
+ # Build for web (direct browser usage)
187
+ wasm-pack build --target web --release
188
+
189
+ # Build for Node.js
190
+ wasm-pack build --target nodejs --release
191
+ ```
192
+
193
+ ### Output
194
+
195
+ The build produces:
196
+ - `pkg/claim169_wasm.js` - JavaScript glue code
197
+ - `pkg/claim169_wasm_bg.wasm` - WebAssembly binary
198
+ - `pkg/claim169_wasm.d.ts` - TypeScript definitions
199
+
200
+ ## Bundler Configuration
201
+
202
+ ### Vite
203
+
204
+ ```typescript
205
+ // vite.config.ts
206
+ import { defineConfig } from 'vite';
207
+ import wasm from 'vite-plugin-wasm';
208
+ import topLevelAwait from 'vite-plugin-top-level-await';
209
+
210
+ export default defineConfig({
211
+ plugins: [wasm(), topLevelAwait()],
212
+ });
213
+ ```
214
+
215
+ ### Webpack 5
216
+
217
+ ```javascript
218
+ // webpack.config.js
219
+ module.exports = {
220
+ experiments: {
221
+ asyncWebAssembly: true,
222
+ },
223
+ };
224
+ ```
225
+
226
+ ### Rollup
227
+
228
+ ```javascript
229
+ // rollup.config.js
230
+ import { wasm } from '@rollup/plugin-wasm';
231
+
232
+ export default {
233
+ plugins: [wasm()],
234
+ };
235
+ ```
236
+
237
+ ## Security Considerations
238
+
239
+ The WASM bindings include full signature verification and decryption support:
240
+
241
+ - **Ed25519** and **ECDSA P-256** signature verification
242
+ - **AES-128-GCM** and **AES-256-GCM** decryption
243
+ - Secure-by-default: verification is required unless explicitly disabled
244
+
245
+ Best practices:
246
+ - Always verify credentials using `verifyWithEd25519()` or `verifyWithEcdsaP256()`
247
+ - Only use `allowUnverified()` for testing or when verification is handled elsewhere
248
+ - Enable timestamp validation in production to reject expired credentials
249
+ - Set appropriate `maxDecompressedBytes` limits to prevent denial-of-service
250
+
251
+ ## Testing
252
+
253
+ ```bash
254
+ # Run Rust tests
255
+ cargo test
256
+
257
+ # Build and test in Node.js
258
+ wasm-pack build --target nodejs
259
+ node -e "const wasm = require('./pkg'); console.log(wasm.version());"
260
+ ```
261
+
262
+ ## License
263
+
264
+ MIT License - See [LICENSE](../../LICENSE) for details.
@@ -0,0 +1,99 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Decoder builder for Claim 169 credentials
6
+ */
7
+ export class WasmDecoder {
8
+ free(): void;
9
+ [Symbol.dispose](): void;
10
+ /**
11
+ * Allow decoding without signature verification (INSECURE - testing only)
12
+ */
13
+ allowUnverified(): WasmDecoder;
14
+ clockSkewTolerance(seconds: number): WasmDecoder;
15
+ /**
16
+ * Decode the QR code with configured verification and decryption
17
+ */
18
+ decode(): any;
19
+ /**
20
+ * Decrypt with AES-128-GCM (16-byte key)
21
+ */
22
+ decryptWithAes128(key: Uint8Array): WasmDecoder;
23
+ /**
24
+ * Decrypt with AES-256-GCM (32-byte key)
25
+ */
26
+ decryptWithAes256(key: Uint8Array): WasmDecoder;
27
+ maxDecompressedBytes(bytes: number): WasmDecoder;
28
+ constructor(qr_text: string);
29
+ skipBiometrics(): WasmDecoder;
30
+ /**
31
+ * Verify with ECDSA P-256 public key (33 or 65 bytes, SEC1 encoded)
32
+ */
33
+ verifyWithEcdsaP256(public_key: Uint8Array): WasmDecoder;
34
+ /**
35
+ * Verify with Ed25519 public key (32 bytes)
36
+ */
37
+ verifyWithEd25519(public_key: Uint8Array): WasmDecoder;
38
+ withTimestampValidation(): WasmDecoder;
39
+ }
40
+
41
+ /**
42
+ * Encoder builder for creating Claim 169 QR codes
43
+ */
44
+ export class WasmEncoder {
45
+ free(): void;
46
+ [Symbol.dispose](): void;
47
+ /**
48
+ * Allow encoding without a signature (INSECURE - testing only)
49
+ */
50
+ allowUnsigned(): WasmEncoder;
51
+ /**
52
+ * Encode the credential to a Base45 QR string
53
+ */
54
+ encode(): string;
55
+ /**
56
+ * Encrypt with AES-128-GCM (16-byte key)
57
+ */
58
+ encryptWithAes128(key: Uint8Array): WasmEncoder;
59
+ /**
60
+ * Encrypt with AES-256-GCM (32-byte key)
61
+ */
62
+ encryptWithAes256(key: Uint8Array): WasmEncoder;
63
+ /**
64
+ * Create a new encoder with the given claim and CWT metadata.
65
+ *
66
+ * @param claim169 - The identity claim data to encode
67
+ * @param cwtMeta - CWT metadata including issuer, expiration, etc.
68
+ */
69
+ constructor(claim169: any, cwt_meta: any);
70
+ /**
71
+ * Sign with ECDSA P-256 private key (32 bytes)
72
+ */
73
+ signWithEcdsaP256(private_key: Uint8Array): WasmEncoder;
74
+ /**
75
+ * Sign with Ed25519 private key (32 bytes)
76
+ */
77
+ signWithEd25519(private_key: Uint8Array): WasmEncoder;
78
+ /**
79
+ * Skip biometric fields during encoding
80
+ */
81
+ skipBiometrics(): WasmEncoder;
82
+ }
83
+
84
+ /**
85
+ * Generate a random 12-byte nonce for AES-GCM encryption
86
+ */
87
+ export function generateNonce(): Uint8Array;
88
+
89
+ export function init_panic_hook(): void;
90
+
91
+ /**
92
+ * Check if the WASM module is loaded correctly
93
+ */
94
+ export function isLoaded(): boolean;
95
+
96
+ /**
97
+ * Get the library version
98
+ */
99
+ export function version(): string;
@@ -0,0 +1,9 @@
1
+ /* @ts-self-types="./claim169_wasm.d.ts" */
2
+
3
+ import * as wasm from "./claim169_wasm_bg.wasm";
4
+ import { __wbg_set_wasm } from "./claim169_wasm_bg.js";
5
+ __wbg_set_wasm(wasm);
6
+ wasm.__wbindgen_start();
7
+ export {
8
+ WasmDecoder, WasmEncoder, generateNonce, init_panic_hook, isLoaded, version
9
+ } from "./claim169_wasm_bg.js";