@gnufoo/canaad 0.1.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/README.md +104 -0
- package/canaad_wasm.d.ts +253 -0
- package/canaad_wasm.js +540 -0
- package/canaad_wasm_bg.wasm +0 -0
- package/package.json +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# canaad-wasm
|
|
2
|
+
|
|
3
|
+
WASM bindings for AAD (Additional Authenticated Data) canonicalization per RFC 8785.
|
|
4
|
+
|
|
5
|
+
This crate provides WebAssembly bindings for the `canaad-core` library, enabling
|
|
6
|
+
AAD canonicalization in browsers, Node.js, and other WASM runtimes like
|
|
7
|
+
Cloudflare Workers.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @gnufoo/canaad
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Canonicalize JSON
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { canonicalize, canonicalizeString, validate, hash } from '@gnufoo/canaad';
|
|
21
|
+
|
|
22
|
+
// Canonicalize JSON to bytes
|
|
23
|
+
const json = '{"v":1,"tenant":"org_abc","resource":"secrets/db","purpose":"encryption"}';
|
|
24
|
+
const bytes: Uint8Array = canonicalize(json);
|
|
25
|
+
|
|
26
|
+
// Canonicalize JSON to string
|
|
27
|
+
const canonical: string = canonicalizeString(json);
|
|
28
|
+
// => '{"purpose":"encryption","resource":"secrets/db","tenant":"org_abc","v":1}'
|
|
29
|
+
|
|
30
|
+
// Validate JSON
|
|
31
|
+
const isValid: boolean = validate(json);
|
|
32
|
+
|
|
33
|
+
// Get SHA-256 hash of canonical form
|
|
34
|
+
const hashBytes: Uint8Array = hash(json);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Builder API
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { AadBuilder } from '@gnufoo/canaad';
|
|
41
|
+
|
|
42
|
+
const builder = new AadBuilder()
|
|
43
|
+
.tenant("org_abc")
|
|
44
|
+
.resource("secrets/db")
|
|
45
|
+
.purpose("encryption")
|
|
46
|
+
.timestamp(1706400000)
|
|
47
|
+
.extensionString("x_vault_cluster", "us-east-1")
|
|
48
|
+
.extensionInt("x_app_priority", 5);
|
|
49
|
+
|
|
50
|
+
// Build to bytes
|
|
51
|
+
const bytes: Uint8Array = builder.build();
|
|
52
|
+
|
|
53
|
+
// Build to string
|
|
54
|
+
const canonical: string = builder.buildString();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Constants
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { SPEC_VERSION, MAX_SAFE_INTEGER, MAX_SERIALIZED_BYTES } from '@gnufoo/canaad';
|
|
61
|
+
|
|
62
|
+
console.log(SPEC_VERSION); // 1
|
|
63
|
+
console.log(MAX_SAFE_INTEGER); // 9007199254740991 (2^53 - 1)
|
|
64
|
+
console.log(MAX_SERIALIZED_BYTES); // 16384 (16 KiB)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Error Handling
|
|
68
|
+
|
|
69
|
+
All functions that can fail will throw JavaScript errors with descriptive messages:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
try {
|
|
73
|
+
canonicalize('{"v":1}'); // Missing required fields
|
|
74
|
+
} catch (e) {
|
|
75
|
+
console.error(e.message); // "missing required field: tenant"
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Supported Environments
|
|
80
|
+
|
|
81
|
+
- **Browsers**: Modern browsers with WASM support
|
|
82
|
+
- **Node.js**: v14+ with WASM support
|
|
83
|
+
- **Cloudflare Workers**: Full support
|
|
84
|
+
- **Deno**: With WASM import
|
|
85
|
+
|
|
86
|
+
## Building from Source
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Install wasm-pack
|
|
90
|
+
cargo install wasm-pack
|
|
91
|
+
|
|
92
|
+
# Build for bundlers (webpack, vite, etc.)
|
|
93
|
+
wasm-pack build --target bundler
|
|
94
|
+
|
|
95
|
+
# Build for Node.js
|
|
96
|
+
wasm-pack build --target nodejs
|
|
97
|
+
|
|
98
|
+
# Build for web (no bundler)
|
|
99
|
+
wasm-pack build --target web
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT OR Apache-2.0
|
package/canaad_wasm.d.ts
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Builder for constructing AAD objects programmatically.
|
|
6
|
+
*
|
|
7
|
+
* Provides a fluent API for building AAD with method chaining.
|
|
8
|
+
* All setter methods return a new builder to enable chaining.
|
|
9
|
+
*
|
|
10
|
+
* # Example (JavaScript)
|
|
11
|
+
*
|
|
12
|
+
* ```javascript
|
|
13
|
+
* const builder = new AadBuilder()
|
|
14
|
+
* .tenant("org_abc")
|
|
15
|
+
* .resource("secrets/db")
|
|
16
|
+
* .purpose("encryption")
|
|
17
|
+
* .timestamp(1706400000)
|
|
18
|
+
* .extensionString("x_vault_cluster", "us-east-1");
|
|
19
|
+
*
|
|
20
|
+
* const bytes = builder.build();
|
|
21
|
+
* const canonical = builder.buildString();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class AadBuilder {
|
|
25
|
+
free(): void;
|
|
26
|
+
[Symbol.dispose](): void;
|
|
27
|
+
/**
|
|
28
|
+
* Builds the AAD and returns the canonical bytes.
|
|
29
|
+
*
|
|
30
|
+
* # Returns
|
|
31
|
+
*
|
|
32
|
+
* A `Uint8Array` containing the UTF-8 encoded canonical JSON.
|
|
33
|
+
*
|
|
34
|
+
* # Errors
|
|
35
|
+
*
|
|
36
|
+
* Throws a JavaScript error if:
|
|
37
|
+
* - Required fields (tenant, resource, purpose) are missing
|
|
38
|
+
* - Any field value is invalid
|
|
39
|
+
* - Extension keys don't match the required pattern
|
|
40
|
+
* - The serialized output exceeds 16 KiB
|
|
41
|
+
*/
|
|
42
|
+
build(): Uint8Array;
|
|
43
|
+
/**
|
|
44
|
+
* Builds the AAD and returns the canonical string.
|
|
45
|
+
*
|
|
46
|
+
* # Returns
|
|
47
|
+
*
|
|
48
|
+
* The canonical (JCS) representation as a string.
|
|
49
|
+
*
|
|
50
|
+
* # Errors
|
|
51
|
+
*
|
|
52
|
+
* Throws a JavaScript error if:
|
|
53
|
+
* - Required fields (tenant, resource, purpose) are missing
|
|
54
|
+
* - Any field value is invalid
|
|
55
|
+
* - Extension keys don't match the required pattern
|
|
56
|
+
* - The serialized output exceeds 16 KiB
|
|
57
|
+
*/
|
|
58
|
+
buildString(): string;
|
|
59
|
+
/**
|
|
60
|
+
* Adds an integer extension field.
|
|
61
|
+
*
|
|
62
|
+
* Extension keys must match pattern `x_<app>_<field>` where:
|
|
63
|
+
* - `<app>` is one or more lowercase letters
|
|
64
|
+
* - `<field>` is one or more lowercase letters or underscores
|
|
65
|
+
*
|
|
66
|
+
* # Arguments
|
|
67
|
+
*
|
|
68
|
+
* * `key` - Extension key (e.g., `x_app_priority`)
|
|
69
|
+
* * `value` - Integer value (0 to 2^53-1)
|
|
70
|
+
*
|
|
71
|
+
* # Returns
|
|
72
|
+
*
|
|
73
|
+
* A new builder with the extension added.
|
|
74
|
+
*/
|
|
75
|
+
extensionInt(key: string, value: number): AadBuilder;
|
|
76
|
+
/**
|
|
77
|
+
* Adds a string extension field.
|
|
78
|
+
*
|
|
79
|
+
* Extension keys must match pattern `x_<app>_<field>` where:
|
|
80
|
+
* - `<app>` is one or more lowercase letters
|
|
81
|
+
* - `<field>` is one or more lowercase letters or underscores
|
|
82
|
+
*
|
|
83
|
+
* # Arguments
|
|
84
|
+
*
|
|
85
|
+
* * `key` - Extension key (e.g., `x_vault_cluster`)
|
|
86
|
+
* * `value` - String value (no NUL bytes)
|
|
87
|
+
*
|
|
88
|
+
* # Returns
|
|
89
|
+
*
|
|
90
|
+
* A new builder with the extension added.
|
|
91
|
+
*/
|
|
92
|
+
extensionString(key: string, value: string): AadBuilder;
|
|
93
|
+
/**
|
|
94
|
+
* Creates a new AAD builder.
|
|
95
|
+
*/
|
|
96
|
+
constructor();
|
|
97
|
+
/**
|
|
98
|
+
* Sets the purpose or usage context.
|
|
99
|
+
*
|
|
100
|
+
* # Arguments
|
|
101
|
+
*
|
|
102
|
+
* * `value` - Purpose description (1+ bytes, no NUL bytes)
|
|
103
|
+
*
|
|
104
|
+
* # Returns
|
|
105
|
+
*
|
|
106
|
+
* A new builder with the purpose set.
|
|
107
|
+
*/
|
|
108
|
+
purpose(value: string): AadBuilder;
|
|
109
|
+
/**
|
|
110
|
+
* Sets the resource path or identifier.
|
|
111
|
+
*
|
|
112
|
+
* # Arguments
|
|
113
|
+
*
|
|
114
|
+
* * `value` - Resource path (1-1024 bytes, no NUL bytes)
|
|
115
|
+
*
|
|
116
|
+
* # Returns
|
|
117
|
+
*
|
|
118
|
+
* A new builder with the resource set.
|
|
119
|
+
*/
|
|
120
|
+
resource(value: string): AadBuilder;
|
|
121
|
+
/**
|
|
122
|
+
* Sets the tenant identifier.
|
|
123
|
+
*
|
|
124
|
+
* # Arguments
|
|
125
|
+
*
|
|
126
|
+
* * `value` - Tenant identifier (1-256 bytes, no NUL bytes)
|
|
127
|
+
*
|
|
128
|
+
* # Returns
|
|
129
|
+
*
|
|
130
|
+
* A new builder with the tenant set.
|
|
131
|
+
*/
|
|
132
|
+
tenant(value: string): AadBuilder;
|
|
133
|
+
/**
|
|
134
|
+
* Sets the timestamp.
|
|
135
|
+
*
|
|
136
|
+
* # Arguments
|
|
137
|
+
*
|
|
138
|
+
* * `ts` - Unix timestamp (0 to 2^53-1)
|
|
139
|
+
*
|
|
140
|
+
* # Returns
|
|
141
|
+
*
|
|
142
|
+
* A new builder with the timestamp set.
|
|
143
|
+
*/
|
|
144
|
+
timestamp(ts: number): AadBuilder;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Returns the maximum safe integer value (2^53 - 1).
|
|
149
|
+
*
|
|
150
|
+
* This is the maximum integer value that can be exactly represented in
|
|
151
|
+
* JavaScript's Number type.
|
|
152
|
+
*/
|
|
153
|
+
export function MAX_SAFE_INTEGER(): number;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Returns the maximum serialized AAD size in bytes (16 KiB).
|
|
157
|
+
*/
|
|
158
|
+
export function MAX_SERIALIZED_BYTES(): number;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Returns the current AAD specification version.
|
|
162
|
+
*
|
|
163
|
+
* Currently always returns 1.
|
|
164
|
+
*/
|
|
165
|
+
export function SPEC_VERSION(): number;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Parses and canonicalizes a JSON string to bytes.
|
|
169
|
+
*
|
|
170
|
+
* This function:
|
|
171
|
+
* 1. Parses the JSON with duplicate key detection
|
|
172
|
+
* 2. Validates all fields according to the AAD specification
|
|
173
|
+
* 3. Returns the canonical (JCS) representation as bytes
|
|
174
|
+
*
|
|
175
|
+
* # Arguments
|
|
176
|
+
*
|
|
177
|
+
* * `json` - A JSON string containing an AAD object
|
|
178
|
+
*
|
|
179
|
+
* # Returns
|
|
180
|
+
*
|
|
181
|
+
* A `Uint8Array` containing the UTF-8 encoded canonical JSON.
|
|
182
|
+
*
|
|
183
|
+
* # Errors
|
|
184
|
+
*
|
|
185
|
+
* Throws a JavaScript error if:
|
|
186
|
+
* - The JSON is invalid or contains duplicate keys
|
|
187
|
+
* - Any field violates AAD constraints
|
|
188
|
+
* - The serialized output exceeds 16 KiB
|
|
189
|
+
*/
|
|
190
|
+
export function canonicalize(json: string): Uint8Array;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Parses and canonicalizes a JSON string to a UTF-8 string.
|
|
194
|
+
*
|
|
195
|
+
* This is equivalent to `canonicalize` but returns a string instead of bytes.
|
|
196
|
+
*
|
|
197
|
+
* # Arguments
|
|
198
|
+
*
|
|
199
|
+
* * `json` - A JSON string containing an AAD object
|
|
200
|
+
*
|
|
201
|
+
* # Returns
|
|
202
|
+
*
|
|
203
|
+
* The canonical (JCS) representation as a string.
|
|
204
|
+
*
|
|
205
|
+
* # Errors
|
|
206
|
+
*
|
|
207
|
+
* Throws a JavaScript error if:
|
|
208
|
+
* - The JSON is invalid or contains duplicate keys
|
|
209
|
+
* - Any field violates AAD constraints
|
|
210
|
+
* - The serialized output exceeds 16 KiB
|
|
211
|
+
*/
|
|
212
|
+
export function canonicalizeString(json: string): string;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Computes the SHA-256 hash of the canonical JSON form.
|
|
216
|
+
*
|
|
217
|
+
* This function:
|
|
218
|
+
* 1. Parses and validates the JSON
|
|
219
|
+
* 2. Canonicalizes according to RFC 8785
|
|
220
|
+
* 3. Returns the SHA-256 hash of the canonical bytes
|
|
221
|
+
*
|
|
222
|
+
* # Arguments
|
|
223
|
+
*
|
|
224
|
+
* * `json` - A JSON string containing an AAD object
|
|
225
|
+
*
|
|
226
|
+
* # Returns
|
|
227
|
+
*
|
|
228
|
+
* A 32-byte `Uint8Array` containing the SHA-256 hash.
|
|
229
|
+
*
|
|
230
|
+
* # Errors
|
|
231
|
+
*
|
|
232
|
+
* Throws a JavaScript error if:
|
|
233
|
+
* - The JSON is invalid or contains duplicate keys
|
|
234
|
+
* - Any field violates AAD constraints
|
|
235
|
+
* - The serialized output exceeds 16 KiB
|
|
236
|
+
*/
|
|
237
|
+
export function hash(json: string): Uint8Array;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Validates a JSON string against the AAD specification.
|
|
241
|
+
*
|
|
242
|
+
* This function performs full validation without returning the context.
|
|
243
|
+
* Use this for quick validation checks.
|
|
244
|
+
*
|
|
245
|
+
* # Arguments
|
|
246
|
+
*
|
|
247
|
+
* * `json` - A JSON string to validate
|
|
248
|
+
*
|
|
249
|
+
* # Returns
|
|
250
|
+
*
|
|
251
|
+
* `true` if the JSON is valid AAD, `false` otherwise.
|
|
252
|
+
*/
|
|
253
|
+
export function validate(json: string): boolean;
|
package/canaad_wasm.js
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
/* @ts-self-types="./canaad_wasm.d.ts" */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builder for constructing AAD objects programmatically.
|
|
5
|
+
*
|
|
6
|
+
* Provides a fluent API for building AAD with method chaining.
|
|
7
|
+
* All setter methods return a new builder to enable chaining.
|
|
8
|
+
*
|
|
9
|
+
* # Example (JavaScript)
|
|
10
|
+
*
|
|
11
|
+
* ```javascript
|
|
12
|
+
* const builder = new AadBuilder()
|
|
13
|
+
* .tenant("org_abc")
|
|
14
|
+
* .resource("secrets/db")
|
|
15
|
+
* .purpose("encryption")
|
|
16
|
+
* .timestamp(1706400000)
|
|
17
|
+
* .extensionString("x_vault_cluster", "us-east-1");
|
|
18
|
+
*
|
|
19
|
+
* const bytes = builder.build();
|
|
20
|
+
* const canonical = builder.buildString();
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
class AadBuilder {
|
|
24
|
+
static __wrap(ptr) {
|
|
25
|
+
ptr = ptr >>> 0;
|
|
26
|
+
const obj = Object.create(AadBuilder.prototype);
|
|
27
|
+
obj.__wbg_ptr = ptr;
|
|
28
|
+
AadBuilderFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
29
|
+
return obj;
|
|
30
|
+
}
|
|
31
|
+
__destroy_into_raw() {
|
|
32
|
+
const ptr = this.__wbg_ptr;
|
|
33
|
+
this.__wbg_ptr = 0;
|
|
34
|
+
AadBuilderFinalization.unregister(this);
|
|
35
|
+
return ptr;
|
|
36
|
+
}
|
|
37
|
+
free() {
|
|
38
|
+
const ptr = this.__destroy_into_raw();
|
|
39
|
+
wasm.__wbg_aadbuilder_free(ptr, 0);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Builds the AAD and returns the canonical bytes.
|
|
43
|
+
*
|
|
44
|
+
* # Returns
|
|
45
|
+
*
|
|
46
|
+
* A `Uint8Array` containing the UTF-8 encoded canonical JSON.
|
|
47
|
+
*
|
|
48
|
+
* # Errors
|
|
49
|
+
*
|
|
50
|
+
* Throws a JavaScript error if:
|
|
51
|
+
* - Required fields (tenant, resource, purpose) are missing
|
|
52
|
+
* - Any field value is invalid
|
|
53
|
+
* - Extension keys don't match the required pattern
|
|
54
|
+
* - The serialized output exceeds 16 KiB
|
|
55
|
+
* @returns {Uint8Array}
|
|
56
|
+
*/
|
|
57
|
+
build() {
|
|
58
|
+
const ret = wasm.aadbuilder_build(this.__wbg_ptr);
|
|
59
|
+
if (ret[3]) {
|
|
60
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
61
|
+
}
|
|
62
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
63
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
64
|
+
return v1;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Builds the AAD and returns the canonical string.
|
|
68
|
+
*
|
|
69
|
+
* # Returns
|
|
70
|
+
*
|
|
71
|
+
* The canonical (JCS) representation as a string.
|
|
72
|
+
*
|
|
73
|
+
* # Errors
|
|
74
|
+
*
|
|
75
|
+
* Throws a JavaScript error if:
|
|
76
|
+
* - Required fields (tenant, resource, purpose) are missing
|
|
77
|
+
* - Any field value is invalid
|
|
78
|
+
* - Extension keys don't match the required pattern
|
|
79
|
+
* - The serialized output exceeds 16 KiB
|
|
80
|
+
* @returns {string}
|
|
81
|
+
*/
|
|
82
|
+
buildString() {
|
|
83
|
+
let deferred2_0;
|
|
84
|
+
let deferred2_1;
|
|
85
|
+
try {
|
|
86
|
+
const ret = wasm.aadbuilder_buildString(this.__wbg_ptr);
|
|
87
|
+
var ptr1 = ret[0];
|
|
88
|
+
var len1 = ret[1];
|
|
89
|
+
if (ret[3]) {
|
|
90
|
+
ptr1 = 0; len1 = 0;
|
|
91
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
92
|
+
}
|
|
93
|
+
deferred2_0 = ptr1;
|
|
94
|
+
deferred2_1 = len1;
|
|
95
|
+
return getStringFromWasm0(ptr1, len1);
|
|
96
|
+
} finally {
|
|
97
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Adds an integer extension field.
|
|
102
|
+
*
|
|
103
|
+
* Extension keys must match pattern `x_<app>_<field>` where:
|
|
104
|
+
* - `<app>` is one or more lowercase letters
|
|
105
|
+
* - `<field>` is one or more lowercase letters or underscores
|
|
106
|
+
*
|
|
107
|
+
* # Arguments
|
|
108
|
+
*
|
|
109
|
+
* * `key` - Extension key (e.g., `x_app_priority`)
|
|
110
|
+
* * `value` - Integer value (0 to 2^53-1)
|
|
111
|
+
*
|
|
112
|
+
* # Returns
|
|
113
|
+
*
|
|
114
|
+
* A new builder with the extension added.
|
|
115
|
+
* @param {string} key
|
|
116
|
+
* @param {number} value
|
|
117
|
+
* @returns {AadBuilder}
|
|
118
|
+
*/
|
|
119
|
+
extensionInt(key, value) {
|
|
120
|
+
const ptr = this.__destroy_into_raw();
|
|
121
|
+
const ptr0 = passStringToWasm0(key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
122
|
+
const len0 = WASM_VECTOR_LEN;
|
|
123
|
+
const ret = wasm.aadbuilder_extensionInt(ptr, ptr0, len0, value);
|
|
124
|
+
return AadBuilder.__wrap(ret);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Adds a string extension field.
|
|
128
|
+
*
|
|
129
|
+
* Extension keys must match pattern `x_<app>_<field>` where:
|
|
130
|
+
* - `<app>` is one or more lowercase letters
|
|
131
|
+
* - `<field>` is one or more lowercase letters or underscores
|
|
132
|
+
*
|
|
133
|
+
* # Arguments
|
|
134
|
+
*
|
|
135
|
+
* * `key` - Extension key (e.g., `x_vault_cluster`)
|
|
136
|
+
* * `value` - String value (no NUL bytes)
|
|
137
|
+
*
|
|
138
|
+
* # Returns
|
|
139
|
+
*
|
|
140
|
+
* A new builder with the extension added.
|
|
141
|
+
* @param {string} key
|
|
142
|
+
* @param {string} value
|
|
143
|
+
* @returns {AadBuilder}
|
|
144
|
+
*/
|
|
145
|
+
extensionString(key, value) {
|
|
146
|
+
const ptr = this.__destroy_into_raw();
|
|
147
|
+
const ptr0 = passStringToWasm0(key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
148
|
+
const len0 = WASM_VECTOR_LEN;
|
|
149
|
+
const ptr1 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
150
|
+
const len1 = WASM_VECTOR_LEN;
|
|
151
|
+
const ret = wasm.aadbuilder_extensionString(ptr, ptr0, len0, ptr1, len1);
|
|
152
|
+
return AadBuilder.__wrap(ret);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Creates a new AAD builder.
|
|
156
|
+
*/
|
|
157
|
+
constructor() {
|
|
158
|
+
const ret = wasm.aadbuilder_new();
|
|
159
|
+
this.__wbg_ptr = ret >>> 0;
|
|
160
|
+
AadBuilderFinalization.register(this, this.__wbg_ptr, this);
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Sets the purpose or usage context.
|
|
165
|
+
*
|
|
166
|
+
* # Arguments
|
|
167
|
+
*
|
|
168
|
+
* * `value` - Purpose description (1+ bytes, no NUL bytes)
|
|
169
|
+
*
|
|
170
|
+
* # Returns
|
|
171
|
+
*
|
|
172
|
+
* A new builder with the purpose set.
|
|
173
|
+
* @param {string} value
|
|
174
|
+
* @returns {AadBuilder}
|
|
175
|
+
*/
|
|
176
|
+
purpose(value) {
|
|
177
|
+
const ptr = this.__destroy_into_raw();
|
|
178
|
+
const ptr0 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
179
|
+
const len0 = WASM_VECTOR_LEN;
|
|
180
|
+
const ret = wasm.aadbuilder_purpose(ptr, ptr0, len0);
|
|
181
|
+
return AadBuilder.__wrap(ret);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Sets the resource path or identifier.
|
|
185
|
+
*
|
|
186
|
+
* # Arguments
|
|
187
|
+
*
|
|
188
|
+
* * `value` - Resource path (1-1024 bytes, no NUL bytes)
|
|
189
|
+
*
|
|
190
|
+
* # Returns
|
|
191
|
+
*
|
|
192
|
+
* A new builder with the resource set.
|
|
193
|
+
* @param {string} value
|
|
194
|
+
* @returns {AadBuilder}
|
|
195
|
+
*/
|
|
196
|
+
resource(value) {
|
|
197
|
+
const ptr = this.__destroy_into_raw();
|
|
198
|
+
const ptr0 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
199
|
+
const len0 = WASM_VECTOR_LEN;
|
|
200
|
+
const ret = wasm.aadbuilder_resource(ptr, ptr0, len0);
|
|
201
|
+
return AadBuilder.__wrap(ret);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Sets the tenant identifier.
|
|
205
|
+
*
|
|
206
|
+
* # Arguments
|
|
207
|
+
*
|
|
208
|
+
* * `value` - Tenant identifier (1-256 bytes, no NUL bytes)
|
|
209
|
+
*
|
|
210
|
+
* # Returns
|
|
211
|
+
*
|
|
212
|
+
* A new builder with the tenant set.
|
|
213
|
+
* @param {string} value
|
|
214
|
+
* @returns {AadBuilder}
|
|
215
|
+
*/
|
|
216
|
+
tenant(value) {
|
|
217
|
+
const ptr = this.__destroy_into_raw();
|
|
218
|
+
const ptr0 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
219
|
+
const len0 = WASM_VECTOR_LEN;
|
|
220
|
+
const ret = wasm.aadbuilder_tenant(ptr, ptr0, len0);
|
|
221
|
+
return AadBuilder.__wrap(ret);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Sets the timestamp.
|
|
225
|
+
*
|
|
226
|
+
* # Arguments
|
|
227
|
+
*
|
|
228
|
+
* * `ts` - Unix timestamp (0 to 2^53-1)
|
|
229
|
+
*
|
|
230
|
+
* # Returns
|
|
231
|
+
*
|
|
232
|
+
* A new builder with the timestamp set.
|
|
233
|
+
* @param {number} ts
|
|
234
|
+
* @returns {AadBuilder}
|
|
235
|
+
*/
|
|
236
|
+
timestamp(ts) {
|
|
237
|
+
const ptr = this.__destroy_into_raw();
|
|
238
|
+
const ret = wasm.aadbuilder_timestamp(ptr, ts);
|
|
239
|
+
return AadBuilder.__wrap(ret);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (Symbol.dispose) AadBuilder.prototype[Symbol.dispose] = AadBuilder.prototype.free;
|
|
243
|
+
exports.AadBuilder = AadBuilder;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Returns the maximum safe integer value (2^53 - 1).
|
|
247
|
+
*
|
|
248
|
+
* This is the maximum integer value that can be exactly represented in
|
|
249
|
+
* JavaScript's Number type.
|
|
250
|
+
* @returns {number}
|
|
251
|
+
*/
|
|
252
|
+
function MAX_SAFE_INTEGER() {
|
|
253
|
+
const ret = wasm.MAX_SAFE_INTEGER();
|
|
254
|
+
return ret;
|
|
255
|
+
}
|
|
256
|
+
exports.MAX_SAFE_INTEGER = MAX_SAFE_INTEGER;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Returns the maximum serialized AAD size in bytes (16 KiB).
|
|
260
|
+
* @returns {number}
|
|
261
|
+
*/
|
|
262
|
+
function MAX_SERIALIZED_BYTES() {
|
|
263
|
+
const ret = wasm.MAX_SERIALIZED_BYTES();
|
|
264
|
+
return ret >>> 0;
|
|
265
|
+
}
|
|
266
|
+
exports.MAX_SERIALIZED_BYTES = MAX_SERIALIZED_BYTES;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Returns the current AAD specification version.
|
|
270
|
+
*
|
|
271
|
+
* Currently always returns 1.
|
|
272
|
+
* @returns {number}
|
|
273
|
+
*/
|
|
274
|
+
function SPEC_VERSION() {
|
|
275
|
+
const ret = wasm.SPEC_VERSION();
|
|
276
|
+
return ret >>> 0;
|
|
277
|
+
}
|
|
278
|
+
exports.SPEC_VERSION = SPEC_VERSION;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Parses and canonicalizes a JSON string to bytes.
|
|
282
|
+
*
|
|
283
|
+
* This function:
|
|
284
|
+
* 1. Parses the JSON with duplicate key detection
|
|
285
|
+
* 2. Validates all fields according to the AAD specification
|
|
286
|
+
* 3. Returns the canonical (JCS) representation as bytes
|
|
287
|
+
*
|
|
288
|
+
* # Arguments
|
|
289
|
+
*
|
|
290
|
+
* * `json` - A JSON string containing an AAD object
|
|
291
|
+
*
|
|
292
|
+
* # Returns
|
|
293
|
+
*
|
|
294
|
+
* A `Uint8Array` containing the UTF-8 encoded canonical JSON.
|
|
295
|
+
*
|
|
296
|
+
* # Errors
|
|
297
|
+
*
|
|
298
|
+
* Throws a JavaScript error if:
|
|
299
|
+
* - The JSON is invalid or contains duplicate keys
|
|
300
|
+
* - Any field violates AAD constraints
|
|
301
|
+
* - The serialized output exceeds 16 KiB
|
|
302
|
+
* @param {string} json
|
|
303
|
+
* @returns {Uint8Array}
|
|
304
|
+
*/
|
|
305
|
+
function canonicalize(json) {
|
|
306
|
+
const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
307
|
+
const len0 = WASM_VECTOR_LEN;
|
|
308
|
+
const ret = wasm.canonicalize(ptr0, len0);
|
|
309
|
+
if (ret[3]) {
|
|
310
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
311
|
+
}
|
|
312
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
313
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
314
|
+
return v2;
|
|
315
|
+
}
|
|
316
|
+
exports.canonicalize = canonicalize;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Parses and canonicalizes a JSON string to a UTF-8 string.
|
|
320
|
+
*
|
|
321
|
+
* This is equivalent to `canonicalize` but returns a string instead of bytes.
|
|
322
|
+
*
|
|
323
|
+
* # Arguments
|
|
324
|
+
*
|
|
325
|
+
* * `json` - A JSON string containing an AAD object
|
|
326
|
+
*
|
|
327
|
+
* # Returns
|
|
328
|
+
*
|
|
329
|
+
* The canonical (JCS) representation as a string.
|
|
330
|
+
*
|
|
331
|
+
* # Errors
|
|
332
|
+
*
|
|
333
|
+
* Throws a JavaScript error if:
|
|
334
|
+
* - The JSON is invalid or contains duplicate keys
|
|
335
|
+
* - Any field violates AAD constraints
|
|
336
|
+
* - The serialized output exceeds 16 KiB
|
|
337
|
+
* @param {string} json
|
|
338
|
+
* @returns {string}
|
|
339
|
+
*/
|
|
340
|
+
function canonicalizeString(json) {
|
|
341
|
+
let deferred3_0;
|
|
342
|
+
let deferred3_1;
|
|
343
|
+
try {
|
|
344
|
+
const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
345
|
+
const len0 = WASM_VECTOR_LEN;
|
|
346
|
+
const ret = wasm.canonicalizeString(ptr0, len0);
|
|
347
|
+
var ptr2 = ret[0];
|
|
348
|
+
var len2 = ret[1];
|
|
349
|
+
if (ret[3]) {
|
|
350
|
+
ptr2 = 0; len2 = 0;
|
|
351
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
352
|
+
}
|
|
353
|
+
deferred3_0 = ptr2;
|
|
354
|
+
deferred3_1 = len2;
|
|
355
|
+
return getStringFromWasm0(ptr2, len2);
|
|
356
|
+
} finally {
|
|
357
|
+
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
exports.canonicalizeString = canonicalizeString;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Computes the SHA-256 hash of the canonical JSON form.
|
|
364
|
+
*
|
|
365
|
+
* This function:
|
|
366
|
+
* 1. Parses and validates the JSON
|
|
367
|
+
* 2. Canonicalizes according to RFC 8785
|
|
368
|
+
* 3. Returns the SHA-256 hash of the canonical bytes
|
|
369
|
+
*
|
|
370
|
+
* # Arguments
|
|
371
|
+
*
|
|
372
|
+
* * `json` - A JSON string containing an AAD object
|
|
373
|
+
*
|
|
374
|
+
* # Returns
|
|
375
|
+
*
|
|
376
|
+
* A 32-byte `Uint8Array` containing the SHA-256 hash.
|
|
377
|
+
*
|
|
378
|
+
* # Errors
|
|
379
|
+
*
|
|
380
|
+
* Throws a JavaScript error if:
|
|
381
|
+
* - The JSON is invalid or contains duplicate keys
|
|
382
|
+
* - Any field violates AAD constraints
|
|
383
|
+
* - The serialized output exceeds 16 KiB
|
|
384
|
+
* @param {string} json
|
|
385
|
+
* @returns {Uint8Array}
|
|
386
|
+
*/
|
|
387
|
+
function hash(json) {
|
|
388
|
+
const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
389
|
+
const len0 = WASM_VECTOR_LEN;
|
|
390
|
+
const ret = wasm.hash(ptr0, len0);
|
|
391
|
+
if (ret[3]) {
|
|
392
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
393
|
+
}
|
|
394
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
395
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
396
|
+
return v2;
|
|
397
|
+
}
|
|
398
|
+
exports.hash = hash;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Validates a JSON string against the AAD specification.
|
|
402
|
+
*
|
|
403
|
+
* This function performs full validation without returning the context.
|
|
404
|
+
* Use this for quick validation checks.
|
|
405
|
+
*
|
|
406
|
+
* # Arguments
|
|
407
|
+
*
|
|
408
|
+
* * `json` - A JSON string to validate
|
|
409
|
+
*
|
|
410
|
+
* # Returns
|
|
411
|
+
*
|
|
412
|
+
* `true` if the JSON is valid AAD, `false` otherwise.
|
|
413
|
+
* @param {string} json
|
|
414
|
+
* @returns {boolean}
|
|
415
|
+
*/
|
|
416
|
+
function validate(json) {
|
|
417
|
+
const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
418
|
+
const len0 = WASM_VECTOR_LEN;
|
|
419
|
+
const ret = wasm.validate(ptr0, len0);
|
|
420
|
+
return ret !== 0;
|
|
421
|
+
}
|
|
422
|
+
exports.validate = validate;
|
|
423
|
+
|
|
424
|
+
function __wbg_get_imports() {
|
|
425
|
+
const import0 = {
|
|
426
|
+
__proto__: null,
|
|
427
|
+
__wbg_Error_8c4e43fe74559d73: function(arg0, arg1) {
|
|
428
|
+
const ret = Error(getStringFromWasm0(arg0, arg1));
|
|
429
|
+
return ret;
|
|
430
|
+
},
|
|
431
|
+
__wbg___wbindgen_throw_be289d5034ed271b: function(arg0, arg1) {
|
|
432
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
433
|
+
},
|
|
434
|
+
__wbindgen_init_externref_table: function() {
|
|
435
|
+
const table = wasm.__wbindgen_externrefs;
|
|
436
|
+
const offset = table.grow(4);
|
|
437
|
+
table.set(0, undefined);
|
|
438
|
+
table.set(offset + 0, undefined);
|
|
439
|
+
table.set(offset + 1, null);
|
|
440
|
+
table.set(offset + 2, true);
|
|
441
|
+
table.set(offset + 3, false);
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
return {
|
|
445
|
+
__proto__: null,
|
|
446
|
+
"./canaad_wasm_bg.js": import0,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const AadBuilderFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
451
|
+
? { register: () => {}, unregister: () => {} }
|
|
452
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_aadbuilder_free(ptr >>> 0, 1));
|
|
453
|
+
|
|
454
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
455
|
+
ptr = ptr >>> 0;
|
|
456
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function getStringFromWasm0(ptr, len) {
|
|
460
|
+
ptr = ptr >>> 0;
|
|
461
|
+
return decodeText(ptr, len);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
let cachedUint8ArrayMemory0 = null;
|
|
465
|
+
function getUint8ArrayMemory0() {
|
|
466
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
467
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
468
|
+
}
|
|
469
|
+
return cachedUint8ArrayMemory0;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
473
|
+
if (realloc === undefined) {
|
|
474
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
475
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
476
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
477
|
+
WASM_VECTOR_LEN = buf.length;
|
|
478
|
+
return ptr;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
let len = arg.length;
|
|
482
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
483
|
+
|
|
484
|
+
const mem = getUint8ArrayMemory0();
|
|
485
|
+
|
|
486
|
+
let offset = 0;
|
|
487
|
+
|
|
488
|
+
for (; offset < len; offset++) {
|
|
489
|
+
const code = arg.charCodeAt(offset);
|
|
490
|
+
if (code > 0x7F) break;
|
|
491
|
+
mem[ptr + offset] = code;
|
|
492
|
+
}
|
|
493
|
+
if (offset !== len) {
|
|
494
|
+
if (offset !== 0) {
|
|
495
|
+
arg = arg.slice(offset);
|
|
496
|
+
}
|
|
497
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
498
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
499
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
500
|
+
|
|
501
|
+
offset += ret.written;
|
|
502
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
WASM_VECTOR_LEN = offset;
|
|
506
|
+
return ptr;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function takeFromExternrefTable0(idx) {
|
|
510
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
511
|
+
wasm.__externref_table_dealloc(idx);
|
|
512
|
+
return value;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
516
|
+
cachedTextDecoder.decode();
|
|
517
|
+
function decodeText(ptr, len) {
|
|
518
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const cachedTextEncoder = new TextEncoder();
|
|
522
|
+
|
|
523
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
524
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
525
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
526
|
+
view.set(buf);
|
|
527
|
+
return {
|
|
528
|
+
read: arg.length,
|
|
529
|
+
written: buf.length
|
|
530
|
+
};
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
let WASM_VECTOR_LEN = 0;
|
|
535
|
+
|
|
536
|
+
const wasmPath = `${__dirname}/canaad_wasm_bg.wasm`;
|
|
537
|
+
const wasmBytes = require('fs').readFileSync(wasmPath);
|
|
538
|
+
const wasmModule = new WebAssembly.Module(wasmBytes);
|
|
539
|
+
const wasm = new WebAssembly.Instance(wasmModule, __wbg_get_imports()).exports;
|
|
540
|
+
wasm.__wbindgen_start();
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gnufoo/canaad",
|
|
3
|
+
"description": "WASM bindings for AAD canonicalization per RFC 8785",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"license": "MIT OR Apache-2.0",
|
|
6
|
+
"files": [
|
|
7
|
+
"canaad_wasm_bg.wasm",
|
|
8
|
+
"canaad_wasm.js",
|
|
9
|
+
"canaad_wasm.d.ts"
|
|
10
|
+
],
|
|
11
|
+
"main": "canaad_wasm.js",
|
|
12
|
+
"types": "canaad_wasm.d.ts",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"aead",
|
|
15
|
+
"aad",
|
|
16
|
+
"canonicalization",
|
|
17
|
+
"jcs",
|
|
18
|
+
"rfc8785"
|
|
19
|
+
]
|
|
20
|
+
}
|