@hpke/hybridkem-x-wing 0.2.0 → 0.4.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 +35 -30
- package/esm/mod.d.ts +1 -1
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +1 -1
- package/esm/src/{hybridkemXWing.d.ts → xWing.d.ts} +20 -4
- package/esm/src/xWing.d.ts.map +1 -0
- package/esm/src/{hybridkemXWing.js → xWing.js} +21 -5
- package/esm/test/testVectors.d.ts.map +1 -1
- package/package.json +5 -5
- package/script/mod.d.ts +1 -1
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +4 -4
- package/script/src/{hybridkemXWing.d.ts → xWing.d.ts} +20 -4
- package/script/src/xWing.d.ts.map +1 -0
- package/script/src/{hybridkemXWing.js → xWing.js} +23 -7
- package/script/test/testVectors.d.ts.map +1 -1
- package/esm/src/hybridkemXWing.d.ts.map +0 -1
- package/script/src/hybridkemXWing.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Documentation: [jsr.io](https://jsr.io/@hpke/hybridkem-x-wing/doc) |
|
|
|
27
27
|
|
|
28
28
|
## Installation
|
|
29
29
|
|
|
30
|
-
`@hpke/hybridkem-x-wing`
|
|
30
|
+
`@hpke/hybridkem-x-wing` needs to be used with
|
|
31
31
|
[@hpke/core](https://github.com/dajiaji/hpke-js/blob/main/packages/core/README.md),
|
|
32
32
|
which can be installed in the same manner as desribed below.
|
|
33
33
|
|
|
@@ -52,8 +52,8 @@ such as Cloudflare Workers and Bun.
|
|
|
52
52
|
Then, you can use the module from code like this:
|
|
53
53
|
|
|
54
54
|
```ts
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
55
|
+
import { Aes256Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
56
|
+
import { XWing } from "@hpke/hybridkem-x-wing";
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
### Deno
|
|
@@ -75,22 +75,22 @@ Using esm.sh:
|
|
|
75
75
|
<!-- use a specific version -->
|
|
76
76
|
<script type="module">
|
|
77
77
|
import {
|
|
78
|
-
|
|
78
|
+
Aes256Gcm,
|
|
79
79
|
CipherSuite,
|
|
80
80
|
HkdfSha256,
|
|
81
81
|
} from "https://esm.sh/@hpke/core@<SEMVER>";
|
|
82
|
-
import {
|
|
82
|
+
import { XWing } from "https://esm.sh/@hpke/hybridkem-x-wing@<SEMVER>";
|
|
83
83
|
// ...
|
|
84
84
|
</script>
|
|
85
85
|
|
|
86
86
|
<!-- use the latest stable version -->
|
|
87
87
|
<script type="module">
|
|
88
88
|
import {
|
|
89
|
-
|
|
89
|
+
Aes256Gcm,
|
|
90
90
|
CipherSuite,
|
|
91
91
|
HkdfSha256,
|
|
92
92
|
} from "https://esm.sh/@hpke/core";
|
|
93
|
-
import {
|
|
93
|
+
import { XWing } from "https://esm.sh/@hpke/hybridkem-x-wing";
|
|
94
94
|
// ...
|
|
95
95
|
</script>
|
|
96
96
|
```
|
|
@@ -101,11 +101,11 @@ Using unpkg:
|
|
|
101
101
|
<!-- use a specific version -->
|
|
102
102
|
<script type="module">
|
|
103
103
|
import {
|
|
104
|
-
|
|
104
|
+
Aes256Gcm,
|
|
105
105
|
CipherSuite,
|
|
106
106
|
HkdfSha256,
|
|
107
107
|
} from "https://unpkg.com/@hpke/core@<SEMVER>/esm/mod.js";
|
|
108
|
-
import {
|
|
108
|
+
import { XWing } from "https://unpkg.com/@hpke/hybridkem-x-wing@<SEMVER>/esm/mod.js";
|
|
109
109
|
// ...
|
|
110
110
|
</script>
|
|
111
111
|
```
|
|
@@ -117,33 +117,34 @@ This section shows some typical usage examples.
|
|
|
117
117
|
### Node.js
|
|
118
118
|
|
|
119
119
|
```js
|
|
120
|
-
import {
|
|
121
|
-
import {
|
|
120
|
+
import { Aes256Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
121
|
+
import { XWing } from "@hpke/hybridkem-x-wing";
|
|
122
122
|
|
|
123
123
|
async function doHpke() {
|
|
124
124
|
// setup
|
|
125
125
|
const suite = new CipherSuite({
|
|
126
|
-
kem: new
|
|
126
|
+
kem: new XWing(),
|
|
127
127
|
kdf: new HkdfSha256(),
|
|
128
|
-
aead: new
|
|
128
|
+
aead: new Aes256Gcm(),
|
|
129
129
|
});
|
|
130
130
|
|
|
131
131
|
const rkp = await suite.kem.generateKeyPair();
|
|
132
132
|
|
|
133
|
+
// Note that the `ct` (ciphertext) resulting from X-Wing Encapsulate() is set to `sender.enc`.
|
|
133
134
|
const sender = await suite.createSenderContext({
|
|
134
135
|
recipientPublicKey: rkp.publicKey,
|
|
135
136
|
});
|
|
136
137
|
|
|
137
138
|
// encrypt
|
|
138
|
-
const
|
|
139
|
+
const encrypted = await sender.seal(new TextEncoder().encode("Hello world!"));
|
|
139
140
|
|
|
140
141
|
const recipient = await suite.createRecipientContext({
|
|
141
142
|
recipientKey: rkp.privateKey,
|
|
142
|
-
enc: sender.enc,
|
|
143
|
+
enc: sender.enc, // == `ct` (ciphertext) in the context of X-Wing
|
|
143
144
|
});
|
|
144
145
|
|
|
145
146
|
// decrypt
|
|
146
|
-
const pt = await recipient.open(
|
|
147
|
+
const pt = await recipient.open(encrypted);
|
|
147
148
|
|
|
148
149
|
// Hello world!
|
|
149
150
|
console.log(new TextDecoder().decode(pt));
|
|
@@ -159,33 +160,34 @@ try {
|
|
|
159
160
|
### Deno
|
|
160
161
|
|
|
161
162
|
```ts
|
|
162
|
-
import {
|
|
163
|
-
import {
|
|
163
|
+
import { Aes256Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
164
|
+
import { XWing } from "@hpke/hybridkem-x-wing";
|
|
164
165
|
|
|
165
166
|
async function doHpke() {
|
|
166
167
|
// setup
|
|
167
168
|
const suite = new CipherSuite({
|
|
168
|
-
kem: new
|
|
169
|
+
kem: new XWing(),
|
|
169
170
|
kdf: new HkdfSha256(),
|
|
170
|
-
aead: new
|
|
171
|
+
aead: new Aes256Gcm(),
|
|
171
172
|
});
|
|
172
173
|
|
|
173
174
|
const rkp = await suite.kem.generateKeyPair();
|
|
174
175
|
|
|
176
|
+
// Note that the `ct` (ciphertext) resulting from X-Wing::Encapsulate() is set to `sender.enc`.
|
|
175
177
|
const sender = await suite.createSenderContext({
|
|
176
178
|
recipientPublicKey: rkp.publicKey,
|
|
177
179
|
});
|
|
178
180
|
|
|
179
181
|
// encrypt
|
|
180
|
-
const
|
|
182
|
+
const encrypted = await sender.seal(new TextEncoder().encode("Hello world!"));
|
|
181
183
|
|
|
182
184
|
const recipient = await suite.createRecipientContext({
|
|
183
185
|
recipientKey: rkp.privateKey,
|
|
184
|
-
enc: sender.enc,
|
|
186
|
+
enc: sender.enc, // == `ct` (ciphertext) in the context of X-Wing
|
|
185
187
|
});
|
|
186
188
|
|
|
187
189
|
// decrypt
|
|
188
|
-
const pt = await recipient.open(
|
|
190
|
+
const pt = await recipient.open(encrypted);
|
|
189
191
|
|
|
190
192
|
// Hello world!
|
|
191
193
|
console.log(new TextDecoder().decode(pt));
|
|
@@ -206,35 +208,38 @@ try {
|
|
|
206
208
|
<body>
|
|
207
209
|
<script type="module">
|
|
208
210
|
import {
|
|
209
|
-
|
|
211
|
+
Aes256Gcm,
|
|
210
212
|
CipherSuite,
|
|
211
213
|
HkdfSha256,
|
|
212
214
|
} from "https://esm.sh/@hpke/core";
|
|
213
|
-
import {
|
|
215
|
+
import { XWing } from "https://esm.sh/@hpke/hybridkem-x-wing";
|
|
214
216
|
|
|
215
217
|
globalThis.doHpke = async () => {
|
|
216
218
|
try {
|
|
217
219
|
const suite = new CipherSuite({
|
|
218
|
-
kem: new
|
|
220
|
+
kem: new XWing(),
|
|
219
221
|
kdf: new HkdfSha256(),
|
|
220
|
-
aead: new
|
|
222
|
+
aead: new Aes256Gcm(),
|
|
221
223
|
});
|
|
222
224
|
|
|
223
225
|
const rkp = await suite.kem.generateKeyPair();
|
|
224
226
|
|
|
227
|
+
// Note that the `ct` resulting from X-Wing::Encapsulate() is set to `sender.enc`.
|
|
225
228
|
const sender = await suite.createSenderContext({
|
|
226
229
|
recipientPublicKey: rkp.publicKey,
|
|
227
230
|
});
|
|
228
231
|
// encrypt
|
|
229
|
-
const
|
|
232
|
+
const encrypted = await sender.seal(
|
|
233
|
+
new TextEncoder().encode("Hello world!"),
|
|
234
|
+
);
|
|
230
235
|
|
|
231
236
|
const recipient = await suite.createRecipientContext({
|
|
232
237
|
recipientKey: rkp.privateKey, // rkp (CryptoKeyPair) is also acceptable.
|
|
233
|
-
enc: sender.enc,
|
|
238
|
+
enc: sender.enc, // == `ct` (ciphertext) in the context of X-Wing
|
|
234
239
|
});
|
|
235
240
|
|
|
236
241
|
// decrypt
|
|
237
|
-
const pt = await recipient.open(
|
|
242
|
+
const pt = await recipient.open(encrypted);
|
|
238
243
|
|
|
239
244
|
// Hello world!
|
|
240
245
|
alert(new TextDecoder().decode(pt));
|
package/esm/mod.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { XWing } from "./src/xWing.js";
|
|
2
2
|
//# sourceMappingURL=mod.d.ts.map
|
package/esm/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC"}
|
package/esm/mod.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { XWing } from "./src/xWing.js";
|
|
@@ -15,15 +15,15 @@ import { X25519 } from "@hpke/dhkem-x25519";
|
|
|
15
15
|
*
|
|
16
16
|
* ```ts
|
|
17
17
|
* import { Aes128Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
18
|
-
* import {
|
|
18
|
+
* import { XWing } from "@hpke/hybridkem-x-wing";
|
|
19
19
|
* const suite = new CipherSuite({
|
|
20
|
-
* kem: new
|
|
20
|
+
* kem: new XWing(),
|
|
21
21
|
* kdf: new HkdfSha256(),
|
|
22
22
|
* aead: new Aes128Gcm(),
|
|
23
23
|
* });
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
export declare class
|
|
26
|
+
export declare class XWing implements KemInterface {
|
|
27
27
|
readonly id: KemId;
|
|
28
28
|
readonly name: string;
|
|
29
29
|
readonly secretSize: number;
|
|
@@ -63,10 +63,26 @@ export declare class HybridkemXWing implements KemInterface {
|
|
|
63
63
|
*/
|
|
64
64
|
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>;
|
|
65
65
|
importKey(_format: "raw" | "jwk", _key: ArrayBuffer | JsonWebKey, _isPublic?: boolean): Promise<CryptoKey>;
|
|
66
|
+
/**
|
|
67
|
+
* Encapsulates the shared secret and the `ct` (ciphertext) as `enc`.
|
|
68
|
+
* @param params The parameters for encapsulation.
|
|
69
|
+
* @returns {Promise<{ sharedSecret: ArrayBuffer; enc: ArrayBuffer }>} A promise that resolves with the `ss` (shared secret) as `sharedSecret` and the `ct` (ciphertext) as `enc`.
|
|
70
|
+
* @throws {InvalidParamError} Thrown if the length of the `ekm` is not 64 bytes.
|
|
71
|
+
* @throws {EncapError} Thrown if the shared secret cannot be encapsulated.
|
|
72
|
+
*/
|
|
66
73
|
encap(params: SenderContextParams): Promise<{
|
|
67
74
|
sharedSecret: ArrayBuffer;
|
|
68
75
|
enc: ArrayBuffer;
|
|
69
76
|
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Decapsulates the `ss` (shared secret) from the `enc` and the recipient's private key.
|
|
79
|
+
* The `enc` is the same as the `ct` (ciphertext) resulting from `X-Wing::Encapsulate(),
|
|
80
|
+
* which is executed under the `encap()`.
|
|
81
|
+
* @param params The parameters for decapsulation.
|
|
82
|
+
* @returns {Promise<ArrayBuffer>} A promise that resolves with the shared secret.
|
|
83
|
+
* @throws {InvalidParamError} Thrown if the length of the `enc` is not 1120 bytes.
|
|
84
|
+
* @throws {DecapError} Thrown if the shared secret cannot be decapsulated.
|
|
85
|
+
*/
|
|
70
86
|
decap(params: RecipientContextParams): Promise<ArrayBuffer>;
|
|
71
87
|
/**
|
|
72
88
|
* Sets up the MlKemBase instance by loading the necessary crypto library.
|
|
@@ -91,4 +107,4 @@ export declare class HybridkemXWing implements KemInterface {
|
|
|
91
107
|
private _serializePrivateKey;
|
|
92
108
|
private _deserializePrivateKey;
|
|
93
109
|
}
|
|
94
|
-
//# sourceMappingURL=
|
|
110
|
+
//# sourceMappingURL=xWing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xWing.d.ts","sourceRoot":"","sources":["../../src/src/xWing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAQL,KAAK,EAKN,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAc,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAwCxD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,KAAM,YAAW,YAAY;IACxC,SAAgB,EAAE,EAAE,KAAK,CAAe;IACxC,SAAgB,IAAI,EAAE,MAAM,CAAY;IACxC,SAAgB,UAAU,EAAE,MAAM,CAAM;IACxC,SAAgB,OAAO,EAAE,MAAM,CAAQ;IACvC,SAAgB,aAAa,EAAE,MAAM,CAAQ;IAC7C,SAAgB,cAAc,EAAE,MAAM,CAAM;IAC5C,SAAgB,IAAI,EAAE,OAAO,CAAS;IACtC,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC;IACvB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAiC;;IAOhC,kBAAkB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASxD,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IAS1D,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASzD,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IASxE;;;;OAIG;IACU,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC;IAkBtD;;;;;;OAMG;IACU,qBAAqB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAc1E;;;;;;;OAOG;IACU,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAevD,SAAS,CACpB,OAAO,EAAE,KAAK,GAAG,KAAK,EACtB,IAAI,EAAE,WAAW,GAAG,UAAU,EAC9B,SAAS,UAAO,GACf,OAAO,CAAC,SAAS,CAAC;IAcrB;;;;;;OAMG;IACU,KAAK,CAChB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC;QAAE,YAAY,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC;IA4C3D;;;;;;;;OAQG;IACU,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC;IAyBxE;;;;OAIG;YACW,MAAM;IAOpB;;;;OAIG;YACW,sBAAsB;IAOpC;;;;OAIG;YACW,uBAAuB;IAUrC,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,sBAAsB;CAU/B"}
|
|
@@ -15,7 +15,7 @@ const X25519_BASE = new Uint8Array([
|
|
|
15
15
|
// "/^\",
|
|
16
16
|
// );
|
|
17
17
|
// deno-fmt-ignore
|
|
18
|
-
const XWING_LABEL = new Uint8Array([46, 47, 47, 94, 92]);
|
|
18
|
+
const XWING_LABEL = new Uint8Array([92, 46, 47, 47, 94, 92]);
|
|
19
19
|
function emitNotSupported() {
|
|
20
20
|
return new Promise((_resolve, reject) => {
|
|
21
21
|
reject(new NotSupportedError("Not supported"));
|
|
@@ -43,21 +43,21 @@ function combiner(ssM, ssX, ctX, pkX) {
|
|
|
43
43
|
*
|
|
44
44
|
* ```ts
|
|
45
45
|
* import { Aes128Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
46
|
-
* import {
|
|
46
|
+
* import { XWing } from "@hpke/hybridkem-x-wing";
|
|
47
47
|
* const suite = new CipherSuite({
|
|
48
|
-
* kem: new
|
|
48
|
+
* kem: new XWing(),
|
|
49
49
|
* kdf: new HkdfSha256(),
|
|
50
50
|
* aead: new Aes128Gcm(),
|
|
51
51
|
* });
|
|
52
52
|
* ```
|
|
53
53
|
*/
|
|
54
|
-
export class
|
|
54
|
+
export class XWing {
|
|
55
55
|
constructor() {
|
|
56
56
|
Object.defineProperty(this, "id", {
|
|
57
57
|
enumerable: true,
|
|
58
58
|
configurable: true,
|
|
59
59
|
writable: true,
|
|
60
|
-
value: KemId.
|
|
60
|
+
value: KemId.XWing
|
|
61
61
|
});
|
|
62
62
|
Object.defineProperty(this, "name", {
|
|
63
63
|
enumerable: true,
|
|
@@ -233,6 +233,13 @@ export class HybridkemXWing {
|
|
|
233
233
|
// }
|
|
234
234
|
// return await this.deserializePrivateKey(key as ArrayBuffer);
|
|
235
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Encapsulates the shared secret and the `ct` (ciphertext) as `enc`.
|
|
238
|
+
* @param params The parameters for encapsulation.
|
|
239
|
+
* @returns {Promise<{ sharedSecret: ArrayBuffer; enc: ArrayBuffer }>} A promise that resolves with the `ss` (shared secret) as `sharedSecret` and the `ct` (ciphertext) as `enc`.
|
|
240
|
+
* @throws {InvalidParamError} Thrown if the length of the `ekm` is not 64 bytes.
|
|
241
|
+
* @throws {EncapError} Thrown if the shared secret cannot be encapsulated.
|
|
242
|
+
*/
|
|
236
243
|
async encap(params) {
|
|
237
244
|
let ekm = undefined;
|
|
238
245
|
if (params.ekm !== undefined && !isCryptoKeyPair(params.ekm)) {
|
|
@@ -277,6 +284,15 @@ export class HybridkemXWing {
|
|
|
277
284
|
throw new EncapError(e);
|
|
278
285
|
}
|
|
279
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Decapsulates the `ss` (shared secret) from the `enc` and the recipient's private key.
|
|
289
|
+
* The `enc` is the same as the `ct` (ciphertext) resulting from `X-Wing::Encapsulate(),
|
|
290
|
+
* which is executed under the `encap()`.
|
|
291
|
+
* @param params The parameters for decapsulation.
|
|
292
|
+
* @returns {Promise<ArrayBuffer>} A promise that resolves with the shared secret.
|
|
293
|
+
* @throws {InvalidParamError} Thrown if the length of the `enc` is not 1120 bytes.
|
|
294
|
+
* @throws {DecapError} Thrown if the shared secret cannot be decapsulated.
|
|
295
|
+
*/
|
|
280
296
|
async decap(params) {
|
|
281
297
|
const rSk = isCryptoKeyPair(params.recipientKey)
|
|
282
298
|
? params.recipientKey.privateKey
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testVectors.d.ts","sourceRoot":"","sources":["../../src/test/testVectors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"testVectors.d.ts","sourceRoot":"","sources":["../../src/test/testVectors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,UAAU,CAkC1C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hpke/hybridkem-x-wing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A Hybrid Public Key Encryption (HPKE) module extension for X-Wing: general-purpose hybrid post-quantum KEM.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hpke",
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"node": ">=16.0.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@hpke/common": "^1.
|
|
45
|
-
"@hpke/dhkem-x25519": "^1.
|
|
44
|
+
"@hpke/common": "^1.6.1",
|
|
45
|
+
"@hpke/dhkem-x25519": "^1.6.0",
|
|
46
46
|
"@noble/hashes": "^1.5.0",
|
|
47
|
-
"mlkem": "^2.
|
|
47
|
+
"mlkem": "^2.3.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^20.9.0",
|
|
51
51
|
"picocolors": "^1.0.0",
|
|
52
|
-
"@hpke/core": "^1.
|
|
52
|
+
"@hpke/core": "^1.6.0",
|
|
53
53
|
"@deno/shim-deno": "~0.18.0"
|
|
54
54
|
},
|
|
55
55
|
"_generatedBy": "dnt@dev"
|
package/script/mod.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { XWing } from "./src/xWing.js";
|
|
2
2
|
//# sourceMappingURL=mod.d.ts.map
|
package/script/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC"}
|
package/script/mod.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
if (v !== undefined) module.exports = v;
|
|
5
5
|
}
|
|
6
6
|
else if (typeof define === "function" && define.amd) {
|
|
7
|
-
define(["require", "exports", "./src/
|
|
7
|
+
define(["require", "exports", "./src/xWing.js"], factory);
|
|
8
8
|
}
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
13
|
-
var
|
|
14
|
-
Object.defineProperty(exports, "
|
|
12
|
+
exports.XWing = void 0;
|
|
13
|
+
var xWing_js_1 = require("./src/xWing.js");
|
|
14
|
+
Object.defineProperty(exports, "XWing", { enumerable: true, get: function () { return xWing_js_1.XWing; } });
|
|
15
15
|
});
|
|
@@ -15,15 +15,15 @@ import { X25519 } from "@hpke/dhkem-x25519";
|
|
|
15
15
|
*
|
|
16
16
|
* ```ts
|
|
17
17
|
* import { Aes128Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
18
|
-
* import {
|
|
18
|
+
* import { XWing } from "@hpke/hybridkem-x-wing";
|
|
19
19
|
* const suite = new CipherSuite({
|
|
20
|
-
* kem: new
|
|
20
|
+
* kem: new XWing(),
|
|
21
21
|
* kdf: new HkdfSha256(),
|
|
22
22
|
* aead: new Aes128Gcm(),
|
|
23
23
|
* });
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
export declare class
|
|
26
|
+
export declare class XWing implements KemInterface {
|
|
27
27
|
readonly id: KemId;
|
|
28
28
|
readonly name: string;
|
|
29
29
|
readonly secretSize: number;
|
|
@@ -63,10 +63,26 @@ export declare class HybridkemXWing implements KemInterface {
|
|
|
63
63
|
*/
|
|
64
64
|
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>;
|
|
65
65
|
importKey(_format: "raw" | "jwk", _key: ArrayBuffer | JsonWebKey, _isPublic?: boolean): Promise<CryptoKey>;
|
|
66
|
+
/**
|
|
67
|
+
* Encapsulates the shared secret and the `ct` (ciphertext) as `enc`.
|
|
68
|
+
* @param params The parameters for encapsulation.
|
|
69
|
+
* @returns {Promise<{ sharedSecret: ArrayBuffer; enc: ArrayBuffer }>} A promise that resolves with the `ss` (shared secret) as `sharedSecret` and the `ct` (ciphertext) as `enc`.
|
|
70
|
+
* @throws {InvalidParamError} Thrown if the length of the `ekm` is not 64 bytes.
|
|
71
|
+
* @throws {EncapError} Thrown if the shared secret cannot be encapsulated.
|
|
72
|
+
*/
|
|
66
73
|
encap(params: SenderContextParams): Promise<{
|
|
67
74
|
sharedSecret: ArrayBuffer;
|
|
68
75
|
enc: ArrayBuffer;
|
|
69
76
|
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Decapsulates the `ss` (shared secret) from the `enc` and the recipient's private key.
|
|
79
|
+
* The `enc` is the same as the `ct` (ciphertext) resulting from `X-Wing::Encapsulate(),
|
|
80
|
+
* which is executed under the `encap()`.
|
|
81
|
+
* @param params The parameters for decapsulation.
|
|
82
|
+
* @returns {Promise<ArrayBuffer>} A promise that resolves with the shared secret.
|
|
83
|
+
* @throws {InvalidParamError} Thrown if the length of the `enc` is not 1120 bytes.
|
|
84
|
+
* @throws {DecapError} Thrown if the shared secret cannot be decapsulated.
|
|
85
|
+
*/
|
|
70
86
|
decap(params: RecipientContextParams): Promise<ArrayBuffer>;
|
|
71
87
|
/**
|
|
72
88
|
* Sets up the MlKemBase instance by loading the necessary crypto library.
|
|
@@ -91,4 +107,4 @@ export declare class HybridkemXWing implements KemInterface {
|
|
|
91
107
|
private _serializePrivateKey;
|
|
92
108
|
private _deserializePrivateKey;
|
|
93
109
|
}
|
|
94
|
-
//# sourceMappingURL=
|
|
110
|
+
//# sourceMappingURL=xWing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xWing.d.ts","sourceRoot":"","sources":["../../src/src/xWing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAQL,KAAK,EAKN,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAc,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAwCxD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,KAAM,YAAW,YAAY;IACxC,SAAgB,EAAE,EAAE,KAAK,CAAe;IACxC,SAAgB,IAAI,EAAE,MAAM,CAAY;IACxC,SAAgB,UAAU,EAAE,MAAM,CAAM;IACxC,SAAgB,OAAO,EAAE,MAAM,CAAQ;IACvC,SAAgB,aAAa,EAAE,MAAM,CAAQ;IAC7C,SAAgB,cAAc,EAAE,MAAM,CAAM;IAC5C,SAAgB,IAAI,EAAE,OAAO,CAAS;IACtC,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC;IACvB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAiC;;IAOhC,kBAAkB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASxD,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IAS1D,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASzD,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IASxE;;;;OAIG;IACU,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC;IAkBtD;;;;;;OAMG;IACU,qBAAqB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAc1E;;;;;;;OAOG;IACU,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAevD,SAAS,CACpB,OAAO,EAAE,KAAK,GAAG,KAAK,EACtB,IAAI,EAAE,WAAW,GAAG,UAAU,EAC9B,SAAS,UAAO,GACf,OAAO,CAAC,SAAS,CAAC;IAcrB;;;;;;OAMG;IACU,KAAK,CAChB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC;QAAE,YAAY,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC;IA4C3D;;;;;;;;OAQG;IACU,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC;IAyBxE;;;;OAIG;YACW,MAAM;IAOpB;;;;OAIG;YACW,sBAAsB;IAOpC;;;;OAIG;YACW,uBAAuB;IAUrC,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,sBAAsB;CAU/B"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.XWing = void 0;
|
|
13
13
|
const sha3_1 = require("@noble/hashes/sha3");
|
|
14
14
|
// @ts-ignore: Unreachable code error
|
|
15
15
|
const mlkem_1 = require("mlkem");
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
// "/^\",
|
|
28
28
|
// );
|
|
29
29
|
// deno-fmt-ignore
|
|
30
|
-
const XWING_LABEL = new Uint8Array([46, 47, 47, 94, 92]);
|
|
30
|
+
const XWING_LABEL = new Uint8Array([92, 46, 47, 47, 94, 92]);
|
|
31
31
|
function emitNotSupported() {
|
|
32
32
|
return new Promise((_resolve, reject) => {
|
|
33
33
|
reject(new common_1.NotSupportedError("Not supported"));
|
|
@@ -55,21 +55,21 @@
|
|
|
55
55
|
*
|
|
56
56
|
* ```ts
|
|
57
57
|
* import { Aes128Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
58
|
-
* import {
|
|
58
|
+
* import { XWing } from "@hpke/hybridkem-x-wing";
|
|
59
59
|
* const suite = new CipherSuite({
|
|
60
|
-
* kem: new
|
|
60
|
+
* kem: new XWing(),
|
|
61
61
|
* kdf: new HkdfSha256(),
|
|
62
62
|
* aead: new Aes128Gcm(),
|
|
63
63
|
* });
|
|
64
64
|
* ```
|
|
65
65
|
*/
|
|
66
|
-
class
|
|
66
|
+
class XWing {
|
|
67
67
|
constructor() {
|
|
68
68
|
Object.defineProperty(this, "id", {
|
|
69
69
|
enumerable: true,
|
|
70
70
|
configurable: true,
|
|
71
71
|
writable: true,
|
|
72
|
-
value: common_1.KemId.
|
|
72
|
+
value: common_1.KemId.XWing
|
|
73
73
|
});
|
|
74
74
|
Object.defineProperty(this, "name", {
|
|
75
75
|
enumerable: true,
|
|
@@ -245,6 +245,13 @@
|
|
|
245
245
|
// }
|
|
246
246
|
// return await this.deserializePrivateKey(key as ArrayBuffer);
|
|
247
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Encapsulates the shared secret and the `ct` (ciphertext) as `enc`.
|
|
250
|
+
* @param params The parameters for encapsulation.
|
|
251
|
+
* @returns {Promise<{ sharedSecret: ArrayBuffer; enc: ArrayBuffer }>} A promise that resolves with the `ss` (shared secret) as `sharedSecret` and the `ct` (ciphertext) as `enc`.
|
|
252
|
+
* @throws {InvalidParamError} Thrown if the length of the `ekm` is not 64 bytes.
|
|
253
|
+
* @throws {EncapError} Thrown if the shared secret cannot be encapsulated.
|
|
254
|
+
*/
|
|
248
255
|
async encap(params) {
|
|
249
256
|
let ekm = undefined;
|
|
250
257
|
if (params.ekm !== undefined && !(0, common_1.isCryptoKeyPair)(params.ekm)) {
|
|
@@ -289,6 +296,15 @@
|
|
|
289
296
|
throw new common_1.EncapError(e);
|
|
290
297
|
}
|
|
291
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* Decapsulates the `ss` (shared secret) from the `enc` and the recipient's private key.
|
|
301
|
+
* The `enc` is the same as the `ct` (ciphertext) resulting from `X-Wing::Encapsulate(),
|
|
302
|
+
* which is executed under the `encap()`.
|
|
303
|
+
* @param params The parameters for decapsulation.
|
|
304
|
+
* @returns {Promise<ArrayBuffer>} A promise that resolves with the shared secret.
|
|
305
|
+
* @throws {InvalidParamError} Thrown if the length of the `enc` is not 1120 bytes.
|
|
306
|
+
* @throws {DecapError} Thrown if the shared secret cannot be decapsulated.
|
|
307
|
+
*/
|
|
292
308
|
async decap(params) {
|
|
293
309
|
const rSk = (0, common_1.isCryptoKeyPair)(params.recipientKey)
|
|
294
310
|
? params.recipientKey.privateKey
|
|
@@ -391,5 +407,5 @@
|
|
|
391
407
|
});
|
|
392
408
|
}
|
|
393
409
|
}
|
|
394
|
-
exports.
|
|
410
|
+
exports.XWing = XWing;
|
|
395
411
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testVectors.d.ts","sourceRoot":"","sources":["../../src/test/testVectors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"testVectors.d.ts","sourceRoot":"","sources":["../../src/test/testVectors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,UAAU,CAkC1C,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hybridkemXWing.d.ts","sourceRoot":"","sources":["../../src/src/hybridkemXWing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAQL,KAAK,EAKN,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAc,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAwCxD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,cAAe,YAAW,YAAY;IACjD,SAAgB,EAAE,EAAE,KAAK,CAAwB;IACjD,SAAgB,IAAI,EAAE,MAAM,CAAY;IACxC,SAAgB,UAAU,EAAE,MAAM,CAAM;IACxC,SAAgB,OAAO,EAAE,MAAM,CAAQ;IACvC,SAAgB,aAAa,EAAE,MAAM,CAAQ;IAC7C,SAAgB,cAAc,EAAE,MAAM,CAAM;IAC5C,SAAgB,IAAI,EAAE,OAAO,CAAS;IACtC,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC;IACvB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAiC;;IAOhC,kBAAkB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASxD,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IAS1D,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASzD,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IASxE;;;;OAIG;IACU,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC;IAkBtD;;;;;;OAMG;IACU,qBAAqB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAc1E;;;;;;;OAOG;IACU,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAevD,SAAS,CACpB,OAAO,EAAE,KAAK,GAAG,KAAK,EACtB,IAAI,EAAE,WAAW,GAAG,UAAU,EAC9B,SAAS,UAAO,GACf,OAAO,CAAC,SAAS,CAAC;IAcR,KAAK,CAChB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC;QAAE,YAAY,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC;IA4C9C,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC;IAyBxE;;;;OAIG;YACW,MAAM;IAOpB;;;;OAIG;YACW,sBAAsB;IAOpC;;;;OAIG;YACW,uBAAuB;IAUrC,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,sBAAsB;CAU/B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hybridkemXWing.d.ts","sourceRoot":"","sources":["../../src/src/hybridkemXWing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAQL,KAAK,EAKN,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAc,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAwCxD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,cAAe,YAAW,YAAY;IACjD,SAAgB,EAAE,EAAE,KAAK,CAAwB;IACjD,SAAgB,IAAI,EAAE,MAAM,CAAY;IACxC,SAAgB,UAAU,EAAE,MAAM,CAAM;IACxC,SAAgB,OAAO,EAAE,MAAM,CAAQ;IACvC,SAAgB,aAAa,EAAE,MAAM,CAAQ;IAC7C,SAAgB,cAAc,EAAE,MAAM,CAAM;IAC5C,SAAgB,IAAI,EAAE,OAAO,CAAS;IACtC,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC;IACvB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAiC;;IAOhC,kBAAkB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASxD,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IAS1D,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASzD,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IASxE;;;;OAIG;IACU,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC;IAkBtD;;;;;;OAMG;IACU,qBAAqB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAc1E;;;;;;;OAOG;IACU,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAevD,SAAS,CACpB,OAAO,EAAE,KAAK,GAAG,KAAK,EACtB,IAAI,EAAE,WAAW,GAAG,UAAU,EAC9B,SAAS,UAAO,GACf,OAAO,CAAC,SAAS,CAAC;IAcR,KAAK,CAChB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC;QAAE,YAAY,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC;IA4C9C,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC;IAyBxE;;;;OAIG;YACW,MAAM;IAOpB;;;;OAIG;YACW,sBAAsB;IAOpC;;;;OAIG;YACW,uBAAuB;IAUrC,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,sBAAsB;CAU/B"}
|