@parmanasystems/crypto 1.71.5 → 1.71.9

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/dist/index.d.ts CHANGED
@@ -1,14 +1,17 @@
1
1
  /**
2
2
  * Reads the root trust private key PEM.
3
+ * Auto-generates a dev keypair at the default location if neither key file exists.
3
4
  *
4
- * Production deployments should inject this
5
- * via secure secret management.
5
+ * @param keyPath - explicit path to the private key file; defaults to ./trust/root.key
6
6
  */
7
- declare function loadPrivateKey(): string;
7
+ declare function loadPrivateKey(keyPath?: string): string;
8
8
  /**
9
9
  * Reads the root trust public key PEM.
10
+ * Auto-generates a dev keypair at the default location if neither key file exists.
11
+ *
12
+ * @param keyPath - explicit path to the public key file; defaults to ./trust/root.pub
10
13
  */
11
- declare function loadPublicKey(): string;
14
+ declare function loadPublicKey(keyPath?: string): string;
12
15
 
13
16
  /**
14
17
  * Writes a base64 signature string to `<directory>/bundle.sig`.
package/dist/index.js CHANGED
@@ -1,25 +1,45 @@
1
1
  // src/keys.ts
2
+ import * as crypto from "crypto";
2
3
  import * as fs from "fs";
3
4
  import * as path from "path";
4
- var PRIVATE_KEY_PATH = path.resolve(
5
- process.cwd(),
6
- "trust",
7
- "root.key"
8
- );
9
- var PUBLIC_KEY_PATH = path.resolve(
10
- process.cwd(),
11
- "trust",
12
- "root.pub"
13
- );
14
- function loadPrivateKey() {
5
+ function ensureTrustKeys(privateKeyPath, publicKeyPath) {
6
+ if (fs.existsSync(privateKeyPath) && fs.existsSync(publicKeyPath)) {
7
+ return;
8
+ }
9
+ const { privateKey, publicKey } = crypto.generateKeyPairSync("ed25519", {
10
+ privateKeyEncoding: { type: "pkcs8", format: "pem" },
11
+ publicKeyEncoding: { type: "spki", format: "pem" }
12
+ });
13
+ fs.mkdirSync(
14
+ path.dirname(privateKeyPath),
15
+ { recursive: true }
16
+ );
17
+ fs.writeFileSync(privateKeyPath, privateKey, "utf8");
18
+ fs.writeFileSync(publicKeyPath, publicKey, "utf8");
19
+ }
20
+ function loadPrivateKey(keyPath) {
21
+ const resolvedPath = keyPath ?? path.resolve(
22
+ process.cwd(),
23
+ "trust",
24
+ "root.key"
25
+ );
26
+ const publicPath = resolvedPath.replace(/root\.key$/, "root.pub");
27
+ ensureTrustKeys(resolvedPath, publicPath);
15
28
  return fs.readFileSync(
16
- PRIVATE_KEY_PATH,
29
+ resolvedPath,
17
30
  "utf8"
18
31
  );
19
32
  }
20
- function loadPublicKey() {
33
+ function loadPublicKey(keyPath) {
34
+ const resolvedPath = keyPath ?? path.resolve(
35
+ process.cwd(),
36
+ "trust",
37
+ "root.pub"
38
+ );
39
+ const privatePath = resolvedPath.replace(/root\.pub$/, "root.key");
40
+ ensureTrustKeys(privatePath, resolvedPath);
21
41
  return fs.readFileSync(
22
- PUBLIC_KEY_PATH,
42
+ resolvedPath,
23
43
  "utf8"
24
44
  );
25
45
  }
@@ -51,7 +71,7 @@ function readSignature(directory) {
51
71
 
52
72
  // src/sign.ts
53
73
  import * as fs3 from "fs";
54
- import * as crypto from "crypto";
74
+ import * as crypto2 from "crypto";
55
75
  import {
56
76
  canonicalize
57
77
  } from "@parmanasystems/bundle";
@@ -66,7 +86,7 @@ function signManifest(manifestPath) {
66
86
  manifest
67
87
  );
68
88
  const privateKey = loadPrivateKey();
69
- const signature = crypto.sign(
89
+ const signature = crypto2.sign(
70
90
  null,
71
91
  Buffer.from(
72
92
  canonical,
@@ -81,7 +101,7 @@ function signManifest(manifestPath) {
81
101
 
82
102
  // src/verify.ts
83
103
  import * as fs4 from "fs";
84
- import * as crypto2 from "crypto";
104
+ import * as crypto3 from "crypto";
85
105
  import {
86
106
  canonicalize as canonicalize2
87
107
  } from "@parmanasystems/bundle";
@@ -96,7 +116,7 @@ function verifySignature(manifestPath, signature) {
96
116
  manifest
97
117
  );
98
118
  const publicKey = loadPublicKey();
99
- return crypto2.verify(
119
+ return crypto3.verify(
100
120
  null,
101
121
  Buffer.from(
102
122
  canonical,
@@ -110,7 +130,7 @@ function verifySignature(manifestPath, signature) {
110
130
  );
111
131
  }
112
132
  function verifyPayloadSignature(payload, signature, publicKey) {
113
- return crypto2.verify(
133
+ return crypto3.verify(
114
134
  null,
115
135
  Buffer.from(
116
136
  payload,
@@ -125,10 +145,10 @@ function verifyPayloadSignature(payload, signature, publicKey) {
125
145
  }
126
146
 
127
147
  // src/verify-manifest-signature.ts
128
- import * as crypto3 from "crypto";
148
+ import * as crypto4 from "crypto";
129
149
  function verifyManifestSignature(manifest, signature) {
130
150
  const publicKey = loadPublicKey();
131
- return crypto3.verify(
151
+ return crypto4.verify(
132
152
  null,
133
153
  Buffer.from(
134
154
  manifest
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/keys.ts","../src/persist.ts","../src/sign.ts","../src/verify.ts","../src/verify-manifest-signature.ts","../src/sign-bundle.ts"],"sourcesContent":["import * as fs from \"node:fs\";\r\n\r\nimport * as path from \"node:path\";\r\n\r\nconst PRIVATE_KEY_PATH =\r\n path.resolve(\r\n process.cwd(),\r\n \"trust\",\r\n \"root.key\"\r\n );\r\n\r\nconst PUBLIC_KEY_PATH =\r\n path.resolve(\r\n process.cwd(),\r\n \"trust\",\r\n \"root.pub\"\r\n );\r\n\r\n/**\r\n * Reads the root trust private key PEM.\r\n *\r\n * Production deployments should inject this\r\n * via secure secret management.\r\n */\r\nexport function loadPrivateKey(): string {\r\n\r\n return fs.readFileSync(\r\n PRIVATE_KEY_PATH,\r\n \"utf8\"\r\n );\r\n}\r\n\r\n/**\r\n * Reads the root trust public key PEM.\r\n */\r\nexport function loadPublicKey(): string {\r\n\r\n return fs.readFileSync(\r\n PUBLIC_KEY_PATH,\r\n \"utf8\"\r\n );\r\n}\r\n","import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\n/**\r\n * Writes a base64 signature string to `<directory>/bundle.sig`.\r\n * Overwrites any existing file at that path.\r\n */\r\nexport function writeSignature(\r\n signature: string,\r\n directory: string\r\n): void {\r\n const signaturePath = path.join(\r\n directory,\r\n \"bundle.sig\"\r\n );\r\n\r\n fs.writeFileSync(\r\n signaturePath,\r\n signature,\r\n \"utf8\"\r\n );\r\n}\r\n\r\n/** Reads and returns the raw base64 signature from `<directory>/bundle.sig`. */\r\nexport function readSignature(\r\n directory: string\r\n): string {\r\n const signaturePath = path.join(\r\n directory,\r\n \"bundle.sig\"\r\n );\r\n\r\n return fs.readFileSync(\r\n signaturePath,\r\n \"utf8\"\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\n\r\nimport * as crypto from \"node:crypto\";\r\nimport {\r\n canonicalize,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n loadPrivateKey,\r\n} from \"./keys.js\";\r\n\r\n/**\r\n * Reads the manifest JSON at `manifestPath`, canonicalizes it, and returns a\r\n * base64-encoded Ed25519 signature produced with the dev private key.\r\n *\r\n * @param manifestPath - Absolute or CWD-relative path to a `bundle.manifest.json` file.\r\n * @returns Base64-encoded Ed25519 signature over the canonical manifest bytes.\r\n */\r\nexport function signManifest(\r\n manifestPath: string\r\n): string {\r\n\r\n const manifest =\r\n JSON.parse(\r\n fs.readFileSync(\r\n manifestPath,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n const canonical =\r\n canonicalize(\r\n manifest\r\n );\r\n\r\n const privateKey =\r\n loadPrivateKey();\r\n\r\n const signature =\r\n crypto.sign(\r\n null,\r\n\r\n Buffer.from(\r\n canonical,\r\n \"utf8\"\r\n ),\r\n\r\n privateKey\r\n );\r\n\r\n return signature.toString(\r\n \"base64\"\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\n\r\nimport * as crypto from \"node:crypto\";\r\n\r\nimport {\r\n canonicalize,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n loadPublicKey,\r\n} from \"./keys.js\";\r\n\r\n/**\r\n * Reads the manifest JSON at `manifestPath`, canonicalizes it, and verifies\r\n * `signature` (base64 Ed25519) against the dev public key.\r\n *\r\n * @param manifestPath - Path to the `bundle.manifest.json` file.\r\n * @param signature - Base64-encoded Ed25519 signature to verify.\r\n */\r\nexport function verifySignature(\r\n manifestPath: string,\r\n signature: string\r\n): boolean {\r\n\r\n const manifest =\r\n JSON.parse(\r\n fs.readFileSync(\r\n manifestPath,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n const canonical =\r\n canonicalize(\r\n manifest\r\n );\r\n\r\n const publicKey =\r\n loadPublicKey();\r\n\r\n return crypto.verify(\r\n null,\r\n\r\n Buffer.from(\r\n canonical,\r\n \"utf8\"\r\n ),\r\n\r\n publicKey,\r\n\r\n Buffer.from(\r\n signature,\r\n \"base64\"\r\n )\r\n );\r\n}\r\n\r\n/**\r\n * Verifies a base64-encoded Ed25519 `signature` over an arbitrary UTF-8\r\n * `payload` using the provided `publicKey` PEM. Unlike `verifySignature`,\r\n * this function accepts any payload string rather than reading a manifest\r\n * file from disk.\r\n *\r\n * @param payload - The original signed UTF-8 string.\r\n * @param signature - Base64-encoded Ed25519 signature.\r\n * @param publicKey - PEM-encoded Ed25519 public key.\r\n */\r\nexport function verifyPayloadSignature(\r\n payload: string,\r\n signature: string,\r\n publicKey: string\r\n): boolean {\r\n\r\n return crypto.verify(\r\n null,\r\n\r\n Buffer.from(\r\n payload,\r\n \"utf8\"\r\n ),\r\n\r\n publicKey,\r\n\r\n Buffer.from(\r\n signature,\r\n \"base64\"\r\n )\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import * as crypto from \"node:crypto\";\r\n\r\nimport {\r\n loadPublicKey,\r\n} from \"./keys.js\";\r\n\r\n/**\r\n * Verifies `signature` (base64 Ed25519) over the already-serialized canonical\r\n * `manifest` string against the dev public key.\r\n *\r\n * Unlike `verifySignature`, this function accepts the manifest bytes directly\r\n * rather than reading them from disk — suited for in-memory verification flows.\r\n *\r\n * @param manifest - Canonical manifest bytes (UTF-8 string).\r\n * @param signature - Base64-encoded Ed25519 signature.\r\n */\r\nexport function verifyManifestSignature(\r\n manifest: string,\r\n signature: string\r\n): boolean {\r\n\r\n const publicKey =\r\n loadPublicKey();\r\n\r\n return crypto.verify(\r\n null,\r\n\r\n Buffer.from(\r\n manifest\r\n ),\r\n\r\n publicKey,\r\n\r\n Buffer.from(\r\n signature,\r\n \"base64\"\r\n )\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\n\r\n// ----------------------------------\r\n// Local deterministic canonicalize\r\n// ----------------------------------\r\n\r\nfunction canonicalize(\r\n value: unknown\r\n): string {\r\n\r\n if (\r\n value === null ||\r\n typeof value !== \"object\"\r\n ) {\r\n return JSON.stringify(value);\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return `[${value\r\n .map(canonicalize)\r\n .join(\",\")}]`;\r\n }\r\n\r\n const entries =\r\n Object.entries(\r\n value as Record<string, unknown>\r\n )\r\n .sort(([a], [b]) =>\r\n a.localeCompare(b)\r\n );\r\n\r\n return `{${entries\r\n .map(\r\n ([key, val]) =>\r\n `${JSON.stringify(key)}:${canonicalize(val)}`\r\n )\r\n .join(\",\")}}`;\r\n}\r\n\r\ntype SignBundleOptions = {\r\n\r\n bundlePath: string;\r\n\r\n signer: {\r\n\r\n sign(\r\n payload: string\r\n ): Promise<string>;\r\n };\r\n};\r\n\r\nexport async function signBundle(\r\n options: SignBundleOptions\r\n): Promise<void> {\r\n\r\n const manifestPath =\r\n path.join(\r\n options.bundlePath,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n const manifest =\r\n JSON.parse(\r\n fs.readFileSync(\r\n manifestPath,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n const canonical =\r\n canonicalize(manifest);\r\n\r\n const signature =\r\n await options.signer.sign(\r\n canonical\r\n );\r\n\r\n fs.writeFileSync(\r\n\r\n path.join(\r\n options.bundlePath,\r\n \"bundle.sig\"\r\n ),\r\n\r\n signature\r\n );\r\n}\r\n"],"mappings":"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","names":["fs","path","fs","fs","crypto","canonicalize","canonicalize","crypto","fs","path","canonicalize"]}
1
+ {"version":3,"sources":["../src/keys.ts","../src/persist.ts","../src/sign.ts","../src/verify.ts","../src/verify-manifest-signature.ts","../src/sign-bundle.ts"],"sourcesContent":["import * as crypto from \"node:crypto\";\r\nimport * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\nfunction ensureTrustKeys(\r\n privateKeyPath: string,\r\n publicKeyPath: string\r\n): void {\r\n if (\r\n fs.existsSync(privateKeyPath) &&\r\n fs.existsSync(publicKeyPath)\r\n ) {\r\n return;\r\n }\r\n\r\n const { privateKey, publicKey } =\r\n crypto.generateKeyPairSync(\"ed25519\", {\r\n privateKeyEncoding: { type: \"pkcs8\", format: \"pem\" },\r\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\r\n });\r\n\r\n fs.mkdirSync(\r\n path.dirname(privateKeyPath),\r\n { recursive: true }\r\n );\r\n\r\n fs.writeFileSync(privateKeyPath, privateKey, \"utf8\");\r\n fs.writeFileSync(publicKeyPath, publicKey, \"utf8\");\r\n}\r\n\r\n/**\r\n * Reads the root trust private key PEM.\r\n * Auto-generates a dev keypair at the default location if neither key file exists.\r\n *\r\n * @param keyPath - explicit path to the private key file; defaults to ./trust/root.key\r\n */\r\nexport function loadPrivateKey(keyPath?: string): string {\r\n\r\n const resolvedPath =\r\n keyPath ??\r\n path.resolve(\r\n process.cwd(),\r\n \"trust\",\r\n \"root.key\"\r\n );\r\n\r\n const publicPath =\r\n resolvedPath.replace(/root\\.key$/, \"root.pub\");\r\n\r\n ensureTrustKeys(resolvedPath, publicPath);\r\n\r\n return fs.readFileSync(\r\n resolvedPath,\r\n \"utf8\"\r\n );\r\n}\r\n\r\n/**\r\n * Reads the root trust public key PEM.\r\n * Auto-generates a dev keypair at the default location if neither key file exists.\r\n *\r\n * @param keyPath - explicit path to the public key file; defaults to ./trust/root.pub\r\n */\r\nexport function loadPublicKey(keyPath?: string): string {\r\n\r\n const resolvedPath =\r\n keyPath ??\r\n path.resolve(\r\n process.cwd(),\r\n \"trust\",\r\n \"root.pub\"\r\n );\r\n\r\n const privatePath =\r\n resolvedPath.replace(/root\\.pub$/, \"root.key\");\r\n\r\n ensureTrustKeys(privatePath, resolvedPath);\r\n\r\n return fs.readFileSync(\r\n resolvedPath,\r\n \"utf8\"\r\n );\r\n}\r\n","import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\n/**\r\n * Writes a base64 signature string to `<directory>/bundle.sig`.\r\n * Overwrites any existing file at that path.\r\n */\r\nexport function writeSignature(\r\n signature: string,\r\n directory: string\r\n): void {\r\n const signaturePath = path.join(\r\n directory,\r\n \"bundle.sig\"\r\n );\r\n\r\n fs.writeFileSync(\r\n signaturePath,\r\n signature,\r\n \"utf8\"\r\n );\r\n}\r\n\r\n/** Reads and returns the raw base64 signature from `<directory>/bundle.sig`. */\r\nexport function readSignature(\r\n directory: string\r\n): string {\r\n const signaturePath = path.join(\r\n directory,\r\n \"bundle.sig\"\r\n );\r\n\r\n return fs.readFileSync(\r\n signaturePath,\r\n \"utf8\"\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\n\r\nimport * as crypto from \"node:crypto\";\r\nimport {\r\n canonicalize,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n loadPrivateKey,\r\n} from \"./keys.js\";\r\n\r\n/**\r\n * Reads the manifest JSON at `manifestPath`, canonicalizes it, and returns a\r\n * base64-encoded Ed25519 signature produced with the dev private key.\r\n *\r\n * @param manifestPath - Absolute or CWD-relative path to a `bundle.manifest.json` file.\r\n * @returns Base64-encoded Ed25519 signature over the canonical manifest bytes.\r\n */\r\nexport function signManifest(\r\n manifestPath: string\r\n): string {\r\n\r\n const manifest =\r\n JSON.parse(\r\n fs.readFileSync(\r\n manifestPath,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n const canonical =\r\n canonicalize(\r\n manifest\r\n );\r\n\r\n const privateKey =\r\n loadPrivateKey();\r\n\r\n const signature =\r\n crypto.sign(\r\n null,\r\n\r\n Buffer.from(\r\n canonical,\r\n \"utf8\"\r\n ),\r\n\r\n privateKey\r\n );\r\n\r\n return signature.toString(\r\n \"base64\"\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\n\r\nimport * as crypto from \"node:crypto\";\r\n\r\nimport {\r\n canonicalize,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n loadPublicKey,\r\n} from \"./keys.js\";\r\n\r\n/**\r\n * Reads the manifest JSON at `manifestPath`, canonicalizes it, and verifies\r\n * `signature` (base64 Ed25519) against the dev public key.\r\n *\r\n * @param manifestPath - Path to the `bundle.manifest.json` file.\r\n * @param signature - Base64-encoded Ed25519 signature to verify.\r\n */\r\nexport function verifySignature(\r\n manifestPath: string,\r\n signature: string\r\n): boolean {\r\n\r\n const manifest =\r\n JSON.parse(\r\n fs.readFileSync(\r\n manifestPath,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n const canonical =\r\n canonicalize(\r\n manifest\r\n );\r\n\r\n const publicKey =\r\n loadPublicKey();\r\n\r\n return crypto.verify(\r\n null,\r\n\r\n Buffer.from(\r\n canonical,\r\n \"utf8\"\r\n ),\r\n\r\n publicKey,\r\n\r\n Buffer.from(\r\n signature,\r\n \"base64\"\r\n )\r\n );\r\n}\r\n\r\n/**\r\n * Verifies a base64-encoded Ed25519 `signature` over an arbitrary UTF-8\r\n * `payload` using the provided `publicKey` PEM. Unlike `verifySignature`,\r\n * this function accepts any payload string rather than reading a manifest\r\n * file from disk.\r\n *\r\n * @param payload - The original signed UTF-8 string.\r\n * @param signature - Base64-encoded Ed25519 signature.\r\n * @param publicKey - PEM-encoded Ed25519 public key.\r\n */\r\nexport function verifyPayloadSignature(\r\n payload: string,\r\n signature: string,\r\n publicKey: string\r\n): boolean {\r\n\r\n return crypto.verify(\r\n null,\r\n\r\n Buffer.from(\r\n payload,\r\n \"utf8\"\r\n ),\r\n\r\n publicKey,\r\n\r\n Buffer.from(\r\n signature,\r\n \"base64\"\r\n )\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import * as crypto from \"node:crypto\";\r\n\r\nimport {\r\n loadPublicKey,\r\n} from \"./keys.js\";\r\n\r\n/**\r\n * Verifies `signature` (base64 Ed25519) over the already-serialized canonical\r\n * `manifest` string against the dev public key.\r\n *\r\n * Unlike `verifySignature`, this function accepts the manifest bytes directly\r\n * rather than reading them from disk — suited for in-memory verification flows.\r\n *\r\n * @param manifest - Canonical manifest bytes (UTF-8 string).\r\n * @param signature - Base64-encoded Ed25519 signature.\r\n */\r\nexport function verifyManifestSignature(\r\n manifest: string,\r\n signature: string\r\n): boolean {\r\n\r\n const publicKey =\r\n loadPublicKey();\r\n\r\n return crypto.verify(\r\n null,\r\n\r\n Buffer.from(\r\n manifest\r\n ),\r\n\r\n publicKey,\r\n\r\n Buffer.from(\r\n signature,\r\n \"base64\"\r\n )\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\n\r\n// ----------------------------------\r\n// Local deterministic canonicalize\r\n// ----------------------------------\r\n\r\nfunction canonicalize(\r\n value: unknown\r\n): string {\r\n\r\n if (\r\n value === null ||\r\n typeof value !== \"object\"\r\n ) {\r\n return JSON.stringify(value);\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return `[${value\r\n .map(canonicalize)\r\n .join(\",\")}]`;\r\n }\r\n\r\n const entries =\r\n Object.entries(\r\n value as Record<string, unknown>\r\n )\r\n .sort(([a], [b]) =>\r\n a.localeCompare(b)\r\n );\r\n\r\n return `{${entries\r\n .map(\r\n ([key, val]) =>\r\n `${JSON.stringify(key)}:${canonicalize(val)}`\r\n )\r\n .join(\",\")}}`;\r\n}\r\n\r\ntype SignBundleOptions = {\r\n\r\n bundlePath: string;\r\n\r\n signer: {\r\n\r\n sign(\r\n payload: string\r\n ): Promise<string>;\r\n };\r\n};\r\n\r\nexport async function signBundle(\r\n options: SignBundleOptions\r\n): Promise<void> {\r\n\r\n const manifestPath =\r\n path.join(\r\n options.bundlePath,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n const manifest =\r\n JSON.parse(\r\n fs.readFileSync(\r\n manifestPath,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n const canonical =\r\n canonicalize(manifest);\r\n\r\n const signature =\r\n await options.signer.sign(\r\n canonical\r\n );\r\n\r\n fs.writeFileSync(\r\n\r\n path.join(\r\n options.bundlePath,\r\n \"bundle.sig\"\r\n ),\r\n\r\n signature\r\n );\r\n}\r\n"],"mappings":"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","names":["fs","path","fs","crypto","fs","crypto","canonicalize","canonicalize","crypto","fs","path","canonicalize"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parmanasystems/crypto",
3
- "version": "1.71.5",
3
+ "version": "1.71.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  ],
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
- "@parmanasystems/bundle": "^1.71.5"
21
+ "@parmanasystems/bundle": "^1.71.9"
22
22
  },
23
23
  "description": "Signing and verification primitives for deterministic governance infrastructure.",
24
24
  "license": "Apache-2.0",