neozip-blockchain 1.0.5 → 1.5.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.
Files changed (62) hide show
  1. package/README.md +2 -1
  2. package/WHATS_NEW.md +26 -0
  3. package/dist/encryption/AccessMetadata.d.ts +24 -0
  4. package/dist/encryption/AccessMetadata.d.ts.map +1 -0
  5. package/dist/encryption/AccessMetadata.js +71 -0
  6. package/dist/encryption/AccessMetadata.js.map +1 -0
  7. package/dist/encryption/KeyWrapper.d.ts +40 -0
  8. package/dist/encryption/KeyWrapper.d.ts.map +1 -0
  9. package/dist/encryption/KeyWrapper.js +129 -0
  10. package/dist/encryption/KeyWrapper.js.map +1 -0
  11. package/dist/encryption/KeyWrapperX25519.d.ts +43 -0
  12. package/dist/encryption/KeyWrapperX25519.d.ts.map +1 -0
  13. package/dist/encryption/KeyWrapperX25519.js +136 -0
  14. package/dist/encryption/KeyWrapperX25519.js.map +1 -0
  15. package/dist/encryption/RecipientEncryption.d.ts +60 -0
  16. package/dist/encryption/RecipientEncryption.d.ts.map +1 -0
  17. package/dist/encryption/RecipientEncryption.js +237 -0
  18. package/dist/encryption/RecipientEncryption.js.map +1 -0
  19. package/dist/encryption/index.d.ts +6 -0
  20. package/dist/encryption/index.d.ts.map +1 -0
  21. package/dist/encryption/index.js +23 -0
  22. package/dist/encryption/index.js.map +1 -0
  23. package/dist/encryption/types.d.ts +60 -0
  24. package/dist/encryption/types.d.ts.map +1 -0
  25. package/dist/encryption/types.js +6 -0
  26. package/dist/encryption/types.js.map +1 -0
  27. package/dist/identity/ENSResolver.d.ts +30 -0
  28. package/dist/identity/ENSResolver.d.ts.map +1 -0
  29. package/dist/identity/ENSResolver.js +85 -0
  30. package/dist/identity/ENSResolver.js.map +1 -0
  31. package/dist/identity/IdentityResolverDispatch.d.ts +35 -0
  32. package/dist/identity/IdentityResolverDispatch.d.ts.map +1 -0
  33. package/dist/identity/IdentityResolverDispatch.js +55 -0
  34. package/dist/identity/IdentityResolverDispatch.js.map +1 -0
  35. package/dist/identity/LitPkpResolver.d.ts +17 -0
  36. package/dist/identity/LitPkpResolver.d.ts.map +1 -0
  37. package/dist/identity/LitPkpResolver.js +44 -0
  38. package/dist/identity/LitPkpResolver.js.map +1 -0
  39. package/dist/identity/index.d.ts +6 -0
  40. package/dist/identity/index.d.ts.map +1 -0
  41. package/dist/identity/index.js +18 -0
  42. package/dist/identity/index.js.map +1 -0
  43. package/dist/identity/types.d.ts +38 -0
  44. package/dist/identity/types.d.ts.map +1 -0
  45. package/dist/identity/types.js +13 -0
  46. package/dist/identity/types.js.map +1 -0
  47. package/dist/index.d.ts +1 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +2 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/version.d.ts +3 -0
  52. package/dist/version.d.ts.map +1 -0
  53. package/dist/version.js +6 -0
  54. package/dist/version.js.map +1 -0
  55. package/docs/CONTRACT_CODE_VERIFICATION_DESIGN.md +525 -0
  56. package/docs/ENCRYPTION.md +213 -0
  57. package/docs/MIGRATION.md +175 -0
  58. package/docs/RATE_LIMITING_DESIGN.md +290 -0
  59. package/docs/TOKEN_SERVICE_API_UPDATE_PLAN.md +712 -0
  60. package/docs/security-hardening-plan.html +398 -0
  61. package/docs/security-hardening-plan.md +316 -0
  62. package/package.json +24 -5
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Blockchain functionality for NeoZip: **NeoZip Token Service timestamping** (stamp, upgrade, mint, verify), NFT minting, verification, and wallet management. Part of the [neozipkit monorepo](../../README.md).
4
4
 
5
- > **Stable 1.0:** This package **1.0.5** (first non-beta was **1.0.2**). Format profile: [NEOZIP_APPNOTE.md](../neozipkit/NEOZIP_APPNOTE.md). See [WHATS_NEW.md](WHATS_NEW.md).
5
+ > **Stable 1.5:** This package **1.5.0** (identity-based encryption; pairs with `neozipkit@1.5.0`). Format profile: [NEOZIP_APPNOTE.md](../neozipkit/NEOZIP_APPNOTE.md). See [WHATS_NEW.md](WHATS_NEW.md).
6
6
 
7
7
  See [WHATS_NEW.md](WHATS_NEW.md) for release notes.
8
8
 
