spd-lib 1.1.7 → 1.1.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.
Files changed (2) hide show
  1. package/index.js +22 -85
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -11,27 +11,11 @@ class SPD {
11
11
  this.keyPair; // Generate a key pair for encryption/decryption
12
12
  this.userKey;
13
13
  this.salt;
14
- this.signingKeyPair;
15
14
  this.init();
16
15
  }
17
16
  async init() {
18
17
  await sodium.ready;
19
18
  this.keyPair = sodium.crypto_box_keypair()
20
- this.signingKeyPair = sodium.crypto_sign_keypair();
21
- }
22
- static async deriveSigningKeys(passcode, salt) {
23
- if (!passcode || typeof passcode !== 'string' || passcode.length < 8 ||
24
- !salt || !(salt instanceof Buffer) || salt.length !== 16) {
25
- throw new Error('Invalid passcode or salt.');
26
- }
27
-
28
- const { pbk } = await SPD.derivePBK(passcode, salt);
29
- await sodium.ready;
30
- // Derive separate keys for signing to avoid key reuse
31
- const signingSeed = pbk.slice(0, sodium.crypto_sign_SEEDBYTES);
32
- const signingKeyPair = sodium.crypto_sign_seed_keypair(signingSeed);
33
-
34
- return { signingKeyPair };
35
19
  }
36
20
  async setPassKey(passcode){
37
21
  await sodium.ready;
@@ -40,8 +24,6 @@ class SPD {
40
24
  const userKey = pqcKey.publicKey;
41
25
  this.userKey = userKey;
42
26
  this.salt = salt;
43
- const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
44
- this.signingKeyPair = derivedKeys.signingKeyPair;
45
27
  }
46
28
 
47
29
  async addData(name, data) {
@@ -50,12 +32,13 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
50
32
  const dmap = await this.CITS(data)
51
33
  await sodium.ready;
52
34
  const dat = Buffer.from(dmap[0]);
53
- const compressedData = zlib.deflateSync(dat);
35
+ const compressedData = zlib.deflateSync(dat,{
36
+ level:9
37
+ });
54
38
  const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);
55
39
  const encryptedData = sodium.crypto_secretbox_easy(compressedData, nonce, this.userKey);
56
40
  const hash = crypto.createHash('sha256').update(encryptedData).digest('hex');
57
- const signature = sodium.crypto_sign_detached(encryptedData, this.signingKeyPair.privateKey);
58
- this.data.push({ dataName: name, nonce: Array.from(nonce), data: Array.from(encryptedData),signature:Array.from(signature), hash, dataType: dmap[1] });
41
+ this.data.push({ dataName: name, nonce: Array.from(nonce), data: Array.from(encryptedData), hash, dataType: dmap[1] });
59
42
  }
60
43
 
61
44
  saveToFile(outputPath) {
@@ -63,8 +46,10 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
63
46
  throw new Error('Invalid output path or salt.');
64
47
  }
65
48
 
66
- const spdData = JSON.stringify({ data: this.data, salt: Array.from(this.salt),signingPublicKey:Array.from(this.signingKeyPair.publicKey) });
67
- const compressedSpdData = zlib.deflateSync(spdData);
49
+ const spdData = JSON.stringify({ data: this.data, salt: Array.from(this.salt) });
50
+ const compressedSpdData = zlib.deflateSync(spdData,{
51
+ level:9
52
+ });
68
53
  fs.writeFileSync(outputPath, compressedSpdData, { mode: 0o600 });
69
54
  }
70
55
 
@@ -78,8 +63,8 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
78
63
 
79
64
  await sodium.ready;
80
65
  const compressedSpdData = fs.readFileSync(spdPath);
81
- const spdData = zlib.inflateSync(compressedSpdData).toString('utf8');
82
- const { data, salt, signingPublicKey } = JSON.parse(spdData);
66
+ const spdData = zlib.inflateSync(compressedSpdData,{level:9}).toString('utf8');
67
+ const { data, salt } = JSON.parse(spdData);
83
68
 
84
69
  const { pqcKey } = await new SPD().convertPasscodeToPQCKeySalted(passcode, new Uint8Array(salt));
85
70
  const pbk = pqcKey.publicKey;
@@ -88,34 +73,19 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
88
73
  spd.keyPair = {
89
74
  publicKey: pbk.publicKey
90
75
  };
91
-
92
- spd.signingKeyPair = { publicKey: Uint8Array.from(signingPublicKey) };
93
76
  spd.data = data.map(dat => ({
94
77
  dataName: dat.dataName,
95
78
  nonce: Buffer.from(dat.nonce),
96
79
  data: Buffer.from(dat.data),
97
- signature: Buffer.from(dat.signature),
98
80
  hash: dat.hash,
99
81
  dataType: dat.dataType
100
82
  }));
101
83
  spd.data.forEach(dat => {
102
- const encryptedBuffer = Buffer.from(dat.data);
103
- const signatureBuffer = Buffer.from(dat.signature);
104
- const signingPublicKeyBuffer = Uint8Array.from(signingPublicKey);
105
-
106
- const isValid = sodium.crypto_sign_verify_detached(signatureBuffer, encryptedBuffer, signingPublicKeyBuffer);
107
- if (!isValid) {
108
- rej(new Error(`Signature verification failed for ${dat.dataName}`));
109
- return;
110
- }
111
-
112
- const calculatedHash = crypto.createHash('sha256').update(encryptedBuffer).digest('hex');
84
+ const calculatedHash = crypto.createHash('sha256').update(Buffer.from(dat.data)).digest('hex');
113
85
  if (calculatedHash !== dat.hash) {
114
86
  rej(new Error(`Data integrity check failed for ${dat.dataName}`));
115
- return;
116
87
  }
117
88
  });
