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/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
|
+
[](https://www.npmjs.com/package/claim169)
|
|
6
|
+
[](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";
|