@@ -16,6 +16,7 @@ This package provides the client-side API and utilities that work with the sibli
16
16
  - **Wallet Management**: Browser and Node.js wallet integrations
17
17
  - **Multi-Network Support**: Base Mainnet, Base Sepolia, and more
18
18
  - **Examples**: Runnable scripts for stamp, upgrade, mint, verify, and token-create flows (see [`examples/README.md`](examples/README.md), `examples/`, and `package.json` `example:*` scripts)
19
+ - **Identity encryption**: Encrypt `.nzip` archives for ENS / address / Lit PKP recipients (`neozip-blockchain/encryption` + `neozip-blockchain/identity`). See [docs/ENCRYPTION.md](docs/ENCRYPTION.md).
19
20
 
20
21
  ## Installation
21
22
 
package/WHATS_NEW.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  Release notes for people who install and use **`neozip-blockchain`** from npm (alongside [`neozipkit`](https://www.npmjs.com/package/neozipkit)).
4
4
 
5
+ ## 1.5.0 (2026-10-25)
6
+
7
+ Released with sibling **`neozipkit@1.5.0`** (Zip64, Extra Field `0x014F`, browser/buffer zstd, `forceZip64`).
8
+
9
+ ### Identity-based (recipient) encryption
10
+
11
+ Moved from the former private `@neowareinc/neozipkit-pro` package into this library:
12
+
13
+ - **`neozip-blockchain/encryption`** — ECIES key wrapping (secp256k1 / X25519 + AES-256-GCM), `META-INF/ACCESS.NZIP`, `encryptForRecipients` / `decryptAsRecipient`
14
+ - **`neozip-blockchain/identity`** — ENS / address / Lit PKP resolvers for recipient public keys
15
+
16
+ Inner ZIP entry encryption still uses **neozipkit** NeoEncrypt (`neo-aes256`) by default. See [docs/ENCRYPTION.md](docs/ENCRYPTION.md).
17
+
18
+ HKDF domain-separation strings are unchanged (`neozipkit-pro/ecies/v1`, …) so existing recipient-encrypted archives remain decryptable.
19
+
20
+ ```bash
21
+ npm install neozipkit@^1.5.0 neozip-blockchain@^1.5.0
22
+ ```
23
+
24
+ ```typescript
25
+ import { encryptForRecipients } from 'neozip-blockchain/encryption';
26
+ import { ENSResolver } from 'neozip-blockchain/identity';
27
+ ```
28
+
29
+ ---
30
+
5
31
  ## 1.0.5 (2026-08-14)
6
32
 
7
33
  ### Token Service network profiles (Base Sepolia + Base Mainnet)
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Serialize and parse META-INF/ACCESS.NZIP — the JSON envelope that stores
3
+ * ECIES-wrapped AES passwords and recipient identity information.
4
+ */
5
+ import { type ResolvedIdentity } from '../identity/types';
6
+ import type { AccessControlMetadata, WrappedKeyResult } from './types';
7
+ /** Well-known path inside a .nzip archive for recipient access control. */
8
+ export declare const ACCESS_NZIP_PATH = "META-INF/ACCESS.NZIP";
9
+ /**
10
+ * Build an AccessControlMetadata object from resolved identities and their
11
+ * individually wrapped keys.
12
+ */
13
+ export declare function buildAccessMetadata(recipients: Array<{
14
+ resolved: ResolvedIdentity;
15
+ wrapped: WrappedKeyResult;
16
+ }>, scheme?: AccessControlMetadata['scheme'], innerZipEncryption?: 'neo-aes256' | 'aes256'): AccessControlMetadata;
17
+ /** Serialize metadata to a UTF-8 buffer suitable for writing as a ZIP entry. */
18
+ export declare function serializeAccessMetadata(metadata: AccessControlMetadata): Buffer;
19
+ /**
20
+ * Parse a raw buffer (extracted from META-INF/ACCESS.NZIP) back into typed metadata.
21
+ * Throws on malformed JSON or missing required fields.
22
+ */
23
+ export declare function parseAccessMetadata(raw: Buffer | string): AccessControlMetadata;
24
+ //# sourceMappingURL=AccessMetadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccessMetadata.d.ts","sourceRoot":"","sources":["../../src/encryption/AccessMetadata.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EACV,qBAAqB,EAErB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAEjB,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC,EAC5E,MAAM,GAAE,qBAAqB,CAAC,QAAQ,CAAgB,EACtD,kBAAkB,GAAE,YAAY,GAAG,QAAuB,GACzD,qBAAqB,CAgCvB;AAED,gFAAgF;AAChF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,qBAAqB,CAsB/E"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /**
3
+ * Serialize and parse META-INF/ACCESS.NZIP — the JSON envelope that stores
4
+ * ECIES-wrapped AES passwords and recipient identity information.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ACCESS_NZIP_PATH = void 0;
8
+ exports.buildAccessMetadata = buildAccessMetadata;
9
+ exports.serializeAccessMetadata = serializeAccessMetadata;
10
+ exports.parseAccessMetadata = parseAccessMetadata;
11
+ const version_1 = require("../version");
12
+ const types_1 = require("../identity/types");
13
+ /** Well-known path inside a .nzip archive for recipient access control. */
14
+ exports.ACCESS_NZIP_PATH = 'META-INF/ACCESS.NZIP';
15
+ /**
16
+ * Build an AccessControlMetadata object from resolved identities and their
17
+ * individually wrapped keys.
18
+ */
19
+ function buildAccessMetadata(recipients, scheme = 'ens-hybrid', innerZipEncryption = 'neo-aes256') {
20
+ const encryptionInner = innerZipEncryption === 'aes256'
21
+ ? {
22
+ method: 'aes-256-winzip',
23
+ note: 'AES key derived via PBKDF2 from wrapped password (neozipkit AE-1)',
24
+ }
25
+ : {
26
+ method: 'neo-aes256',
27
+ note: 'NeoEncrypt (NEO extra 0x024E); AES-256 via PBKDF2 from wrapped password (neozipkit)',
28
+ };
29
+ const wrappedRecipients = recipients.map(({ resolved, wrapped }) => ({
30
+ identity: resolved.identity,
31
+ identityType: resolved.identityType,
32
+ resolvedAddress: resolved.address,
33
+ publicKeyHex: resolved.publicKeyHex,
34
+ wrappedKey: wrapped.ciphertext,
35
+ ephemeralPublicKey: wrapped.ephemeralPublicKey,
36
+ keyAlgorithm: wrapped.keyAlgorithm,
37
+ }));
38
+ return {
39
+ version: '1.0',
40
+ scheme,
41
+ recipients: wrappedRecipients,
42
+ encryption: encryptionInner,
43
+ created: new Date().toISOString(),
44
+ proVersion: version_1.VERSION,
45
+ };
46
+ }
47
+ /** Serialize metadata to a UTF-8 buffer suitable for writing as a ZIP entry. */
48
+ function serializeAccessMetadata(metadata) {
49
+ return Buffer.from(JSON.stringify(metadata, null, 2), 'utf8');
50
+ }
51
+ /**
52
+ * Parse a raw buffer (extracted from META-INF/ACCESS.NZIP) back into typed metadata.
53
+ * Throws on malformed JSON or missing required fields.
54
+ */
55
+ function parseAccessMetadata(raw) {
56
+ const text = typeof raw === 'string' ? raw : raw.toString('utf8');
57
+ const parsed = JSON.parse(text);
58
+ if (!parsed.version || !parsed.scheme || !Array.isArray(parsed.recipients)) {
59
+ throw new Error('Invalid ACCESS.NZIP: missing version, scheme, or recipients');
60
+ }
61
+ for (const r of parsed.recipients) {
62
+ if (!r.identityType || !(0, types_1.isIdentityType)(r.identityType)) {
63
+ throw new Error(`Invalid ACCESS.NZIP recipient "${r.identity ?? '?'}": unknown or missing identityType`);
64
+ }
65
+ if (!r.wrappedKey || !r.ephemeralPublicKey || !r.keyAlgorithm) {
66
+ throw new Error(`Invalid ACCESS.NZIP recipient "${r.identity}": missing wrappedKey, ephemeralPublicKey, or keyAlgorithm`);
67
+ }
68
+ }
69
+ return parsed;
70
+ }
71
+ //# sourceMappingURL=AccessMetadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccessMetadata.js","sourceRoot":"","sources":["../../src/encryption/AccessMetadata.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAiBH,kDAoCC;AAGD,0DAIC;AAMD,kDAsBC;AAtFD,wCAAqC;AACrC,6CAA0E;AAO1E,2EAA2E;AAC9D,QAAA,gBAAgB,GAAG,sBAAsB,CAAC;AAEvD;;;GAGG;AACH,SAAgB,mBAAmB,CACjC,UAA4E,EAC5E,SAA0C,YAAY,EACtD,qBAA8C,YAAY;IAE1D,MAAM,eAAe,GACnB,kBAAkB,KAAK,QAAQ;QAC7B,CAAC,CAAC;YACE,MAAM,EAAE,gBAAyB;YACjC,IAAI,EAAE,mEAAmE;SAC1E;QACH,CAAC,CAAC;YACE,MAAM,EAAE,YAAqB;YAC7B,IAAI,EAAE,qFAAqF;SAC5F,CAAC;IAER,MAAM,iBAAiB,GAAuB,UAAU,CAAC,GAAG,CAC1D,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,eAAe,EAAE,QAAQ,CAAC,OAAO;QACjC,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CACH,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM;QACN,UAAU,EAAE,iBAAiB;QAC7B,UAAU,EAAE,eAAe;QAC3B,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACjC,UAAU,EAAE,iBAAO;KACpB,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,SAAgB,uBAAuB,CACrC,QAA+B;IAE/B,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,GAAoB;IACtD,MAAM,IAAI,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA0B,CAAC;IAEzD,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,IAAA,sBAAc,EAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CACb,kCAAkC,CAAC,CAAC,QAAQ,IAAI,GAAG,oCAAoC,CACxF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CACb,kCAAkC,CAAC,CAAC,QAAQ,4DAA4D,CACzG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ECIES key wrapping using secp256k1.
3
+ *
4
+ * Encrypt:
5
+ * 1. Generate ephemeral secp256k1 key pair
6
+ * 2. ECDH(ephemeral private, recipient public) → shared secret
7
+ * 3. HKDF-SHA256(shared secret) → 32-byte wrapping key
8
+ * 4. AES-256-GCM encrypt plaintext with wrapping key
9
+ *
10
+ * Decrypt:
11
+ * 1. ECDH(recipient private, ephemeral public) → same shared secret
12
+ * 2. HKDF-SHA256(shared secret) → same wrapping key
13
+ * 3. AES-256-GCM decrypt ciphertext
14
+ */
15
+ import type { WrappedKeyResult } from './types';
16
+ export declare const KEY_ALGORITHM_SECP256K1 = "ecies-secp256k1-aes256gcm";
17
+ /** @deprecated Use KEY_ALGORITHM_SECP256K1 */
18
+ export declare const KEY_ALGORITHM = "ecies-secp256k1-aes256gcm";
19
+ /**
20
+ * Wrap (encrypt) plaintext so only the holder of `recipientPubKeyHex` can unwrap it.
21
+ *
22
+ * @param recipientPubKeyHex Uncompressed secp256k1 public key ("04…", 130 hex chars).
23
+ * @param plaintext The secret to protect (typically a hex-encoded AES password).
24
+ */
25
+ export declare function wrapKey(recipientPubKeyHex: string, plaintext: Buffer): WrappedKeyResult;
26
+ /**
27
+ * Unwrap (decrypt) ciphertext using the recipient's private key.
28
+ *
29
+ * @param recipientPrivKeyHex Recipient's secp256k1 private key (hex, 64 chars).
30
+ * @param ciphertextB64 Base64 string produced by `wrapKey`.
31
+ * @param ephemeralPubKeyHex Ephemeral public key from `wrapKey` result.
32
+ * @returns The original plaintext buffer.
33
+ */
34
+ export declare function unwrapKey(recipientPrivKeyHex: string, ciphertextB64: string, ephemeralPubKeyHex: string): Buffer;
35
+ /**
36
+ * Derive the public key (uncompressed, hex) from a private key. Useful for
37
+ * matching a recipient entry in ACCESS.NZIP without knowing the identity string.
38
+ */
39
+ export declare function publicKeyFromPrivate(privKeyHex: string): string;
40
+ //# sourceMappingURL=KeyWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyWrapper.d.ts","sourceRoot":"","sources":["../../src/encryption/KeyWrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AACnE,8CAA8C;AAC9C,eAAO,MAAM,aAAa,8BAA0B,CAAC;AAYrD;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,GAChB,gBAAgB,CAsBlB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,mBAAmB,EAAE,MAAM,EAC3B,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GACzB,MAAM,CAgBR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAI/D"}
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ /**
3
+ * ECIES key wrapping using secp256k1.
4
+ *
5
+ * Encrypt:
6
+ * 1. Generate ephemeral secp256k1 key pair
7
+ * 2. ECDH(ephemeral private, recipient public) → shared secret
8
+ * 3. HKDF-SHA256(shared secret) → 32-byte wrapping key
9
+ * 4. AES-256-GCM encrypt plaintext with wrapping key
10
+ *
11
+ * Decrypt:
12
+ * 1. ECDH(recipient private, ephemeral public) → same shared secret
13
+ * 2. HKDF-SHA256(shared secret) → same wrapping key
14
+ * 3. AES-256-GCM decrypt ciphertext
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.KEY_ALGORITHM = exports.KEY_ALGORITHM_SECP256K1 = void 0;
51
+ exports.wrapKey = wrapKey;
52
+ exports.unwrapKey = unwrapKey;
53
+ exports.publicKeyFromPrivate = publicKeyFromPrivate;
54
+ const crypto = __importStar(require("crypto"));
55
+ const secp256k1_1 = require("@noble/curves/secp256k1");
56
+ const hkdf_1 = require("@noble/hashes/hkdf");
57
+ const sha256_1 = require("@noble/hashes/sha256");
58
+ exports.KEY_ALGORITHM_SECP256K1 = 'ecies-secp256k1-aes256gcm';
59
+ /** @deprecated Use KEY_ALGORITHM_SECP256K1 */
60
+ exports.KEY_ALGORITHM = exports.KEY_ALGORITHM_SECP256K1;
61
+ const AES_KEY_BYTES = 32;
62
+ const GCM_IV_BYTES = 12;
63
+ const GCM_AUTH_TAG_BYTES = 16;
64
+ const HKDF_INFO = Buffer.from('neozipkit-pro/ecies/v1', 'utf8');
65
+ function deriveWrappingKey(sharedSecret) {
66
+ const ikm = sharedSecret.slice(1); // drop the 0x04 prefix byte
67
+ const derived = (0, hkdf_1.hkdf)(sha256_1.sha256, ikm, undefined, HKDF_INFO, AES_KEY_BYTES);
68
+ return Buffer.from(derived);
69
+ }
70
+ /**
71
+ * Wrap (encrypt) plaintext so only the holder of `recipientPubKeyHex` can unwrap it.
72
+ *
73
+ * @param recipientPubKeyHex Uncompressed secp256k1 public key ("04…", 130 hex chars).
74
+ * @param plaintext The secret to protect (typically a hex-encoded AES password).
75
+ */
76
+ function wrapKey(recipientPubKeyHex, plaintext) {
77
+ const recipientPub = hexToBytes(recipientPubKeyHex);
78
+ const ephPriv = secp256k1_1.secp256k1.utils.randomPrivateKey();
79
+ const ephPub = secp256k1_1.secp256k1.getPublicKey(ephPriv, false); // uncompressed
80
+ const shared = secp256k1_1.secp256k1.getSharedSecret(ephPriv, recipientPub, false);
81
+ const wrappingKey = deriveWrappingKey(shared);
82
+ const iv = crypto.randomBytes(GCM_IV_BYTES);
83
+ const cipher = crypto.createCipheriv('aes-256-gcm', wrappingKey, iv);
84
+ const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
85
+ const tag = cipher.getAuthTag();
86
+ // ciphertext layout: iv (12) || authTag (16) || encrypted data
87
+ const ciphertextBuf = Buffer.concat([iv, tag, encrypted]);
88
+ return {
89
+ ciphertext: ciphertextBuf.toString('base64'),
90
+ ephemeralPublicKey: Buffer.from(ephPub).toString('hex'),
91
+ keyAlgorithm: exports.KEY_ALGORITHM,
92
+ };
93
+ }
94
+ /**
95
+ * Unwrap (decrypt) ciphertext using the recipient's private key.
96
+ *
97
+ * @param recipientPrivKeyHex Recipient's secp256k1 private key (hex, 64 chars).
98
+ * @param ciphertextB64 Base64 string produced by `wrapKey`.
99
+ * @param ephemeralPubKeyHex Ephemeral public key from `wrapKey` result.
100
+ * @returns The original plaintext buffer.
101
+ */
102
+ function unwrapKey(recipientPrivKeyHex, ciphertextB64, ephemeralPubKeyHex) {
103
+ const recipientPriv = hexToBytes(recipientPrivKeyHex);
104
+ const ephPub = hexToBytes(ephemeralPubKeyHex);
105
+ const shared = secp256k1_1.secp256k1.getSharedSecret(recipientPriv, ephPub, false);
106
+ const wrappingKey = deriveWrappingKey(shared);
107
+ const ciphertextBuf = Buffer.from(ciphertextB64, 'base64');
108
+ const iv = ciphertextBuf.subarray(0, GCM_IV_BYTES);
109
+ const tag = ciphertextBuf.subarray(GCM_IV_BYTES, GCM_IV_BYTES + GCM_AUTH_TAG_BYTES);
110
+ const encrypted = ciphertextBuf.subarray(GCM_IV_BYTES + GCM_AUTH_TAG_BYTES);
111
+ const decipher = crypto.createDecipheriv('aes-256-gcm', wrappingKey, iv);
112
+ decipher.setAuthTag(tag);
113
+ const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
114
+ return decrypted;
115
+ }
116
+ /**
117
+ * Derive the public key (uncompressed, hex) from a private key. Useful for
118
+ * matching a recipient entry in ACCESS.NZIP without knowing the identity string.
119
+ */
120
+ function publicKeyFromPrivate(privKeyHex) {
121
+ const priv = hexToBytes(privKeyHex);
122
+ const pub = secp256k1_1.secp256k1.getPublicKey(priv, false);
123
+ return Buffer.from(pub).toString('hex');
124
+ }
125
+ function hexToBytes(hex) {
126
+ const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
127
+ return Uint8Array.from(Buffer.from(clean, 'hex'));
128
+ }
129
+ //# sourceMappingURL=KeyWrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyWrapper.js","sourceRoot":"","sources":["../../src/encryption/KeyWrapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * ECIES key wrapping using X25519 (Curve25519 Diffie-Hellman).
3
+ *
4
+ * X25519 is purpose-built for key agreement / secure messaging and is used by
5
+ * Signal, WireGuard, TLS 1.3, and libsodium. The ZipStamp server provisions
6
+ * X25519 key pairs for each user, so no additional key infrastructure is needed.
7
+ *
8
+ * Encrypt:
9
+ * 1. Generate ephemeral X25519 key pair
10
+ * 2. X25519(ephemeral private, recipient public) → 32-byte shared secret
11
+ * 3. HKDF-SHA256(shared secret) → 32-byte wrapping key
12
+ * 4. AES-256-GCM encrypt plaintext with wrapping key
13
+ *
14
+ * Decrypt:
15
+ * 1. X25519(recipient private, ephemeral public) → same shared secret
16
+ * 2. HKDF-SHA256(shared secret) → same wrapping key
17
+ * 3. AES-256-GCM decrypt ciphertext
18
+ */
19
+ import type { WrappedKeyResult } from './types';
20
+ export declare const KEY_ALGORITHM_X25519 = "ecies-x25519-aes256gcm";
21
+ /**
22
+ * Wrap (encrypt) plaintext so only the holder of `recipientPubKeyHex` can unwrap it.
23
+ *
24
+ * @param recipientPubKeyHex Raw X25519 public key, 64 hex chars (32 bytes).
25
+ * Obtained from ZipStamp GET /crypto/public → x25519PublicKey.
26
+ * @param plaintext The secret to protect (typically a hex-encoded AES password).
27
+ */
28
+ export declare function wrapKeyX25519(recipientPubKeyHex: string, plaintext: Buffer): WrappedKeyResult;
29
+ /**
30
+ * Unwrap (decrypt) ciphertext using the recipient's X25519 private key.
31
+ *
32
+ * @param recipientPrivKeyHex Recipient's X25519 private key (hex, 64 chars / 32 bytes).
33
+ * @param ciphertextB64 Base64 string produced by `wrapKeyX25519`.
34
+ * @param ephemeralPubKeyHex Ephemeral public key from `wrapKeyX25519` result (64 hex chars).
35
+ * @returns The original plaintext buffer.
36
+ */
37
+ export declare function unwrapKeyX25519(recipientPrivKeyHex: string, ciphertextB64: string, ephemeralPubKeyHex: string): Buffer;
38
+ /**
39
+ * Derive the X25519 public key (hex, 64 chars) from a private key.
40
+ * Useful for matching a recipient entry in ACCESS.NZIP.
41
+ */
42
+ export declare function publicKeyFromPrivateX25519(privKeyHex: string): string;
43
+ //# sourceMappingURL=KeyWrapperX25519.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyWrapperX25519.d.ts","sourceRoot":"","sources":["../../src/encryption/KeyWrapperX25519.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAW7D;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,GAChB,gBAAgB,CAyBlB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,mBAAmB,EAAE,MAAM,EAC3B,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GACzB,MAAM,CAsBR;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrE"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * ECIES key wrapping using X25519 (Curve25519 Diffie-Hellman).
4
+ *
5
+ * X25519 is purpose-built for key agreement / secure messaging and is used by
6
+ * Signal, WireGuard, TLS 1.3, and libsodium. The ZipStamp server provisions
7
+ * X25519 key pairs for each user, so no additional key infrastructure is needed.
8
+ *
9
+ * Encrypt:
10
+ * 1. Generate ephemeral X25519 key pair
11
+ * 2. X25519(ephemeral private, recipient public) → 32-byte shared secret
12
+ * 3. HKDF-SHA256(shared secret) → 32-byte wrapping key
13
+ * 4. AES-256-GCM encrypt plaintext with wrapping key
14
+ *
15
+ * Decrypt:
16
+ * 1. X25519(recipient private, ephemeral public) → same shared secret
17
+ * 2. HKDF-SHA256(shared secret) → same wrapping key
18
+ * 3. AES-256-GCM decrypt ciphertext
19
+ */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || (function () {
37
+ var ownKeys = function(o) {
38
+ ownKeys = Object.getOwnPropertyNames || function (o) {
39
+ var ar = [];
40
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
41
+ return ar;
42
+ };
43
+ return ownKeys(o);
44
+ };
45
+ return function (mod) {
46
+ if (mod && mod.__esModule) return mod;
47
+ var result = {};
48
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49
+ __setModuleDefault(result, mod);
50
+ return result;
51
+ };
52
+ })();
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.KEY_ALGORITHM_X25519 = void 0;
55
+ exports.wrapKeyX25519 = wrapKeyX25519;
56
+ exports.unwrapKeyX25519 = unwrapKeyX25519;
57
+ exports.publicKeyFromPrivateX25519 = publicKeyFromPrivateX25519;
58
+ const crypto = __importStar(require("crypto"));
59
+ const ed25519_1 = require("@noble/curves/ed25519");
60
+ const hkdf_1 = require("@noble/hashes/hkdf");
61
+ const sha256_1 = require("@noble/hashes/sha256");
62
+ exports.KEY_ALGORITHM_X25519 = 'ecies-x25519-aes256gcm';
63
+ const AES_KEY_BYTES = 32;
64
+ const GCM_IV_BYTES = 12;
65
+ const GCM_AUTH_TAG_BYTES = 16;
66
+ const HKDF_INFO = Buffer.from('neozipkit-pro/ecies-x25519/v1', 'utf8');
67
+ function deriveWrappingKey(sharedSecret) {
68
+ const derived = (0, hkdf_1.hkdf)(sha256_1.sha256, sharedSecret, undefined, HKDF_INFO, AES_KEY_BYTES);
69
+ return Buffer.from(derived);
70
+ }
71
+ /**
72
+ * Wrap (encrypt) plaintext so only the holder of `recipientPubKeyHex` can unwrap it.
73
+ *
74
+ * @param recipientPubKeyHex Raw X25519 public key, 64 hex chars (32 bytes).
75
+ * Obtained from ZipStamp GET /crypto/public → x25519PublicKey.
76
+ * @param plaintext The secret to protect (typically a hex-encoded AES password).
77
+ */
78
+ function wrapKeyX25519(recipientPubKeyHex, plaintext) {
79
+ const clean = recipientPubKeyHex.startsWith('0x')
80
+ ? recipientPubKeyHex.slice(2)
81
+ : recipientPubKeyHex;
82
+ const recipientPub = Uint8Array.from(Buffer.from(clean, 'hex'));
83
+ const ephPriv = ed25519_1.x25519.utils.randomPrivateKey();
84
+ const ephPub = ed25519_1.x25519.getPublicKey(ephPriv);
85
+ const shared = ed25519_1.x25519.getSharedSecret(ephPriv, recipientPub);
86
+ const wrappingKey = deriveWrappingKey(shared);
87
+ const iv = crypto.randomBytes(GCM_IV_BYTES);
88
+ const cipher = crypto.createCipheriv('aes-256-gcm', wrappingKey, iv);
89
+ const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
90
+ const tag = cipher.getAuthTag();
91
+ // ciphertext layout: iv (12) || authTag (16) || encrypted data
92
+ const ciphertextBuf = Buffer.concat([iv, tag, encrypted]);
93
+ return {
94
+ ciphertext: ciphertextBuf.toString('base64'),
95
+ ephemeralPublicKey: Buffer.from(ephPub).toString('hex'),
96
+ keyAlgorithm: exports.KEY_ALGORITHM_X25519,
97
+ };
98
+ }
99
+ /**
100
+ * Unwrap (decrypt) ciphertext using the recipient's X25519 private key.
101
+ *
102
+ * @param recipientPrivKeyHex Recipient's X25519 private key (hex, 64 chars / 32 bytes).
103
+ * @param ciphertextB64 Base64 string produced by `wrapKeyX25519`.
104
+ * @param ephemeralPubKeyHex Ephemeral public key from `wrapKeyX25519` result (64 hex chars).
105
+ * @returns The original plaintext buffer.
106
+ */
107
+ function unwrapKeyX25519(recipientPrivKeyHex, ciphertextB64, ephemeralPubKeyHex) {
108
+ const cleanPriv = recipientPrivKeyHex.startsWith('0x')
109
+ ? recipientPrivKeyHex.slice(2)
110
+ : recipientPrivKeyHex;
111
+ const cleanEph = ephemeralPubKeyHex.startsWith('0x')
112
+ ? ephemeralPubKeyHex.slice(2)
113
+ : ephemeralPubKeyHex;
114
+ const recipientPriv = Uint8Array.from(Buffer.from(cleanPriv, 'hex'));
115
+ const ephPub = Uint8Array.from(Buffer.from(cleanEph, 'hex'));
116
+ const shared = ed25519_1.x25519.getSharedSecret(recipientPriv, ephPub);
117
+ const wrappingKey = deriveWrappingKey(shared);
118
+ const ciphertextBuf = Buffer.from(ciphertextB64, 'base64');
119
+ const iv = ciphertextBuf.subarray(0, GCM_IV_BYTES);
120
+ const tag = ciphertextBuf.subarray(GCM_IV_BYTES, GCM_IV_BYTES + GCM_AUTH_TAG_BYTES);
121
+ const encrypted = ciphertextBuf.subarray(GCM_IV_BYTES + GCM_AUTH_TAG_BYTES);
122
+ const decipher = crypto.createDecipheriv('aes-256-gcm', wrappingKey, iv);
123
+ decipher.setAuthTag(tag);
124
+ return Buffer.concat([decipher.update(encrypted), decipher.final()]);
125
+ }
126
+ /**
127
+ * Derive the X25519 public key (hex, 64 chars) from a private key.
128
+ * Useful for matching a recipient entry in ACCESS.NZIP.
129
+ */
130
+ function publicKeyFromPrivateX25519(privKeyHex) {
131
+ const clean = privKeyHex.startsWith('0x') ? privKeyHex.slice(2) : privKeyHex;
132
+ const priv = Uint8Array.from(Buffer.from(clean, 'hex'));
133
+ const pub = ed25519_1.x25519.getPublicKey(priv);
134
+ return Buffer.from(pub).toString('hex');
135
+ }
136
+ //# sourceMappingURL=KeyWrapperX25519.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyWrapperX25519.js","sourceRoot":"","sources":["../../src/encryption/KeyWrapperX25519.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * High-level orchestrator for identity-based (recipient) encryption.
3
+ *
4
+ * Encrypt workflow:
5
+ * 1. Generate a random AES password (32 random bytes → hex)
6
+ * 2. Create a NeoEncrypt (neo-aes256) encrypted .nzip via neozipkit by default
7
+ * 3. For each recipient: ECIES-wrap the password with their public key
8
+ * 4. Append META-INF/ACCESS.NZIP (STORED, unencrypted) with the wrapped keys
9
+ *
10
+ * Decrypt workflow:
11
+ * 1. Load the .nzip and extract META-INF/ACCESS.NZIP
12
+ * 2. Match the recipient by public key derived from the private key
13
+ * 3. ECIES-unwrap → recover the AES password
14
+ * 4. Set the password on the zipkit instance for normal extraction
15
+ */
16
+ import type { ResolvedIdentity } from '../identity/types';
17
+ import type { RecipientEncryptionFileInput, RecipientEncryptionOptions } from './types';
18
+ interface ZipkitNodeLike {
19
+ initializeZipFile(outputPath: string): Promise<any>;
20
+ prepareEntryFromFile(filePath: string, entryName?: string): Promise<any>;
21
+ writeZipEntry(writer: any, entry: any, filePath: string, options?: any): Promise<void>;
22
+ writeCentralDirectory(writer: any, entries: any[], options?: any): Promise<number>;
23
+ writeEndOfCentralDirectory(writer: any, count: number, size: number, offset: number): Promise<void>;
24
+ finalizeZipFile(writer: any): Promise<void>;
25
+ getDirectory(): any[];
26
+ loadZipFile(filePath: string): Promise<any[]>;
27
+ getZipEntry(filename: string): any | null;
28
+ extractToBuffer(entry: any, options?: any): Promise<Buffer>;
29
+ /** neozipkit ZipkitNode: close read handle opened by loadZipFile */
30
+ closeFile?: () => Promise<void>;
31
+ }
32
+ /**
33
+ * Create an encrypted .nzip file that can only be opened by the listed
34
+ * recipients (via their secp256k1 public keys). Entry data uses **NeoEncrypt**
35
+ * (`neo-aes256`, NEO extra `0x024E` in neozipkit) by default; set
36
+ * `zipEncryptionMethod: 'aes256'` in options if you need WinZip AES.
37
+ *
38
+ * @param zipkit A fresh ZipkitNode instance (will be mutated).
39
+ * @param files Paths only (`string[]`) or `{ path, entryName? }[]` — forwarded to neozipkit
40
+ * `prepareEntryFromFile` / `writeZipEntry` (compress then encrypt).
41
+ * @param outputPath Where to write the .nzip.
42
+ * @param recipients Pre-resolved identities with public keys.
43
+ * @param options Compression and inner ZIP encryption options forwarded to neozipkit.
44
+ */
45
+ export declare function encryptForRecipients(zipkit: ZipkitNodeLike, files: string[] | RecipientEncryptionFileInput[], outputPath: string, recipients: ResolvedIdentity[], options?: RecipientEncryptionOptions): Promise<void>;
46
+ /**
47
+ * Recover the AES password from a recipient-encrypted .nzip and configure the
48
+ * zipkit instance for extraction.
49
+ *
50
+ * After this call succeeds, use the returned zipkit normally:
51
+ * `const buf = await zipkit.extractToBuffer(entry);`
52
+ *
53
+ * @param zipkit A ZipkitNode instance.
54
+ * @param archivePath Path to the .nzip file.
55
+ * @param recipientPrivKey Recipient's secp256k1 private key (hex).
56
+ * @returns The same zipkit instance, now configured with the recovered password.
57
+ */
58
+ export declare function decryptAsRecipient(zipkit: ZipkitNodeLike, archivePath: string, recipientPrivKey: string): Promise<ZipkitNodeLike>;
59
+ export {};
60
+ //# sourceMappingURL=RecipientEncryption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecipientEncryption.d.ts","sourceRoot":"","sources":["../../src/encryption/RecipientEncryption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAmBH,OAAO,KAAK,EAAE,gBAAgB,EAAkC,MAAM,mBAAmB,CAAC;AAC1F,OAAO,KAAK,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAwCxF,UAAU,cAAc;IACtB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACpD,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACzE,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvF,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnF,0BAA0B,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpG,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,YAAY,IAAI,GAAG,EAAE,CAAC;IACtB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC;IAC1C,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5D,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,MAAM,EAAE,GAAG,4BAA4B,EAAE,EAChD,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,gBAAgB,EAAE,EAC9B,OAAO,CAAC,EAAE,0BAA0B,GACnC,OAAO,CAAC,IAAI,CAAC,CAkFf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,CAAC,CA6DzB"}