118
-
119
89
  res(spd);
120
90
  }catch{
121
91
  rej()
@@ -130,30 +100,10 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
130
100
  let extractedFiles = {};
131
101
  this.data.forEach(async dat => {
132
102
  try{
133
- const calculatedHash = crypto.createHash('sha256').update(dat.data).digest('hex');
134
- if (calculatedHash !== dat.hash) {
135
- throw new Error(`Hash mismatch for ${dat.dataName}`);
136
- }
137
-
138
- // Verify signature
139
- const isValid = sodium.crypto_sign_verify_detached(
140
- Buffer.from(dat.signature),
141
- Buffer.from(dat.data),
142
- this.signingKeyPair.publicKey
143
- );
144
- if (!isValid) {
145
- throw new Error(`Signature verification failed for ${dat.dataName}`);
146
- }
147
-
148
- // Decrypt data
149
- const decryptedData = sodium.crypto_secretbox_open_easy(
150
- Buffer.from(dat.data),
151
- Buffer.from(dat.nonce),
152
- this.userKey
153
- );
154
- const decompressedData = zlib.inflateSync(decryptedData);
155
- const dt = decompressedData.toString('utf8');
156
- extractedFiles[dat.dataName] = await this.CSTI(dt, dat.dataType);
103
+ const decryptedData = sodium.crypto_secretbox_open_easy(dat.data, dat.nonce, this.userKey);
104
+ const decompressedData = zlib.inflateSync(decryptedData,{level:9});
105
+ const dt = decompressedData.toString('utf8');
106
+ extractedFiles[dat.dataName] = await this.CSTI(dt, dat.dataType);
157
107
  }catch{
158
108
  rej()
159
109
  }
@@ -185,7 +135,7 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
185
135
 
186
136
  saveData() {
187
137
  const spdData = JSON.stringify({ data: this.data, salt: Array.from(this.salt) });
188
- const compressedSpdData = zlib.deflateSync(spdData);
138
+ const compressedSpdData = zlib.deflateSync(spdData,{level:9});
189
139
  return compressedSpdData;
190
140
  }
191
141
 
@@ -198,17 +148,15 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
198
148
 
199
149
  await sodium.ready;
200
150
  const spdDataBuffer = Buffer.from(spdData, 'base64');
201
- const spdData2 = zlib.inflateSync(spdDataBuffer).toString('utf8');
202
- const { data, salt, signingPublicKey } = JSON.parse(spdData2);
151
+ const spdData2 = zlib.inflateSync(spdDataBuffer,{level:9}).toString('utf8');
152
+ const { data, salt } = JSON.parse(spdData2);
203
153
  const { pqcKey } = await new SPD().convertPasscodeToPQCKeySalted(passcode, new Uint8Array(salt));
204
-
205
154
  const pbk = pqcKey.publicKey;
206
155
  const spd = new SPD();
207
156
  spd.userKey = pbk;
208
157
  spd.keyPair = {
209
158
  publicKey: pbk.publicKey
210
159
  };
211
- spd.signingKeyPair = { publicKey: Uint8Array.from(signingPublicKey) };
212
160
  spd.data = data.map(dat => ({
213
161
  dataName: dat.dataName,
214
162
  nonce: Buffer.from(dat.nonce),
@@ -217,21 +165,10 @@ const derivedKeys = await SPD.deriveSigningKeys(passcode, salt);
217
165
  dataType: dat.dataType
218
166
  }));
219
167
  spd.data.forEach(dat => {
220
- const encryptedBuffer = Buffer.from(dat.data);
221
- const signatureBuffer = Buffer.from(dat.signature);
222
- const signingPublicKeyBuffer = Uint8Array.from(signingPublicKey);
223
-
224
- const isValid = sodium.crypto_sign_verify_detached(signatureBuffer, encryptedBuffer, signingPublicKeyBuffer);
225
- if (!isValid) {
226
- rej(new Error(`Signature verification failed for ${dat.dataName}`));
227
- return;
228
- }
229
-
230
- const calculatedHash = crypto.createHash('sha256').update(encryptedBuffer).digest('hex');
231
- if (calculatedHash !== dat.hash) {
232
- rej(new Error(`Data integrity check failed for ${dat.dataName}`));
233
- return;
234
- }
168
+ const calculatedHash = crypto.createHash('sha256').update(Buffer.from(dat.data)).digest('hex');
169
+ if (calculatedHash !== dat.hash) {
170
+ rej(new Error(`Data integrity check failed for ${dat.dataName}`));
171
+ }
235
172
  });
236
173
  res(spd);
237
174
  }catch{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spd-lib",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "SPD or Secure Packaged Data is a compress PQC protected file format to store sensitive data localy",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -21,6 +21,6 @@
21
21
  "author": "ALS-OPSS",
22
22
  "license": "ISC",
23
23
  "dependencies": {
24
- "libsodium-wrappers": "^0.7.13"
24
+ "libsodium-wrappers": "^0.7.15"
25
25
  }
26
26
  }