dignity.js 0.2.0 → 0.3.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 +22 -16
- package/dist/dignity.cjs.js +45 -6
- package/dist/dignity.cjs.js.map +2 -2
- package/dist/dignity.esm.js +45 -6
- package/dist/dignity.esm.js.map +2 -2
- package/dist/dignity.min.js +5 -5
- package/package.json +2 -2
- package/src/security/message-security-service.js +51 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dignity.js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "P2P object API for decentralized JavaScript applications",
|
|
5
5
|
"main": "dist/dignity.cjs.js",
|
|
6
6
|
"module": "dist/dignity.esm.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"rest",
|
|
40
40
|
"objects"
|
|
41
41
|
],
|
|
42
|
-
"license": "
|
|
42
|
+
"license": "Apache 2.0",
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"esbuild": "^0.28.0",
|
|
45
45
|
"jest": "^29.7.0"
|
|
@@ -12,7 +12,8 @@ const DEFAULT_SECURITY_OPTIONS = {
|
|
|
12
12
|
broadcastPasswords: {},
|
|
13
13
|
resolveBroadcastPassword: null,
|
|
14
14
|
powSteps: 22,
|
|
15
|
-
trustedPeerKeys: {}
|
|
15
|
+
trustedPeerKeys: {},
|
|
16
|
+
kdfIterations: 100000
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
function stableStringify(value) {
|
|
@@ -47,6 +48,37 @@ function utf8ToBytes(value) {
|
|
|
47
48
|
return naclUtil.decodeUTF8(value);
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
async function deriveBroadcastKey(password, salt, iterations) {
|
|
52
|
+
const subtle = globalThis.crypto && globalThis.crypto.subtle;
|
|
53
|
+
|
|
54
|
+
if (subtle) {
|
|
55
|
+
const keyMaterial = await subtle.importKey(
|
|
56
|
+
'raw',
|
|
57
|
+
utf8ToBytes(password),
|
|
58
|
+
'PBKDF2',
|
|
59
|
+
false,
|
|
60
|
+
['deriveBits']
|
|
61
|
+
);
|
|
62
|
+
const bits = await subtle.deriveBits(
|
|
63
|
+
{ name: 'PBKDF2', salt, iterations, hash: 'SHA-256' },
|
|
64
|
+
keyMaterial,
|
|
65
|
+
256
|
|
66
|
+
);
|
|
67
|
+
return new Uint8Array(bits);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const { pbkdf2Sync } = require('crypto');
|
|
72
|
+
return new Uint8Array(pbkdf2Sync(password, Buffer.from(salt), iterations, 32, 'sha256'));
|
|
73
|
+
} catch (_ignored) {
|
|
74
|
+
return hash32(concatBytes(utf8ToBytes(password), salt));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function legacyBroadcastKey(password, salt) {
|
|
79
|
+
return hash32(concatBytes(utf8ToBytes(password), salt));
|
|
80
|
+
}
|
|
81
|
+
|
|
50
82
|
function normalizePeerPublicKey(publicKey) {
|
|
51
83
|
if (!publicKey || typeof publicKey !== 'object') {
|
|
52
84
|
throw new Error('Public key must be an object with signingPublicKey and encryptionPublicKey');
|
|
@@ -240,7 +272,7 @@ class MessageSecurityService {
|
|
|
240
272
|
this.verifySignature(envelope);
|
|
241
273
|
}
|
|
242
274
|
|
|
243
|
-
const payload = this.decryptPayload(envelope);
|
|
275
|
+
const payload = await this.decryptPayload(envelope);
|
|
244
276
|
|
|
245
277
|
return {
|
|
246
278
|
ignored: false,
|
|
@@ -320,7 +352,8 @@ class MessageSecurityService {
|
|
|
320
352
|
const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
|
|
321
353
|
const salt = nacl.randomBytes(16);
|
|
322
354
|
const password = this.resolveBroadcastPassword(scope);
|
|
323
|
-
const
|
|
355
|
+
const iterations = this.options.kdfIterations || DEFAULT_SECURITY_OPTIONS.kdfIterations;
|
|
356
|
+
const key = await deriveBroadcastKey(password, salt, iterations);
|
|
324
357
|
const encrypted = nacl.secretbox(plainText, nonce, key);
|
|
325
358
|
|
|
326
359
|
return {
|
|
@@ -330,12 +363,14 @@ class MessageSecurityService {
|
|
|
330
363
|
mode: 'broadcast',
|
|
331
364
|
scope,
|
|
332
365
|
nonce: naclUtil.encodeBase64(nonce),
|
|
333
|
-
salt: naclUtil.encodeBase64(salt)
|
|
366
|
+
salt: naclUtil.encodeBase64(salt),
|
|
367
|
+
kdf: 'pbkdf2',
|
|
368
|
+
kdfIterations: iterations
|
|
334
369
|
}
|
|
335
370
|
};
|
|
336
371
|
}
|
|
337
372
|
|
|
338
|
-
decryptPayload(envelope) {
|
|
373
|
+
async decryptPayload(envelope) {
|
|
339
374
|
const encryption = envelope.security ? envelope.security.encryption : null;
|
|
340
375
|
|
|
341
376
|
if (!encryption || !encryption.enabled || !this.options.encryptionEnabled) {
|
|
@@ -349,7 +384,15 @@ class MessageSecurityService {
|
|
|
349
384
|
const password = this.resolveBroadcastPassword(scope);
|
|
350
385
|
const salt = naclUtil.decodeBase64(encryption.salt);
|
|
351
386
|
const nonce = naclUtil.decodeBase64(encryption.nonce);
|
|
352
|
-
|
|
387
|
+
|
|
388
|
+
let key;
|
|
389
|
+
if (encryption.kdf === 'pbkdf2') {
|
|
390
|
+
const iterations = encryption.kdfIterations || DEFAULT_SECURITY_OPTIONS.kdfIterations;
|
|
391
|
+
key = await deriveBroadcastKey(password, salt, iterations);
|
|
392
|
+
} else {
|
|
393
|
+
key = legacyBroadcastKey(password, salt);
|
|
394
|
+
}
|
|
395
|
+
|
|
353
396
|
const decrypted = nacl.secretbox.open(encryptedBuffer, nonce, key);
|
|
354
397
|
|
|
355
398
|
if (!decrypted) {
|
|
@@ -470,5 +513,7 @@ class MessageSecurityService {
|
|
|
470
513
|
module.exports = {
|
|
471
514
|
MessageSecurityService,
|
|
472
515
|
stableStringify,
|
|
516
|
+
deriveBroadcastKey,
|
|
517
|
+
legacyBroadcastKey,
|
|
473
518
|
DEFAULT_SECURITY_OPTIONS
|
|
474
519
|
};
|