@freesignal/protocol 0.6.0 → 0.6.1

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.
@@ -42,7 +42,6 @@ export declare class KeySession {
42
42
  static readonly version = 1;
43
43
  static readonly info: string;
44
44
  static readonly maxCount = 65536;
45
- readonly id: string;
46
45
  readonly identityKey: IdentityKey;
47
46
  private keyPair;
48
47
  private rootKey?;
@@ -50,18 +49,14 @@ export declare class KeySession {
50
49
  private receivingChain?;
51
50
  private nextHeaderKey?;
52
51
  private previousKeys;
53
- constructor(identityKey: IdentityKey, opts?: {
54
- id?: string;
52
+ constructor({ identityKey, secretKey, remoteKey, rootKey }: {
53
+ identityKey: IdentityKey;
55
54
  secretKey?: Uint8Array;
56
55
  remoteKey?: Uint8Array;
57
56
  rootKey?: Uint8Array;
58
57
  });
59
58
  get userId(): UserId;
60
59
  private getChain;
61
- getHeaderKeys(): {
62
- readonly sending?: Uint8Array;
63
- readonly receiving?: Uint8Array;
64
- };
65
60
  getSendingKey(): PrivateEncryptionKeys | undefined;
66
61
  getReceivingKey(encryptionKeys: EncryptionKeys): Uint8Array | undefined;
67
62
  /**
@@ -88,8 +83,6 @@ interface ExportedKeyChain {
88
83
  publicKey: string;
89
84
  remoteKey: string;
90
85
  chainKey: string;
91
- nextHeaderKey: string;
92
- headerKey?: string;
93
86
  count: number;
94
87
  previousCount: number;
95
88
  }
@@ -31,38 +31,40 @@ const types_1 = require("./types");
31
31
  */
32
32
  class KeySession {
33
33
  //headerKey?: Uint8Array, nextHeaderKey?: Uint8Array,
34
- constructor(identityKey, opts = {}) {
35
- var _a;
34
+ constructor({ identityKey, secretKey, remoteKey, rootKey }) {
36
35
  this.previousKeys = new KeyMap();
37
36
  this.identityKey = identityKey;
38
- this.id = (_a = opts.id) !== null && _a !== void 0 ? _a : crypto_1.default.UUID.generate().toString();
39
- this.keyPair = crypto_1.default.ECDH.keyPair(opts.secretKey);
40
- if (opts.rootKey)
41
- this.rootKey = opts.rootKey;
37
+ this.keyPair = crypto_1.default.ECDH.keyPair(secretKey);
38
+ if (rootKey)
39
+ this.rootKey = rootKey;
42
40
  //if (opts.nextHeaderKey)
43
41
  // this.nextHeaderKey = opts.nextHeaderKey;
44
- if (opts.remoteKey) {
45
- this.sendingChain = this.getChain(opts.remoteKey); //, opts.headerKey);
42
+ if (remoteKey) {
43
+ this.sendingChain = this.getChain(remoteKey); //, opts.headerKey);
46
44
  }
47
45
  }
48
46
  get userId() {
49
47
  return this.identityKey.userId;
50
48
  }
51
- getChain(remoteKey, headerKey, previousCount) {
49
+ //headerKey?: Uint8Array,
50
+ getChain(remoteKey, previousCount) {
52
51
  const sharedKey = crypto_1.default.ECDH.scalarMult(this.keyPair.secretKey, remoteKey);
53
52
  if (!this.rootKey)
54
53
  this.rootKey = crypto_1.default.hash(sharedKey);
55
54
  const hashkey = crypto_1.default.hkdf(sharedKey, this.rootKey, KeySession.info, KeySession.keyLength * 3);
56
55
  this.rootKey = hashkey.subarray(0, KeySession.keyLength);
57
- return new KeyChain(this.publicKey, remoteKey, hashkey.subarray(KeySession.keyLength, KeySession.keyLength * 2), hashkey.subarray(KeySession.keyLength * 2), headerKey, previousCount);
56
+ //hashkey.subarray(KeySession.keyLength * 2), headerKey,
57
+ return new KeyChain(this.publicKey, remoteKey, hashkey.subarray(KeySession.keyLength, KeySession.keyLength * 2), previousCount);
58
58
  }
59
- getHeaderKeys() {
60
- var _a, _b, _c, _d, _e;
59
+ /*public getHeaderKeys(): {
60
+ readonly sending?: Uint8Array,
61
+ readonly receiving?: Uint8Array
62
+ } {
61
63
  return {
62
- sending: (_a = this.sendingChain) === null || _a === void 0 ? void 0 : _a.headerKey,
63
- 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
64
- };
65
- }
64
+ sending: this.sendingChain?.headerKey,
65
+ receiving: (this.receivingChain?.headerKey ?? this.receivingChain?.nextHeaderKey) ?? this.nextHeaderKey
66
+ }
67
+ }*/
66
68
  getSendingKey() {
67
69
  if (!this.sendingChain)
68
70
  return;
@@ -76,17 +78,19 @@ class KeySession {
76
78
  };
77
79
  }
78
80
  getReceivingKey(encryptionKeys) {
79
- var _a, _b, _c, _d, _e, _f;
81
+ var _a, _b, _c, _d;
80
82
  if (!this.previousKeys.has((0, utils_1.decodeBase64)(encryptionKeys.publicKey) + encryptionKeys.count.toString())) {
81
83
  if (!(0, utils_1.compareBytes)(encryptionKeys.publicKey, (_b = (_a = this.receivingChain) === null || _a === void 0 ? void 0 : _a.remoteKey) !== null && _b !== void 0 ? _b : new Uint8Array())) {
82
84
  while (this.receivingChain && this.receivingChain.count < encryptionKeys.previous) {
83
85
  const key = this.receivingChain.getKey();
84
86
  this.previousKeys.set((0, utils_1.decodeBase64)(this.receivingChain.remoteKey) + this.receivingChain.count.toString(), key);
85
87
  }
86
- this.receivingChain = this.getChain(encryptionKeys.publicKey, (_c = this.nextHeaderKey) !== null && _c !== void 0 ? _c : (_d = this.receivingChain) === null || _d === void 0 ? void 0 : _d.nextHeaderKey);
88
+ //this.nextHeaderKey ?? this.receivingChain?.nextHeaderKey
89
+ this.receivingChain = this.getChain(encryptionKeys.publicKey, (_c = this.receivingChain) === null || _c === void 0 ? void 0 : _c.count);
87
90
  this.nextHeaderKey = undefined;
88
91
  this.keyPair = crypto_1.default.ECDH.keyPair();
89
- this.sendingChain = this.getChain(encryptionKeys.publicKey, (_e = this.sendingChain) === null || _e === void 0 ? void 0 : _e.nextHeaderKey, (_f = this.sendingChain) === null || _f === void 0 ? void 0 : _f.count);
92
+ //this.sendingChain?.nextHeaderKey,
93
+ this.sendingChain = this.getChain(encryptionKeys.publicKey, (_d = this.sendingChain) === null || _d === void 0 ? void 0 : _d.count);
90
94
  }
91
95
  if (!this.receivingChain)
92
96
  throw new Error("Error initializing receivingChain");
@@ -126,7 +130,7 @@ class KeySession {
126
130
  * @returns session with the state parsed.
127
131
  */
128
132
  static from(data) {
129
- const session = new KeySession(types_1.IdentityKey.from(data.identityKey), { secretKey: (0, utils_1.encodeBase64)(data.secretKey), rootKey: data.rootKey ? (0, utils_1.encodeBase64)(data.rootKey) : undefined });
133
+ const session = new KeySession({ identityKey: types_1.IdentityKey.from(data.identityKey), secretKey: (0, utils_1.encodeBase64)(data.secretKey), rootKey: data.rootKey ? (0, utils_1.encodeBase64)(data.rootKey) : undefined });
130
134
  session.sendingChain = data.sendingChain ? KeyChain.from(data.sendingChain) : undefined;
131
135
  session.receivingChain = data.receivingChain ? KeyChain.from(data.receivingChain) : undefined;
132
136
  session.previousKeys = new KeyMap(data.previousKeys);
@@ -139,12 +143,11 @@ KeySession.version = 1;
139
143
  KeySession.info = "/freesignal/double-ratchet/v0." + KeySession.version;
140
144
  KeySession.maxCount = 65536;
141
145
  class KeyChain {
142
- constructor(publicKey, remoteKey, chainKey, nextHeaderKey, headerKey, previousCount = 0) {
146
+ //public readonly nextHeaderKey: Uint8Array, public readonly headerKey?: Uint8Array,
147
+ constructor(publicKey, remoteKey, chainKey, previousCount = 0) {
143
148
  this.publicKey = publicKey;
144
149
  this.remoteKey = remoteKey;
145
150
  this.chainKey = chainKey;
146
- this.nextHeaderKey = nextHeaderKey;
147
- this.headerKey = headerKey;
148
151
  this.previousCount = previousCount;
149
152
  this._count = 0;
150
153
  }
@@ -166,14 +169,15 @@ class KeyChain {
166
169
  publicKey: (0, utils_1.decodeBase64)(this.publicKey),
167
170
  remoteKey: (0, utils_1.decodeBase64)(this.remoteKey),
168
171
  chainKey: (0, utils_1.decodeBase64)(this.chainKey),
169
- nextHeaderKey: (0, utils_1.decodeBase64)(this.nextHeaderKey),
170
- headerKey: this.headerKey ? (0, utils_1.decodeBase64)(this.headerKey) : undefined,
172
+ //nextHeaderKey: decodeBase64(this.nextHeaderKey),
173
+ //headerKey: this.headerKey ? decodeBase64(this.headerKey) : undefined,
171
174
  count: this.count,
172
175
  previousCount: this.previousCount
173
176
  };
174
177
  }
175
178
  static from(obj) {
176
- const chain = new KeyChain((0, utils_1.encodeBase64)(obj.publicKey), (0, utils_1.encodeBase64)(obj.remoteKey), (0, utils_1.encodeBase64)(obj.chainKey), (0, utils_1.encodeBase64)(obj.nextHeaderKey), obj.headerKey ? (0, utils_1.encodeBase64)(obj.headerKey) : undefined, obj.previousCount);
179
+ //encodeBase64(obj.nextHeaderKey), obj.headerKey ? encodeBase64(obj.headerKey) : undefined,
180
+ const chain = new KeyChain((0, utils_1.encodeBase64)(obj.publicKey), (0, utils_1.encodeBase64)(obj.remoteKey), (0, utils_1.encodeBase64)(obj.chainKey), obj.previousCount);
177
181
  chain._count = obj.count;
178
182
  return chain;
179
183
  }
package/dist/node.d.ts CHANGED
@@ -23,11 +23,11 @@ import { ExportedKeySession, KeySession } from "./double-ratchet";
23
23
  export declare class BootstrapRequest {
24
24
  #private;
25
25
  readonly senderId: UserId | string;
26
- private readonly data;
27
- constructor(senderId: UserId | string, data: KeyExchangeData);
26
+ private readonly datagram;
27
+ constructor(senderId: UserId | string, datagram: Datagram);
28
28
  get status(): "pending" | "accepted" | "denied";
29
- get(): Promise<KeyExchangeData | undefined>;
30
- accept(): Promise<KeyExchangeData | undefined>;
29
+ get(): Promise<Datagram | undefined>;
30
+ accept(): Promise<Datagram | undefined>;
31
31
  deny(): void;
32
32
  }
33
33
  export declare class FreeSignalNode {
@@ -46,7 +46,7 @@ export declare class FreeSignalNode {
46
46
  get identityKey(): IdentityKey;
47
47
  get userId(): UserId;
48
48
  onRequest: (request: BootstrapRequest) => void;
49
- getRequest(userId: string): Promise<KeyExchangeData | undefined>;
49
+ getRequest(userId: string): Promise<Datagram | undefined>;
50
50
  protected encrypt(receiverId: string | UserId, protocol: Protocols, data: Uint8Array): Promise<Datagram>;
51
51
  packHandshake(data: KeyExchangeData): Promise<Datagram>;
52
52
  packHandshake(receiverId: string | UserId): Promise<Datagram>;
@@ -54,6 +54,7 @@ export declare class FreeSignalNode {
54
54
  packRelay(receiverId: string | UserId, data: Datagram): Promise<Datagram>;
55
55
  packDiscover(receiverId: string | UserId, discoverId: string | UserId): Promise<Datagram>;
56
56
  packBootstrap(receiverId: string | UserId): Promise<Datagram>;
57
+ packGetBootstrap(receiverId: string | UserId): Promise<Datagram>;
57
58
  protected decrypt(datagram: Datagram): Promise<Uint8Array>;
58
59
  /**
59
60
  * Open the datagram and execute operation of Discover and Handshake.
package/dist/node.js CHANGED
@@ -50,9 +50,9 @@ const _1 = require(".");
50
50
  const utils_1 = require("@freesignal/utils");
51
51
  const crypto_1 = __importDefault(require("@freesignal/crypto"));
52
52
  class BootstrapRequest {
53
- constructor(senderId, data) {
53
+ constructor(senderId, datagram) {
54
54
  this.senderId = senderId;
55
- this.data = data;
55
+ this.datagram = datagram;
56
56
  _BootstrapRequest_status.set(this, 'pending');
57
57
  }
58
58
  get status() {
@@ -60,7 +60,7 @@ class BootstrapRequest {
60
60
  }
61
61
  get() {
62
62
  return __awaiter(this, void 0, void 0, function* () {
63
- return __classPrivateFieldGet(this, _BootstrapRequest_status, "f") === 'accepted' ? this.data : undefined;
63
+ return __classPrivateFieldGet(this, _BootstrapRequest_status, "f") === 'accepted' ? this.datagram : undefined;
64
64
  });
65
65
  }
66
66
  accept() {
@@ -116,25 +116,31 @@ class FreeSignalNode {
116
116
  return __awaiter(this, void 0, void 0, function* () {
117
117
  var _a;
118
118
  if (typeof data === 'string' || data instanceof types_1.UserId) {
119
+ //console.debug("Packing Handshake Ack");
119
120
  const userId = data.toString();
120
121
  const identityKey = (_a = (yield this.sessions.get(userId))) === null || _a === void 0 ? void 0 : _a.identityKey;
121
122
  if (!identityKey)
122
123
  throw new Error("Missing user");
123
- return yield this.encrypt(userId, types_1.Protocols.HANDSHAKE, crypto_1.default.ECDH.scalarMult(identityKey.exchangeKey, this.privateIdentityKey.exchangeKey));
124
+ const res = yield this.encrypt(userId, types_1.Protocols.HANDSHAKE, crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, identityKey.exchangeKey));
125
+ return res;
124
126
  }
127
+ //console.debug("Packing Handshake Syn");
125
128
  const { session, message } = yield this.keyExchange.digestData(data, (0, utils_1.encodeData)(yield this.keyExchange.generateBundle()));
126
129
  yield this.sessions.set(session.userId.toString(), session);
127
130
  return new types_1.Datagram(this.userId.toString(), types_1.UserId.fromKey(data.identityKey).toString(), types_1.Protocols.HANDSHAKE, (0, utils_1.encodeData)(message)).sign(this.privateIdentityKey.signatureKey);
128
131
  });
129
132
  }
130
133
  packData(receiverId, data) {
134
+ //console.debug("Packing Data");
131
135
  return this.encrypt(receiverId, types_1.Protocols.MESSAGE, (0, utils_1.encodeData)(data));
132
136
  }
133
137
  packRelay(receiverId, data) {
138
+ //console.debug("Packing Relay");
134
139
  return this.encrypt(receiverId, types_1.Protocols.RELAY, (0, utils_1.encodeData)(data));
135
140
  }
136
141
  packDiscover(receiverId, discoverId) {
137
142
  return __awaiter(this, void 0, void 0, function* () {
143
+ //console.debug("Packing Discover");
138
144
  if (receiverId instanceof types_1.UserId)
139
145
  receiverId = receiverId.toString();
140
146
  if (discoverId instanceof types_1.UserId)
@@ -149,9 +155,16 @@ class FreeSignalNode {
149
155
  }
150
156
  packBootstrap(receiverId) {
151
157
  return __awaiter(this, void 0, void 0, function* () {
158
+ //console.debug("Packing Bootstrap");
152
159
  return new types_1.Datagram(this.userId.toString(), receiverId.toString(), types_1.Protocols.BOOTSTRAP, (0, utils_1.encodeData)(yield this.keyExchange.generateData()));
153
160
  });
154
161
  }
162
+ packGetBootstrap(receiverId) {
163
+ return __awaiter(this, void 0, void 0, function* () {
164
+ //console.debug("Packing GetBootstrap");
165
+ return new types_1.Datagram(this.userId.toString(), receiverId.toString(), types_1.Protocols.BOOTSTRAP);
166
+ });
167
+ }
155
168
  decrypt(datagram) {
156
169
  return __awaiter(this, void 0, void 0, function* () {
157
170
  var _a;
@@ -189,14 +202,16 @@ class FreeSignalNode {
189
202
  if (!datagram.payload)
190
203
  throw new Error("Missing payload");
191
204
  if (yield this.sessions.has(datagram.sender)) {
205
+ //console.debug("Opening Handshake Ack");
192
206
  const payload = yield this.decrypt(datagram);
193
207
  const identityKey = (_a = (yield this.sessions.get(datagram.sender))) === null || _a === void 0 ? void 0 : _a.identityKey;
194
208
  if (!identityKey)
195
209
  throw new Error("Missing user");
196
- if (!(0, utils_1.compareBytes)(payload, crypto_1.default.ECDH.scalarMult(identityKey.exchangeKey, this.privateIdentityKey.exchangeKey)))
210
+ if (!(0, utils_1.compareBytes)(payload, crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, identityKey.exchangeKey)))
197
211
  throw new Error("Error validating handshake data");
198
212
  return out;
199
213
  }
214
+ //console.debug("Opening Handshake Syn");
200
215
  const data = (0, utils_1.decodeData)(datagram.payload);
201
216
  if (!types_1.Datagram.verify(datagram, types_1.IdentityKey.from(data.identityKey).signatureKey))
202
217
  throw new Error("Signature not verified");
@@ -208,12 +223,15 @@ class FreeSignalNode {
208
223
  throw new Error("Error during handshake");
209
224
  return out;
210
225
  case types_1.Protocols.MESSAGE:
226
+ //console.debug("Opening Message");
211
227
  out.payload = yield this.decrypt(datagram);
212
228
  return out;
213
229
  case types_1.Protocols.RELAY:
230
+ //console.debug("Opening Relay");
214
231
  out.payload = yield this.decrypt(datagram);
215
232
  return out;
216
233
  case types_1.Protocols.DISCOVER:
234
+ //console.debug("Opening Discover");
217
235
  const message = (0, utils_1.decodeData)(yield this.decrypt(datagram));
218
236
  if (message.type === types_1.DiscoverType.REQUEST && message.discoverId && !(yield this.sessions.has(message.discoverId))) {
219
237
  let data;
@@ -248,18 +266,19 @@ class FreeSignalNode {
248
266
  }
249
267
  return out;
250
268
  case types_1.Protocols.BOOTSTRAP:
269
+ //console.debug("Opening Bootstrap");
251
270
  if (datagram.payload) {
252
271
  const data = (0, utils_1.decodeData)(datagram.payload);
253
272
  if (!(0, utils_1.compareBytes)(types_1.UserId.fromKey(data.identityKey).toBytes(), (0, utils_1.encodeBase64)(datagram.sender)))
254
273
  new Error("Malicious bootstrap request");
255
- const request = new BootstrapRequest(datagram.sender, data);
274
+ const request = new BootstrapRequest(datagram.sender, yield this.packHandshake(data));
256
275
  yield this.bootstraps.set(datagram.sender, request);
257
276
  this.onRequest(request);
258
277
  }
259
278
  ;
260
- const bootstrap = yield ((_b = (yield this.bootstraps.get(datagram.sender))) === null || _b === void 0 ? void 0 : _b.get());
261
- if (bootstrap)
262
- out.datagram = yield this.packHandshake(bootstrap);
279
+ const handshakeDatagram = yield ((_b = (yield this.bootstraps.get(datagram.sender))) === null || _b === void 0 ? void 0 : _b.get());
280
+ if (handshakeDatagram)
281
+ out.datagram = handshakeDatagram;
263
282
  return out;
264
283
  case types_1.Protocols.PING:
265
284
  return out;
package/dist/test.js CHANGED
@@ -18,15 +18,17 @@ setImmediate(() => __awaiter(void 0, void 0, void 0, function* () {
18
18
  const bobBootstrap = yield bob.packBootstrap(alice.userId);
19
19
  alice.onRequest = (request) => { request.accept(); };
20
20
  const test = (yield alice.open(bobBootstrap)).datagram;
21
- console.log("Valid bootstrap: ", !!test);
22
- const bobRequest = yield alice.getRequest(bob.userId.toString());
23
- if (!bobRequest)
21
+ const aliceHandshake = yield alice.getRequest(bob.userId.toString());
22
+ if (!aliceHandshake)
24
23
  throw new Error("Bootstrap Failed");
25
- const aliceHandshake = yield alice.packHandshake(bobRequest);
26
- yield bob.open(aliceHandshake);
24
+ const bobHandshake = (yield bob.open(aliceHandshake)).datagram;
25
+ if (!bobHandshake)
26
+ throw new Error("Handshake Failed");
27
+ console.log(!!(yield alice.open(bobHandshake)).header);
27
28
  const first = (yield bob.packData(alice.userId, "Hi Alice!")).toBytes();
28
29
  console.log("Bob: ", (0, utils_1.decodeData)((yield alice.open(first)).payload));
29
30
  const second = yield alice.packData(bob.userId, "Hi Bob!");
31
+ console.log("Test");
30
32
  console.log("Alice: ", (0, utils_1.decodeData)((yield bob.open(second)).payload));
31
33
  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)));
32
34
  third.forEach((data) => __awaiter(void 0, void 0, void 0, function* () {
package/dist/types.js CHANGED
@@ -35,32 +35,66 @@ 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
- function encryptData(session, data) {
39
- //console.log(session.id, ' Sending: ', decodeBase64(session.getHeaderKeys().sending ?? new Uint8Array()));
38
+ /*export function encryptData(session: KeySession, data: Uint8Array): EncryptedData {
40
39
  const key = session.getSendingKey();
41
40
  if (!key)
42
41
  throw new Error("Error generating key");
43
- const nonce = crypto_1.default.randomBytes(EncryptionHeader.nonceLength);
44
- const ciphertext = crypto_1.default.box.encrypt(data, nonce, key.secretKey);
42
+ const nonce = crypto.randomBytes(EncryptionHeader.nonceLength);
43
+ const ciphertext = crypto.box.encrypt(data, nonce, key.secretKey);
45
44
  const headerKey = session.getHeaderKeys().sending;
45
+ //console.debug(session.userId.toString(), "Sending: ", decodeBase64(headerKey ?? new Uint8Array()))
46
46
  let header = new EncryptionHeader(key, nonce).toBytes();
47
- const headerNonce = crypto_1.default.randomBytes(EncryptionHeader.nonceLength);
47
+ const headerNonce = crypto.randomBytes(EncryptionHeader.nonceLength)
48
48
  if (headerKey)
49
- header = crypto_1.default.box.encrypt(header, headerNonce, headerKey);
49
+ header = crypto.box.encrypt(header, headerNonce, headerKey);
50
50
  const test = new EncryptedData(header, headerNonce, ciphertext);
51
51
  return test;
52
52
  }
53
- function decryptData(session, encryptedData) {
54
- //console.log(session.id, ' Receiving: ', decodeBase64(session.getHeaderKeys().receiving ?? new Uint8Array()));
53
+
54
+ export function decryptData(session: KeySession, encryptedData: Uint8Array): Uint8Array {
55
55
  const encrypted = EncryptedData.from(encryptedData);
56
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);
57
+ const nextHeaderKey = session.getHeaderKeys().nextReciving;
58
+ let headerData: Uint8Array | undefined;
59
+ try {
60
+ if (!headerKey)
61
+ throw new Error("Error generating key");
62
+ headerData = crypto.box.decrypt(encrypted.header, encrypted.nonce, headerKey);
60
63
  if (!headerData)
61
64
  throw new Error("Error calculating header");
65
+ //console.debug(session.userId.toString(), "Receiving: ", decodeBase64(session.getHeaderKeys().receiving ?? new Uint8Array()))
66
+ } catch {
67
+ if (!nextHeaderKey)
68
+ throw new Error("Error generating key");
69
+ headerData = crypto.box.decrypt(encrypted.header, encrypted.nonce, nextHeaderKey);
70
+ if (!headerData) {
71
+ //console.debug(session.toJSON());
72
+ throw new Error("Error calculating header");
73
+ }
74
+ //console.debug(session.userId.toString(), "NextReceiving: ", decodeBase64(session.getHeaderKeys().nextReciving ?? new Uint8Array()))
62
75
  }
63
- const header = EncryptionHeader.from(headerData);
76
+ const header = EncryptionHeader.from(headerData!);
77
+ const key = session.getReceivingKey(header);
78
+ if (!key)
79
+ throw new Error("Error calculating key");
80
+ const decrypted = crypto.box.decrypt(encrypted.payload, header.nonce, key);
81
+ if (!decrypted)
82
+ throw new Error("Error decrypting data");
83
+ return decrypted;
84
+ }*/
85
+ function encryptData(session, data) {
86
+ const key = session.getSendingKey();
87
+ if (!key)
88
+ throw new Error("Error generating key");
89
+ const nonce = crypto_1.default.randomBytes(EncryptionHeader.nonceLength);
90
+ const ciphertext = crypto_1.default.box.encrypt(data, nonce, key.secretKey);
91
+ let header = new EncryptionHeader(key, nonce).toBytes();
92
+ const test = new EncryptedData(header, crypto_1.default.randomBytes(EncryptionHeader.nonceLength), ciphertext);
93
+ return test;
94
+ }
95
+ function decryptData(session, encryptedData) {
96
+ const encrypted = EncryptedData.from(encryptedData);
97
+ const header = EncryptionHeader.from(encrypted.header);
64
98
  const key = session.getReceivingKey(header);
65
99
  if (!key)
66
100
  throw new Error("Error calculating key");
package/dist/x3dh.js CHANGED
@@ -84,6 +84,7 @@ class KeyExchange {
84
84
  }
85
85
  digestData(message, associatedData) {
86
86
  return __awaiter(this, void 0, void 0, function* () {
87
+ //console.debug("Digest Data")
87
88
  const ephemeralKey = crypto_1.default.ECDH.keyPair();
88
89
  const signedPreKey = (0, utils_1.encodeBase64)(message.signedPreKey);
89
90
  const identityKey = types_1.IdentityKey.from(message.identityKey);
@@ -97,9 +98,9 @@ class KeyExchange {
97
98
  ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, identityKey.exchangeKey),
98
99
  ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, signedPreKey),
99
100
  ...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 * 2);
101
- //, headerKey: derivedKey.subarray(KeySession.keyLength)
102
- const session = new double_ratchet_1.KeySession(identityKey, { remoteKey: identityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength) });
101
+ ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength * 3);
102
+ //, headerKey: derivedKey.subarray(KeySession.keyLength, KeySession.keyLength * 2), nextHeaderKey: derivedKey.subarray(KeySession.keyLength * 2)
103
+ const session = new double_ratchet_1.KeySession({ identityKey, remoteKey: identityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength) });
103
104
  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()));
104
105
  if (!encrypted)
105
106
  throw new Error("Decryption error");
@@ -118,6 +119,7 @@ class KeyExchange {
118
119
  }
119
120
  digestMessage(message) {
120
121
  return __awaiter(this, void 0, void 0, function* () {
122
+ //console.debug("Digest Message")
121
123
  const signedPreKey = yield this.storage.get(message.signedPreKeyHash);
122
124
  const hash = message.signedPreKeyHash.concat(message.onetimePreKeyHash);
123
125
  const onetimePreKey = yield this.storage.get(hash);
@@ -132,9 +134,9 @@ class KeyExchange {
132
134
  ...crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, ephemeralKey),
133
135
  ...crypto_1.default.ECDH.scalarMult(signedPreKey.secretKey, ephemeralKey),
134
136
  ...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 * 2);
136
- //, nextHeaderKey: derivedKey.subarray(KeySession.keyLength)
137
- const session = new double_ratchet_1.KeySession(identityKey, { secretKey: this.privateIdentityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength) });
137
+ ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength * 3);
138
+ //nextHeaderKey: derivedKey.subarray(KeySession.keyLength, KeySession.keyLength * 2), headerKey: derivedKey.subarray(KeySession.keyLength * 2)
139
+ const session = new double_ratchet_1.KeySession({ identityKey, secretKey: this.privateIdentityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength) });
138
140
  const data = (0, types_1.decryptData)(session, (0, utils_1.encodeBase64)(message.associatedData));
139
141
  if (!data)
140
142
  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.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Signal Protocol implementation in javascript",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "author": "Christian Braghette",