@hackthedev/dsync-sign 1.0.4 → 1.0.5

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 (2) hide show
  1. package/index.mjs +44 -16
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { promises as fs } from "fs";
1
+ import {promises as fs} from "fs";
2
2
  import crypto from "crypto";
3
3
 
4
4
  export class dSyncSign {
@@ -11,6 +11,7 @@ export class dSyncSign {
11
11
  if (x === null || typeof x !== "object") return x;
12
12
  if (Array.isArray(x)) return x.map(v => this.canonicalize(v));
13
13
  const out = {};
14
+
14
15
  for (const k of Object.keys(x).sort()) out[k] = this.canonicalize(x[k]);
15
16
  return out;
16
17
  }
@@ -30,45 +31,47 @@ export class dSyncSign {
30
31
  .trim();
31
32
  }
32
33
 
33
-
34
34
  async ensureKeyPair() {
35
35
  try {
36
36
  const raw = await fs.readFile(this.KEY_FILE, "utf8");
37
- const { privateKey } = JSON.parse(raw);
37
+ const {privateKey} = JSON.parse(raw);
38
+
38
39
  crypto.createPrivateKey(privateKey);
39
- const pubKey = crypto.createPublicKey(privateKey).export({ type: "spki", format: "pem" });
40
- return { privateKey, publicKey: pubKey.toString() };
40
+
41
+ const pubKey = crypto.createPublicKey(privateKey).export({type: "spki", format: "pem"});
42
+ return {privateKey, publicKey: pubKey.toString()};
41
43
  } catch {
42
- const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
44
+ const {privateKey, publicKey} = crypto.generateKeyPairSync("rsa", {
43
45
  modulusLength: 2048,
44
- publicKeyEncoding: { type: "spki", format: "pem" },
45
- privateKeyEncoding: { type: "pkcs8", format: "pem" }
46
+ publicKeyEncoding: {type: "spki", format: "pem"},
47
+ privateKeyEncoding: {type: "pkcs8", format: "pem"}
46
48
  });
47
- await fs.writeFile(this.KEY_FILE, JSON.stringify({ privateKey }, null, 2), { encoding: "utf8", mode: 0o600 });
48
- return { privateKey, publicKey };
49
+
50
+ await fs.writeFile(this.KEY_FILE, JSON.stringify({privateKey}, null, 2), {encoding: "utf8", mode: 0o600});
51
+ return {privateKey, publicKey};
49
52
  }
50
53
  }
51
54
 
52
55
  async getPrivateKey() {
53
- const { privateKey } = await this.ensureKeyPair();
56
+ const {privateKey} = await this.ensureKeyPair();
54
57
  return privateKey;
55
58
  }
56
59
 
57
60
  async getPublicKey() {
58
- const { publicKey } = await this.ensureKeyPair();
61
+ const {publicKey} = await this.ensureKeyPair();
59
62
  return publicKey;
60
63
  }
61
64
 
62
65
  async encrypt(data, recipient) {
63
66
  const plaintext = typeof data === "string" ? data : this.stableStringify(data);
64
67
  let aesKey;
65
- let envelope = { method: "" };
68
+ let envelope = {method: ""};
66
69
 
67
70
  if (recipient.includes("BEGIN PUBLIC KEY") || recipient.includes("BEGIN RSA PUBLIC KEY")) {
68
71
  aesKey = crypto.randomBytes(32);
69
72
  envelope.method = "rsa";
70
73
  envelope.encKey = crypto.publicEncrypt(
71
- { key: recipient, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING },
74
+ {key: recipient, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING},
72
75
  aesKey
73
76
  ).toString("base64");
74
77
  } else {
@@ -78,7 +81,9 @@ export class dSyncSign {
78
81
  envelope.salt = salt.toString("base64");
79
82
  }
80
83
 
81
- const iv = crypto.randomBytes(16);
84
+ // Standard-konformer 12-Byte-IV (statt 16)
85
+ const iv = crypto.randomBytes(12);
86
+
82
87
  const cipher = crypto.createCipheriv("aes-256-gcm", aesKey, iv);
83
88
  const ciphertext = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
84
89
  const tag = cipher.getAuthTag();
@@ -96,7 +101,7 @@ export class dSyncSign {
96
101
  if (envelope.method === "rsa") {
97
102
  const priv = await this.getPrivateKey();
98
103
  aesKey = crypto.privateDecrypt(
99
- { key: priv, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING },
104
+ {key: priv, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING},
100
105
  Buffer.from(envelope.encKey, "base64")
101
106
  );
102
107
  } else if (envelope.method === "password") {
@@ -132,16 +137,20 @@ export class dSyncSign {
132
137
  const priv = await this.getPrivateKey();
133
138
  const signer = crypto.createSign("SHA256");
134
139
  const payload = typeof data === "string" ? data : this.stableStringify(data);
140
+
135
141
  signer.update(payload, "utf8");
136
142
  signer.end();
143
+
137
144
  return signer.sign(priv, "base64");
138
145
  }
139
146
 
140
147
  verifyData(data, signature, publicKey) {
141
148
  const verifier = crypto.createVerify("SHA256");
142
149
  const payload = typeof data === "string" ? data : this.stableStringify(data);
150
+
143
151
  verifier.update(payload, "utf8");
144
152
  verifier.end();
153
+
145
154
  return verifier.verify(publicKey, signature, "base64");
146
155
  }
147
156
 
@@ -150,8 +159,10 @@ export class dSyncSign {
150
159
  const re = /([^.\[\]]+)|\[(\d+)\]/g;
151
160
  const parts = [];
152
161
  let m;
162
+
153
163
  while ((m = re.exec(path)) !== null) parts.push(m[1] !== undefined ? m[1] : Number(m[2]));
154
164
  let cur = root;
165
+
155
166
  for (const p of parts) {
156
167
  if (cur == null) return undefined;
157
168
  cur = cur[p];
@@ -162,6 +173,7 @@ export class dSyncSign {
162
173
  cloneWithoutSig(obj) {
163
174
  if (obj == null || typeof obj !== "object") return obj;
164
175
  let copy;
176
+
165
177
  if (typeof structuredClone === "function") {
166
178
  try {
167
179
  copy = structuredClone(obj);
@@ -171,16 +183,19 @@ export class dSyncSign {
171
183
  } else {
172
184
  copy = JSON.parse(JSON.stringify(obj));
173
185
  }
186
+
174
187
  if (copy && Object.prototype.hasOwnProperty.call(copy, this.sigField)) delete copy[this.sigField];
175
188
  return copy;
176
189
  }
177
190
 
178
191
  async signJson(targetOrRoot, path) {
179
192
  let target = path ? this.getByPath(targetOrRoot, path) : targetOrRoot;
193
+
180
194
  if (target == null) {
181
195
  if (path) return false;
182
196
  throw new TypeError("target required");
183
197
  }
198
+
184
199
  if (Array.isArray(target)) {
185
200
  const out = [];
186
201
  for (const item of target) {
@@ -194,15 +209,18 @@ export class dSyncSign {
194
209
  }
195
210
  const payload = this.cloneWithoutSig(item);
196
211
  const s = await this.signData(payload);
212
+
197
213
  item[this.sigField] = s;
198
214
  out.push(s);
199
215
  }
200
216
  return out;
201
217
  }
218
+
202
219
  if (typeof target === "object") {
203
220
  if (Object.prototype.hasOwnProperty.call(target, this.sigField)) return target[this.sigField];
204
221
  const payload = this.cloneWithoutSig(target);
205
222
  const s = await this.signData(payload);
223
+
206
224
  target[this.sigField] = s;
207
225
  return s;
208
226
  }
@@ -211,28 +229,35 @@ export class dSyncSign {
211
229
 
212
230
  async verifyJson(targetOrRoot, publicKeyOrGetter, path) {
213
231
  let target = path ? this.getByPath(targetOrRoot, path) : targetOrRoot;
232
+
214
233
  if (target == null) {
215
234
  if (path) return false;
216
235
  throw new TypeError("target required");
217
236
  }
237
+
218
238
  if (Array.isArray(target)) {
219
239
  const out = [];
240
+
220
241
  for (const item of target) {
221
242
  if (item == null || typeof item !== "object") {
222
243
  out.push(false);
223
244
  continue;
224
245
  }
246
+
225
247
  if (!Object.prototype.hasOwnProperty.call(item, this.sigField)) {
226
248
  out.push(false);
227
249
  continue;
228
250
  }
251
+
229
252
  const signature = item[this.sigField];
230
253
  let pub = publicKeyOrGetter;
254
+
231
255
  if (typeof publicKeyOrGetter === "function") pub = await publicKeyOrGetter(item, targetOrRoot);
232
256
  if (!pub) {
233
257
  out.push(false);
234
258
  continue;
235
259
  }
260
+
236
261
  const payload = this.cloneWithoutSig(item);
237
262
  out.push(Boolean(this.verifyData(payload, signature, pub)));
238
263
  }
@@ -240,10 +265,13 @@ export class dSyncSign {
240
265
  }
241
266
  if (typeof target === "object") {
242
267
  if (!Object.prototype.hasOwnProperty.call(target, this.sigField)) return false;
268
+
243
269
  const signature = target[this.sigField];
244
270
  let pub = publicKeyOrGetter;
271
+
245
272
  if (typeof publicKeyOrGetter === "function") pub = await publicKeyOrGetter(target, targetOrRoot);
246
273
  if (!pub) return false;
274
+
247
275
  const payload = this.cloneWithoutSig(target);
248
276
  return Boolean(this.verifyData(payload, signature, pub));
249
277
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hackthedev/dsync-sign",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "",
5
5
  "main": "index.mjs",
6
6
  "type": "module",