@freesignal/protocol 0.4.6 → 0.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.
@@ -51,8 +51,6 @@ export declare class KeySession {
51
51
  id?: string;
52
52
  secretKey?: Uint8Array;
53
53
  remoteKey?: Uint8Array;
54
- headerKey?: Uint8Array;
55
- nextHeaderKey?: Uint8Array;
56
54
  rootKey?: Uint8Array;
57
55
  });
58
56
  private getChain;
@@ -29,6 +29,7 @@ const utils_1 = require("@freesignal/utils");
29
29
  * Used for forward-secure encryption and decryption of messages.
30
30
  */
31
31
  class KeySession {
32
+ //headerKey?: Uint8Array, nextHeaderKey?: Uint8Array,
32
33
  constructor(opts = {}) {
33
34
  var _a;
34
35
  this.previousKeys = new KeyMap();
@@ -36,10 +37,10 @@ class KeySession {
36
37
  this.keyPair = crypto_1.default.ECDH.keyPair(opts.secretKey);
37
38
  if (opts.rootKey)
38
39
  this.rootKey = opts.rootKey;
39
- if (opts.nextHeaderKey)
40
- this.nextHeaderKey = opts.nextHeaderKey;
40
+ //if (opts.nextHeaderKey)
41
+ // this.nextHeaderKey = opts.nextHeaderKey;
41
42
  if (opts.remoteKey) {
42
- this.sendingChain = this.getChain(opts.remoteKey, opts.headerKey);
43
+ this.sendingChain = this.getChain(opts.remoteKey); //, opts.headerKey);
43
44
  }
44
45
  }
45
46
  getChain(remoteKey, headerKey, previousCount) {
@@ -51,10 +52,10 @@ class KeySession {
51
52
  return new KeyChain(this.publicKey, remoteKey, hashkey.subarray(KeySession.keyLength, KeySession.keyLength * 2), hashkey.subarray(KeySession.keyLength * 2), headerKey, previousCount);
52
53
  }
53
54
  getHeaderKeys() {
54
- var _a, _b, _c;
55
+ var _a, _b, _c, _d, _e;
55
56
  return {
56
57
  sending: (_a = this.sendingChain) === null || _a === void 0 ? void 0 : _a.headerKey,
57
- receiving: (_b = this.nextHeaderKey) !== null && _b !== void 0 ? _b : (_c = this.receivingChain) === null || _c === void 0 ? void 0 : _c.headerKey
58
+ receiving: (_e = ((_c = (_b = this.receivingChain) === null || _b === void 0 ? void 0 : _b.headerKey) !== null && _c !== void 0 ? _c : (_d = this.receivingChain) === null || _d === void 0 ? void 0 : _d.nextHeaderKey)) !== null && _e !== void 0 ? _e : this.nextHeaderKey
58
59
  };
59
60
  }
60
61
  getSendingKey() {
package/dist/node.d.ts CHANGED
@@ -17,7 +17,7 @@
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
19
  import { Database, LocalStorage, Crypto, KeyExchangeDataBundle, KeyExchangeData } from "@freesignal/interfaces";
20
- import { Datagram, DatagramHeader, DiscoverType, IdentityKey, PrivateIdentityKey, Protocols, UserId } from "./types";
20
+ import { Datagram, DatagramHeader, IdentityKey, PrivateIdentityKey, Protocols, UserId } from "./types";
21
21
  import { KeyExchange } from "./x3dh";
22
22
  import { ExportedKeySession, KeySession } from "./double-ratchet";
23
23
  export declare class BootstrapRequest {
@@ -65,7 +65,7 @@ export declare class FreeSignalNode {
65
65
  open(datagram: Datagram | Uint8Array): Promise<{
66
66
  header: DatagramHeader;
67
67
  payload?: Uint8Array;
68
- discoverType?: DiscoverType;
68
+ datagram?: Datagram;
69
69
  }>;
70
70
  }
71
71
  declare class SessionMap implements LocalStorage<string, KeySession> {
package/dist/node.js CHANGED
@@ -168,6 +168,7 @@ class FreeSignalNode {
168
168
  */
169
169
  open(datagram) {
170
170
  return __awaiter(this, void 0, void 0, function* () {
171
+ var _a;
171
172
  if (datagram instanceof Uint8Array)
172
173
  datagram = types_1.Datagram.from(datagram);
173
174
  let out = {
@@ -218,15 +219,12 @@ class FreeSignalNode {
218
219
  };
219
220
  }
220
221
  const response = { type: types_1.DiscoverType.RESPONSE, discoverId: message.discoverId, data };
221
- out.payload = (yield this.encrypt(datagram.sender, types_1.Protocols.DISCOVER, (0, utils_1.encodeData)(response))).toBytes();
222
- out.discoverType = types_1.DiscoverType.REQUEST;
222
+ out.datagram = yield this.encrypt(datagram.sender, types_1.Protocols.DISCOVER, (0, utils_1.encodeData)(response));
223
223
  }
224
224
  else if (message.type === types_1.DiscoverType.RESPONSE && this.discovers.has(message.discoverId)) {
225
225
  this.discovers.delete(message.discoverId);
226
- if (message.data) {
227
- out.payload = (0, utils_1.encodeData)(message.data);
228
- out.discoverType = types_1.DiscoverType.RESPONSE;
229
- }
226
+ if (message.data)
227
+ out.datagram = yield this.packHandshake(message.data);
230
228
  }
231
229
  return out;
232
230
  case types_1.Protocols.BOOTSTRAP:
@@ -239,12 +237,9 @@ class FreeSignalNode {
239
237
  this.onRequest(request);
240
238
  }
241
239
  ;
242
- const request = yield this.bootstraps.get(datagram.sender);
243
- if (request) {
244
- const data = yield request.get();
245
- if (data)
246
- out.payload = (0, utils_1.encodeData)(data);
247
- }
240
+ const bootstrap = yield ((_a = (yield this.bootstraps.get(datagram.sender))) === null || _a === void 0 ? void 0 : _a.get());
241
+ if (bootstrap)
242
+ out.datagram = yield this.packHandshake(bootstrap);
248
243
  return out;
249
244
  default:
250
245
  throw new Error("Invalid protocol");
package/dist/test.js CHANGED
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ const utils_1 = require("@freesignal/utils");
12
13
  const _1 = require(".");
13
14
  console.log("FreeSignal protocol test");
14
15
  const bob = (0, _1.createNode)({ keyExchange: new _1.AsyncMap(), sessions: new _1.AsyncMap(), users: new _1.AsyncMap(), bundles: new _1.AsyncMap(), bootstraps: new _1.AsyncMap() });
@@ -16,22 +17,27 @@ const alice = (0, _1.createNode)({ keyExchange: new _1.AsyncMap(), sessions: new
16
17
  setImmediate(() => __awaiter(void 0, void 0, void 0, function* () {
17
18
  const bobBootstrap = yield bob.packBootstrap(alice.userId);
18
19
  alice.onRequest = (request) => { request.accept(); };
19
- yield alice.open(bobBootstrap);
20
+ const test = (yield alice.open(bobBootstrap)).datagram;
21
+ console.log("Valid bootstrap: ", !!test);
20
22
  const bobRequest = yield alice.getRequest(bob.userId.toString());
21
23
  if (!bobRequest)
22
24
  throw new Error("Bootstrap Failed");
23
25
  const aliceHandshake = yield alice.packHandshake(bobRequest);
24
26
  yield bob.open(aliceHandshake);
25
27
  const first = (yield bob.packData(alice.userId, "Hi Alice!")).toBytes();
26
- console.log("Bob: ", (yield alice.open(first)).payload);
28
+ console.log("Bob: ", (0, utils_1.decodeData)((yield alice.open(first)).payload));
27
29
  const second = yield alice.packData(bob.userId, "Hi Bob!");
28
- console.log("Alice: ", (yield bob.open(second)).payload);
30
+ console.log("Alice: ", (0, utils_1.decodeData)((yield bob.open(second)).payload));
29
31
  const third = yield Promise.all(["How are you?", "How are this days?", "For me it's a good time"].map(msg => bob.packData(alice.userId, msg)));
30
32
  third.forEach((data) => __awaiter(void 0, void 0, void 0, function* () {
31
- console.log("Bob: ", (yield alice.open(data)).payload);
33
+ console.log("Bob: ", (0, utils_1.decodeData)((yield alice.open(data)).payload));
32
34
  }));
33
35
  const fourth = yield alice.packData(bob.userId, "Not so bad my man");
34
- console.log("Alice: ", (yield bob.open(fourth)).payload);
36
+ console.log("Alice: ", (0, utils_1.decodeData)((yield bob.open(fourth)).payload));
37
+ const fifth = yield Promise.all(["I'm thinking...", "His this secure?"].map(msg => bob.packData(alice.userId, msg)));
38
+ fifth.forEach((data) => __awaiter(void 0, void 0, void 0, function* () {
39
+ console.log("Bob: ", (0, utils_1.decodeData)((yield alice.open(data)).payload));
40
+ }));
35
41
  //const testone = await Promise.all(Array(400).fill(0).map(() => alice.packData(bob.userId, decodeBase64(crypto.randomBytes(64)))));
36
42
  //console.log(((await bob.open(testone[350])).payload));
37
43
  }));
package/dist/types.d.ts CHANGED
@@ -17,7 +17,7 @@
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
19
  import { LocalStorage, Encodable, KeyExchangeData } from "@freesignal/interfaces";
20
- import { KeySession } from "./double-ratchet";
20
+ import { EncryptionKeys, KeySession } from "./double-ratchet";
21
21
  export declare function encryptData(session: KeySession, data: Uint8Array): EncryptedData;
22
22
  export declare function decryptData(session: KeySession, encryptedData: Uint8Array): Uint8Array;
23
23
  export declare class UserId implements Encodable {
@@ -130,67 +130,41 @@ export declare class Datagram implements Encodable, DatagramHeader {
130
130
  static verify(datagram: Datagram, publicKey: Uint8Array): boolean;
131
131
  static from(data: Uint8Array | Datagram | string): Datagram;
132
132
  }
133
- /**
134
- * Interface representing an encrypted payload.
135
- * Provides metadata and de/serialization methods.
136
- */
137
- export interface EncryptedData extends Encodable {
138
- /**
139
- * The length of the payload.
140
- */
141
- readonly length: number;
142
- /**
143
- * Version of the payload.
144
- */
145
- readonly version: number;
146
- /**
147
- * The current message count of the sending chain.
148
- */
133
+ export declare class EncryptionHeader implements EncryptionKeys, Encodable {
134
+ readonly nonce: Uint8Array;
135
+ static readonly keyLength: number;
136
+ static readonly nonceLength: number;
137
+ static readonly countLength = 2;
149
138
  readonly count: number;
150
- /**
151
- * The count of the previous sending chain.
152
- */
153
139
  readonly previous: number;
154
- /**
155
- * The sender's public key used for this message.
156
- */
157
140
  readonly publicKey: Uint8Array;
158
- /**
159
- * The nonce used during encryption.
160
- */
161
- readonly nonce: Uint8Array;
162
- /**
163
- * The encrypted message content.
164
- */
165
- readonly ciphertext: Uint8Array;
166
- /**
167
- * Serializes the payload into a Uint8Array for transport.
168
- */
141
+ constructor(keys: EncryptionKeys, nonce: Uint8Array);
169
142
  toBytes(): Uint8Array;
170
- /**
171
- * Returns the payload as a Base64 string.
172
- */
173
- toString(): string;
174
- /**
175
- * Returns the decoded object as a JSON string.
176
- */
177
143
  toJSON(): {
178
- version: number;
179
144
  count: number;
180
145
  previous: number;
181
146
  publicKey: string;
182
- nonce: string;
183
- ciphertext: string;
184
147
  };
148
+ static from(data: Uint8Array | EncryptionHeader): EncryptionHeader;
185
149
  }
186
- export declare namespace EncryptedData {
187
- /**
188
- * Static factory method that constructs an `EncryptedPayload` from a raw Uint8Array.
189
- *
190
- * @param array - A previously serialized encrypted payload.
191
- * @returns An instance of `EncryptedPayload`.
192
- */
193
- function from(array: Uint8Array | EncryptedData): EncryptedData;
150
+ export declare class EncryptedData implements Encodable {
151
+ readonly header: Uint8Array;
152
+ readonly nonce: Uint8Array;
153
+ readonly payload: Uint8Array;
154
+ static readonly version = 1;
155
+ static readonly nonceLength: number;
156
+ private _version;
157
+ constructor(header: Uint8Array, nonce: Uint8Array, payload: Uint8Array);
158
+ get version(): number;
159
+ get length(): number;
160
+ toBytes(): Uint8Array;
161
+ toJSON(): {
162
+ version: number;
163
+ header: string;
164
+ nonce: string;
165
+ payload: string;
166
+ };
167
+ static from(data: Uint8Array | EncryptedData): EncryptedData;
194
168
  }
195
169
  export declare class AsyncMap<K, V> implements LocalStorage<K, V> {
196
170
  private readonly map;
package/dist/types.js CHANGED
@@ -30,26 +30,41 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
30
30
  return (mod && mod.__esModule) ? mod : { "default": mod };
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.AsyncMap = exports.EncryptedData = exports.Datagram = exports.DatagramHeader = exports.Protocols = exports.DiscoverType = exports.PrivateIdentityKey = exports.IdentityKey = exports.UserId = void 0;
33
+ exports.AsyncMap = exports.EncryptedData = exports.EncryptionHeader = exports.Datagram = exports.DatagramHeader = exports.Protocols = exports.DiscoverType = exports.PrivateIdentityKey = exports.IdentityKey = exports.UserId = void 0;
34
34
  exports.encryptData = encryptData;
35
35
  exports.decryptData = decryptData;
36
36
  const utils_1 = require("@freesignal/utils");
37
37
  const crypto_1 = __importDefault(require("@freesignal/crypto"));
38
- const double_ratchet_1 = require("./double-ratchet");
39
38
  function encryptData(session, data) {
39
+ //console.log(session.id, ' Sending: ', decodeBase64(session.getHeaderKeys().sending ?? new Uint8Array()));
40
40
  const key = session.getSendingKey();
41
41
  if (!key)
42
42
  throw new Error("Error generating key");
43
- const nonce = crypto_1.default.randomBytes(EncryptedDataConstructor.nonceLength);
43
+ const nonce = crypto_1.default.randomBytes(EncryptionHeader.nonceLength);
44
44
  const ciphertext = crypto_1.default.box.encrypt(data, nonce, key.secretKey);
45
- return new EncryptedDataConstructor(key.count, key.previous, key.publicKey, nonce, ciphertext);
45
+ const headerKey = session.getHeaderKeys().sending;
46
+ let header = new EncryptionHeader(key, nonce).toBytes();
47
+ const headerNonce = crypto_1.default.randomBytes(EncryptionHeader.nonceLength);
48
+ if (headerKey)
49
+ header = crypto_1.default.box.encrypt(header, headerNonce, headerKey);
50
+ const test = new EncryptedData(header, headerNonce, ciphertext);
51
+ return test;
46
52
  }
47
53
  function decryptData(session, encryptedData) {
54
+ //console.log(session.id, ' Receiving: ', decodeBase64(session.getHeaderKeys().receiving ?? new Uint8Array()));
48
55
  const encrypted = EncryptedData.from(encryptedData);
49
- const key = session.getReceivingKey(encrypted);
56
+ const headerKey = session.getHeaderKeys().receiving;
57
+ let headerData = encrypted.header;
58
+ if (headerKey) {
59
+ headerData = crypto_1.default.box.decrypt(headerData, encrypted.nonce, headerKey);
60
+ if (!headerData)
61
+ throw new Error("Error calculating header");
62
+ }
63
+ const header = EncryptionHeader.from(headerData);
64
+ const key = session.getReceivingKey(header);
50
65
  if (!key)
51
66
  throw new Error("Error calculating key");
52
- const decrypted = crypto_1.default.box.decrypt(encrypted.ciphertext, encrypted.nonce, key);
67
+ const decrypted = crypto_1.default.box.decrypt(encrypted.payload, header.nonce, key);
53
68
  if (!decrypted)
54
69
  throw new Error("Error decrypting data");
55
70
  return decrypted;
@@ -330,10 +345,10 @@ class Datagram {
330
345
  }
331
346
  else if (data instanceof Datagram) {
332
347
  const datagram = new Datagram(data.sender, data.receiver, data.protocol, data.payload);
333
- datagram._id = datagram.id;
334
- datagram._version = datagram.version;
335
- datagram._createdAt = datagram._createdAt;
336
- datagram._signature = datagram._signature;
348
+ datagram._id = data.id;
349
+ datagram._version = data.version;
350
+ datagram._createdAt = data._createdAt;
351
+ datagram._signature = data._signature;
337
352
  return datagram;
338
353
  }
339
354
  else
@@ -343,91 +358,73 @@ class Datagram {
343
358
  exports.Datagram = Datagram;
344
359
  Datagram.version = 1;
345
360
  Datagram.headerOffset = 26 + crypto_1.default.EdDSA.publicKeyLength * 2;
346
- var EncryptedData;
347
- (function (EncryptedData) {
348
- /**
349
- * Static factory method that constructs an `EncryptedPayload` from a raw Uint8Array.
350
- *
351
- * @param array - A previously serialized encrypted payload.
352
- * @returns An instance of `EncryptedPayload`.
353
- */
354
- function from(array) {
355
- return new EncryptedDataConstructor(array);
356
- }
357
- EncryptedData.from = from;
358
- })(EncryptedData || (exports.EncryptedData = EncryptedData = {}));
359
- class EncryptedDataConstructor {
360
- constructor(...arrays) {
361
- arrays = arrays.filter(value => value !== undefined);
362
- if (arrays[0] instanceof EncryptedDataConstructor) {
363
- this.raw = arrays[0].raw;
364
- return this;
365
- }
366
- if (typeof arrays[0] === 'number')
367
- arrays[0] = (0, utils_1.numberToBytes)(arrays[0], EncryptedDataConstructor.countLength);
368
- if (typeof arrays[1] === 'number')
369
- arrays[1] = (0, utils_1.numberToBytes)(arrays[1], EncryptedDataConstructor.countLength);
370
- if (arrays.length === 6) {
371
- arrays.unshift(typeof arrays[5] === 'number' ? (0, utils_1.numberToBytes)(arrays[5], 1) : arrays[5]);
372
- arrays.pop();
373
- }
374
- else if (arrays.length > 1) {
375
- arrays.unshift((0, utils_1.numberToBytes)(double_ratchet_1.KeySession.version, 1));
376
- }
377
- this.raw = (0, utils_1.concatBytes)(...arrays);
378
- }
379
- get length() { return this.raw.length; }
380
- get version() { return (0, utils_1.bytesToNumber)(new Uint8Array(this.raw.buffer, ...Offsets.version.get)); }
381
- get count() { return (0, utils_1.bytesToNumber)(new Uint8Array(this.raw.buffer, ...Offsets.count.get)); }
382
- get previous() { return (0, utils_1.bytesToNumber)(new Uint8Array(this.raw.buffer, ...Offsets.previous.get)); }
383
- get publicKey() { return new Uint8Array(this.raw.buffer, ...Offsets.publicKey.get); }
384
- get nonce() { return new Uint8Array(this.raw.buffer, ...Offsets.nonce.get); }
385
- get ciphertext() { return new Uint8Array(this.raw.buffer, Offsets.ciphertext.start); }
386
- toBytes() {
387
- return this.raw;
361
+ class EncryptionHeader {
362
+ constructor(keys, nonce) {
363
+ this.nonce = nonce;
364
+ this.count = keys.count;
365
+ this.previous = keys.previous;
366
+ this.publicKey = keys.publicKey;
388
367
  }
389
- toString() {
390
- return (0, utils_1.decodeBase64)(this.raw);
368
+ toBytes() {
369
+ return (0, utils_1.concatBytes)((0, utils_1.numberToBytes)(this.count, EncryptionHeader.countLength), (0, utils_1.numberToBytes)(this.previous, EncryptionHeader.countLength), this.publicKey, this.nonce);
391
370
  }
392
371
  toJSON() {
393
372
  return {
394
- version: this.version,
395
373
  count: this.count,
396
374
  previous: this.previous,
397
- publicKey: (0, utils_1.decodeBase64)(this.publicKey),
398
- nonce: (0, utils_1.decodeBase64)(this.nonce),
399
- ciphertext: (0, utils_1.decodeBase64)(this.ciphertext)
375
+ publicKey: (0, utils_1.decodeBase64)(this.publicKey)
400
376
  };
401
377
  }
378
+ static from(data) {
379
+ if (data instanceof EncryptionHeader)
380
+ data = data.toBytes();
381
+ return new EncryptionHeader({
382
+ count: (0, utils_1.bytesToNumber)(data.subarray(0, EncryptionHeader.countLength)),
383
+ previous: (0, utils_1.bytesToNumber)(data.subarray(EncryptionHeader.countLength, EncryptionHeader.countLength * 2)),
384
+ publicKey: data.subarray(EncryptionHeader.countLength * 2, EncryptionHeader.countLength * 2 + EncryptionHeader.keyLength)
385
+ }, data.subarray(EncryptionHeader.countLength * 2 + EncryptionHeader.keyLength, EncryptionHeader.countLength * 2 + EncryptionHeader.keyLength + EncryptedData.nonceLength));
386
+ }
402
387
  }
403
- EncryptedDataConstructor.secretKeyLength = crypto_1.default.ECDH.secretKeyLength;
404
- EncryptedDataConstructor.publicKeyLength = crypto_1.default.ECDH.publicKeyLength;
405
- EncryptedDataConstructor.keyLength = crypto_1.default.box.keyLength;
406
- EncryptedDataConstructor.nonceLength = crypto_1.default.box.nonceLength;
407
- EncryptedDataConstructor.countLength = 2;
408
- class Offsets {
409
- static set(start, length) {
410
- class Offset {
411
- constructor(start, length) {
412
- this.start = start;
413
- this.length = length;
414
- if (typeof length === 'number')
415
- this.end = start + length;
416
- }
417
- get get() {
418
- return [this.start, this.length];
419
- }
420
- }
421
- return new Offset(start, length);
388
+ exports.EncryptionHeader = EncryptionHeader;
389
+ EncryptionHeader.keyLength = crypto_1.default.box.keyLength;
390
+ EncryptionHeader.nonceLength = crypto_1.default.box.nonceLength;
391
+ EncryptionHeader.countLength = 2;
392
+ class EncryptedData {
393
+ constructor(header, nonce, payload) {
394
+ this.header = header;
395
+ this.nonce = nonce;
396
+ this.payload = payload;
397
+ this._version = EncryptedData.version;
398
+ }
399
+ get version() {
400
+ return this._version;
401
+ }
402
+ get length() {
403
+ return this.toBytes().length;
404
+ }
405
+ toBytes() {
406
+ return (0, utils_1.concatBytes)((0, utils_1.numberToBytes)(this._version, 1), (0, utils_1.numberToBytes)(this.header.length, 3), this.header, this.nonce, this.payload);
407
+ }
408
+ toJSON() {
409
+ return {
410
+ version: this._version,
411
+ header: (0, utils_1.decodeBase64)(this.header),
412
+ nonce: (0, utils_1.decodeBase64)(this.nonce),
413
+ payload: (0, utils_1.decodeBase64)(this.payload)
414
+ };
415
+ }
416
+ static from(data) {
417
+ if (data instanceof EncryptedData)
418
+ data = data.toBytes();
419
+ const headerLength = (0, utils_1.bytesToNumber)(data.subarray(1, 4));
420
+ const obj = new EncryptedData(data.subarray(4, 4 + headerLength), data.subarray(4 + headerLength, 4 + headerLength + this.nonceLength), data.subarray(4 + headerLength + this.nonceLength));
421
+ obj._version = (0, utils_1.bytesToNumber)(data.subarray(0, 1));
422
+ return obj;
422
423
  }
423
424
  }
424
- Offsets.checksum = Offsets.set(0, 0);
425
- Offsets.version = Offsets.set(Offsets.checksum.end, 1);
426
- Offsets.count = Offsets.set(Offsets.version.end, EncryptedDataConstructor.countLength);
427
- Offsets.previous = Offsets.set(Offsets.count.end, EncryptedDataConstructor.countLength);
428
- Offsets.publicKey = Offsets.set(Offsets.previous.end, EncryptedDataConstructor.publicKeyLength);
429
- Offsets.nonce = Offsets.set(Offsets.publicKey.end, EncryptedDataConstructor.nonceLength);
430
- Offsets.ciphertext = Offsets.set(Offsets.nonce.end, undefined);
425
+ exports.EncryptedData = EncryptedData;
426
+ EncryptedData.version = 1;
427
+ EncryptedData.nonceLength = crypto_1.default.box.nonceLength;
431
428
  class AsyncMap {
432
429
  constructor(iterable) {
433
430
  this.map = new Map(iterable);
package/dist/x3dh.js CHANGED
@@ -92,13 +92,14 @@ class KeyExchange {
92
92
  const onetimePreKey = message.onetimePreKey ? (0, utils_1.encodeBase64)(message.onetimePreKey) : undefined;
93
93
  const signedPreKeyHash = crypto_1.default.hash(signedPreKey);
94
94
  const onetimePreKeyHash = onetimePreKey ? crypto_1.default.hash(onetimePreKey) : new Uint8Array();
95
- const rootKey = crypto_1.default.hkdf(new Uint8Array([
95
+ const derivedKey = crypto_1.default.hkdf(new Uint8Array([
96
96
  ...crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, signedPreKey),
97
97
  ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, identityKey.exchangeKey),
98
98
  ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, signedPreKey),
99
99
  ...onetimePreKey ? crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, onetimePreKey) : new Uint8Array()
100
- ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength);
101
- const session = new double_ratchet_1.KeySession({ remoteKey: identityKey.exchangeKey, rootKey });
100
+ ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength * 2);
101
+ //, headerKey: derivedKey.subarray(KeySession.keyLength)
102
+ const session = new double_ratchet_1.KeySession({ remoteKey: identityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength) });
102
103
  const encrypted = (0, types_1.encryptData)(session, (0, utils_1.concatBytes)(crypto_1.default.hash(this.identityKey.toBytes()), crypto_1.default.hash(identityKey.toBytes()), associatedData !== null && associatedData !== void 0 ? associatedData : new Uint8Array()));
103
104
  if (!encrypted)
104
105
  throw new Error("Decryption error");
@@ -127,13 +128,14 @@ class KeyExchange {
127
128
  if (!this.storage.delete(hash))
128
129
  throw new Error("Bundle store deleting error");
129
130
  const ephemeralKey = (0, utils_1.encodeBase64)(message.ephemeralKey);
130
- const rootKey = crypto_1.default.hkdf(new Uint8Array([
131
+ const derivedKey = crypto_1.default.hkdf(new Uint8Array([
131
132
  ...crypto_1.default.ECDH.scalarMult(signedPreKey.secretKey, identityKey.exchangeKey),
132
133
  ...crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, ephemeralKey),
133
134
  ...crypto_1.default.ECDH.scalarMult(signedPreKey.secretKey, ephemeralKey),
134
135
  ...onetimePreKey ? crypto_1.default.ECDH.scalarMult(onetimePreKey.secretKey, ephemeralKey) : new Uint8Array()
135
- ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength);
136
- const session = new double_ratchet_1.KeySession({ secretKey: this.privateIdentityKey.exchangeKey, rootKey });
136
+ ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength * 2);
137
+ //, nextHeaderKey: derivedKey.subarray(KeySession.keyLength)
138
+ const session = new double_ratchet_1.KeySession({ secretKey: this.privateIdentityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength) });
137
139
  const data = (0, types_1.decryptData)(session, (0, utils_1.encodeBase64)(message.associatedData));
138
140
  if (!data)
139
141
  throw new Error("Error decrypting ACK message");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freesignal/protocol",
3
- "version": "0.4.6",
3
+ "version": "0.5.0",
4
4
  "description": "Signal Protocol implementation in javascript",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "author": "Christian Braghette",