@freesignal/protocol 0.7.11 → 0.8.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.
package/dist/types.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * FreeSignal Protocol
4
3
  *
@@ -26,38 +25,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
26
25
  step((generator = generator.apply(thisArg, _arguments || [])).next());
27
26
  });
28
27
  };
29
- var __importDefault = (this && this.__importDefault) || function (mod) {
30
- return (mod && mod.__esModule) ? mod : { "default": mod };
31
- };
32
- Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.AsyncMap = exports.EncryptedData = exports.EncryptionHeader = exports.EncryptedDatagram = exports.Datagram = exports.Protocols = exports.DiscoverType = exports.PrivateIdentityKey = exports.IdentityKey = exports.UserId = void 0;
34
- exports.encryptData = encryptData;
35
- exports.decryptData = decryptData;
36
- const utils_1 = require("@freesignal/utils");
37
- const crypto_1 = __importDefault(require("@freesignal/crypto"));
38
- function encryptData(session, data) {
28
+ import { concatBytes, decodeBase64, encodeBase64, bytesToNumber, numberToBytes, compareBytes } from "@freesignal/utils";
29
+ import crypto from "@freesignal/crypto";
30
+ export function encryptData(session, data) {
39
31
  const key = session.getSendingKey();
40
32
  if (!key)
41
33
  throw new Error("Error generating key");
42
- const nonce = crypto_1.default.randomBytes(EncryptionHeader.nonceLength);
43
- const payload = crypto_1.default.box.encrypt(data, nonce, key.secretKey);
34
+ const nonce = crypto.randomBytes(EncryptionHeader.nonceLength);
35
+ const payload = crypto.box.encrypt(data, nonce, key.secretKey);
44
36
  let header = new EncryptionHeader(key, nonce).toBytes();
45
37
  const headerKey = session.getHeaderKey();
46
38
  if (!headerKey)
47
39
  return new EncryptedData({ header, payload });
48
- const headerNonce = crypto_1.default.randomBytes(EncryptionHeader.nonceLength);
40
+ const headerNonce = crypto.randomBytes(EncryptionHeader.nonceLength);
49
41
  if (headerKey)
50
- header = crypto_1.default.box.encrypt(header, headerNonce, headerKey);
51
- return new EncryptedData({ hashkey: crypto_1.default.hash(headerKey !== null && headerKey !== void 0 ? headerKey : new Uint8Array(32).fill(0)), header, nonce: headerNonce, payload });
42
+ header = crypto.box.encrypt(header, headerNonce, headerKey);
43
+ return new EncryptedData({ hashkey: crypto.hash(headerKey !== null && headerKey !== void 0 ? headerKey : new Uint8Array(32).fill(0)), header, nonce: headerNonce, payload });
52
44
  }
53
- function decryptData(session, encryptedData) {
45
+ export function decryptData(session, encryptedData) {
54
46
  const encrypted = EncryptedData.from(encryptedData);
55
47
  let headerData = encrypted.header;
56
48
  if (encrypted.hashkey && encrypted.nonce) {
57
- const headerKey = session.getHeaderKey((0, utils_1.decodeBase64)(encrypted.hashkey));
49
+ const headerKey = session.getHeaderKey(decodeBase64(encrypted.hashkey));
58
50
  if (!headerKey)
59
51
  throw new Error("Error getting key");
60
- const data = crypto_1.default.box.decrypt(encrypted.header, encrypted.nonce, headerKey);
52
+ const data = crypto.box.decrypt(encrypted.header, encrypted.nonce, headerKey);
61
53
  if (!data)
62
54
  throw new Error("Error calculating header");
63
55
  headerData = data;
@@ -66,18 +58,18 @@ function decryptData(session, encryptedData) {
66
58
  const key = session.getReceivingKey(header);
67
59
  if (!key)
68
60
  throw new Error("Error calculating key");
69
- const decrypted = crypto_1.default.box.decrypt(encrypted.payload, header.nonce, key);
61
+ const decrypted = crypto.box.decrypt(encrypted.payload, header.nonce, key);
70
62
  if (!decrypted)
71
63
  throw new Error("Error decrypting data");
72
64
  return decrypted;
73
65
  }
74
- class UserId {
66
+ export class UserId {
75
67
  constructor(array) {
76
68
  this.array = array;
77
69
  }
78
70
  ;
79
71
  toString() {
80
- return (0, utils_1.decodeBase64)(this.array);
72
+ return decodeBase64(this.array);
81
73
  }
82
74
  toJSON() {
83
75
  return this.toString();
@@ -87,20 +79,19 @@ class UserId {
87
79
  }
88
80
  static fromKey(identityKey) {
89
81
  if (typeof identityKey === 'string')
90
- identityKey = (0, utils_1.encodeBase64)(identityKey);
82
+ identityKey = encodeBase64(identityKey);
91
83
  else if (identityKey instanceof IdentityKey)
92
84
  identityKey = (identityKey).toBytes();
93
- return new UserId(crypto_1.default.hkdf(identityKey, new Uint8Array(32).fill(0), "/freesignal/userid", UserId.keyLength));
85
+ return new UserId(crypto.hkdf(identityKey, new Uint8Array(32).fill(0), "/freesignal/userid", UserId.keyLength));
94
86
  }
95
87
  static from(userId) {
96
88
  if (typeof userId === 'string')
97
- userId = (0, utils_1.encodeBase64)(userId);
89
+ userId = encodeBase64(userId);
98
90
  return new UserId(userId instanceof Uint8Array ? userId : userId.array);
99
91
  }
100
92
  }
101
- exports.UserId = UserId;
102
93
  UserId.keyLength = 32;
103
- class IdentityKey {
94
+ export class IdentityKey {
104
95
  constructor(identityKey) {
105
96
  if (identityKey instanceof IdentityKey) {
106
97
  this.info = identityKey.info;
@@ -109,22 +100,22 @@ class IdentityKey {
109
100
  }
110
101
  else {
111
102
  if (typeof identityKey === 'string')
112
- identityKey = (0, utils_1.encodeBase64)(identityKey);
103
+ identityKey = encodeBase64(identityKey);
113
104
  if (identityKey.length !== IdentityKey.keyLength)
114
105
  throw new Error("Invalid key length");
115
106
  this.info = identityKey[0];
116
- this.signatureKey = identityKey.subarray(1, crypto_1.default.EdDSA.publicKeyLength + 1);
117
- this.exchangeKey = identityKey.subarray(crypto_1.default.EdDSA.publicKeyLength + 1, IdentityKey.keyLength);
107
+ this.signatureKey = identityKey.subarray(1, crypto.EdDSA.publicKeyLength + 1);
108
+ this.exchangeKey = identityKey.subarray(crypto.EdDSA.publicKeyLength + 1, IdentityKey.keyLength);
118
109
  }
119
110
  }
120
111
  get userId() {
121
112
  return UserId.fromKey(this.toBytes());
122
113
  }
123
114
  toBytes() {
124
- return (0, utils_1.concatBytes)((0, utils_1.numberToBytes)(this.info, 1), this.signatureKey, this.exchangeKey);
115
+ return concatBytes(numberToBytes(this.info, 1), this.signatureKey, this.exchangeKey);
125
116
  }
126
117
  toString() {
127
- return (0, utils_1.decodeBase64)(this.toBytes());
118
+ return decodeBase64(this.toBytes());
128
119
  }
129
120
  toJSON() {
130
121
  return this.toString();
@@ -134,18 +125,17 @@ class IdentityKey {
134
125
  if (key instanceof IdentityKey)
135
126
  return key.toBytes();
136
127
  else if (typeof key === 'string')
137
- return (0, utils_1.encodeBase64)(key);
128
+ return encodeBase64(key);
138
129
  else
139
130
  return key;
140
131
  });
141
- return new IdentityKey(keys.length === 2 ? (0, utils_1.concatBytes)((0, utils_1.numberToBytes)(IdentityKey.info + IdentityKey.version, 1), ...keys) : keys[0]);
132
+ return new IdentityKey(keys.length === 2 ? concatBytes(numberToBytes(IdentityKey.info + IdentityKey.version, 1), ...keys) : keys[0]);
142
133
  }
143
134
  }
144
- exports.IdentityKey = IdentityKey;
145
- IdentityKey.keyLength = crypto_1.default.EdDSA.publicKeyLength + crypto_1.default.ECDH.publicKeyLength + 1;
135
+ IdentityKey.keyLength = crypto.EdDSA.publicKeyLength + crypto.ECDH.publicKeyLength + 1;
146
136
  IdentityKey.version = 1;
147
137
  IdentityKey.info = 0x70;
148
- class PrivateIdentityKey {
138
+ export class PrivateIdentityKey {
149
139
  constructor(privateIdentityKey) {
150
140
  if (privateIdentityKey instanceof PrivateIdentityKey) {
151
141
  this.info = privateIdentityKey.info;
@@ -155,23 +145,23 @@ class PrivateIdentityKey {
155
145
  }
156
146
  else {
157
147
  if (typeof privateIdentityKey === 'string')
158
- privateIdentityKey = (0, utils_1.encodeBase64)(privateIdentityKey);
148
+ privateIdentityKey = encodeBase64(privateIdentityKey);
159
149
  if (!PrivateIdentityKey.isIdentityKeys(privateIdentityKey))
160
150
  throw new Error("Invalid key length");
161
151
  this.info = privateIdentityKey[0];
162
- this.signatureKey = privateIdentityKey.subarray(1, crypto_1.default.EdDSA.secretKeyLength + 1);
163
- this.exchangeKey = privateIdentityKey.subarray(crypto_1.default.EdDSA.secretKeyLength + 1, PrivateIdentityKey.keyLength);
164
- this.identityKey = IdentityKey.from(crypto_1.default.EdDSA.keyPair(this.signatureKey).publicKey, crypto_1.default.ECDH.keyPair(this.exchangeKey).publicKey);
152
+ this.signatureKey = privateIdentityKey.subarray(1, crypto.EdDSA.secretKeyLength + 1);
153
+ this.exchangeKey = privateIdentityKey.subarray(crypto.EdDSA.secretKeyLength + 1, PrivateIdentityKey.keyLength);
154
+ this.identityKey = IdentityKey.from(crypto.EdDSA.keyPair(this.signatureKey).publicKey, crypto.ECDH.keyPair(this.exchangeKey).publicKey);
165
155
  }
166
156
  }
167
157
  get userId() {
168
158
  return UserId.fromKey(this.identityKey.toBytes()).toString();
169
159
  }
170
160
  toBytes() {
171
- return (0, utils_1.concatBytes)((0, utils_1.numberToBytes)(this.info, 1), this.signatureKey, this.exchangeKey);
161
+ return concatBytes(numberToBytes(this.info, 1), this.signatureKey, this.exchangeKey);
172
162
  }
173
163
  toString() {
174
- return (0, utils_1.decodeBase64)(this.toBytes());
164
+ return decodeBase64(this.toBytes());
175
165
  }
176
166
  toJSON() {
177
167
  return this.toString();
@@ -184,23 +174,22 @@ class PrivateIdentityKey {
184
174
  if (key instanceof PrivateIdentityKey)
185
175
  return key.toBytes();
186
176
  else if (typeof key === 'string')
187
- return (0, utils_1.encodeBase64)(key);
177
+ return encodeBase64(key);
188
178
  else
189
179
  return key;
190
180
  });
191
- return new PrivateIdentityKey(keys.length === 2 ? (0, utils_1.concatBytes)((0, utils_1.numberToBytes)(PrivateIdentityKey.info + PrivateIdentityKey.version, 1), ...keys) : keys[0]);
181
+ return new PrivateIdentityKey(keys.length === 2 ? concatBytes(numberToBytes(PrivateIdentityKey.info + PrivateIdentityKey.version, 1), ...keys) : keys[0]);
192
182
  }
193
183
  }
194
- exports.PrivateIdentityKey = PrivateIdentityKey;
195
- PrivateIdentityKey.keyLength = crypto_1.default.EdDSA.secretKeyLength + crypto_1.default.ECDH.secretKeyLength + 1;
184
+ PrivateIdentityKey.keyLength = crypto.EdDSA.secretKeyLength + crypto.ECDH.secretKeyLength + 1;
196
185
  PrivateIdentityKey.version = 1;
197
186
  PrivateIdentityKey.info = 0x4E;
198
- var DiscoverType;
187
+ export var DiscoverType;
199
188
  (function (DiscoverType) {
200
189
  DiscoverType[DiscoverType["REQUEST"] = 0] = "REQUEST";
201
190
  DiscoverType[DiscoverType["RESPONSE"] = 1] = "RESPONSE";
202
- })(DiscoverType || (exports.DiscoverType = DiscoverType = {}));
203
- var Protocols;
191
+ })(DiscoverType || (DiscoverType = {}));
192
+ export var Protocols;
204
193
  (function (Protocols) {
205
194
  Protocols["PING"] = "/freesignal/ping";
206
195
  Protocols["MESSAGE"] = "/freesignal/message";
@@ -208,7 +197,7 @@ var Protocols;
208
197
  Protocols["HANDSHAKE"] = "/freesignal/handshake";
209
198
  Protocols["DISCOVER"] = "/freesignal/discover";
210
199
  Protocols["BOOTSTRAP"] = "/freesignal/bootstrap";
211
- })(Protocols || (exports.Protocols = Protocols = {}));
200
+ })(Protocols || (Protocols = {}));
212
201
  (function (Protocols) {
213
202
  function isProtocol(protocol) {
214
203
  return Object.values(Protocols).includes(protocol);
@@ -223,19 +212,19 @@ var Protocols;
223
212
  }
224
213
  Protocols.toCode = toCode;
225
214
  function encode(protocol, length = 1) {
226
- return (0, utils_1.numberToBytes)(Protocols.toCode(protocol), length);
215
+ return numberToBytes(Protocols.toCode(protocol), length);
227
216
  }
228
217
  Protocols.encode = encode;
229
218
  function decode(array) {
230
- return Protocols.fromCode((0, utils_1.bytesToNumber)(array));
219
+ return Protocols.fromCode(bytesToNumber(array));
231
220
  }
232
221
  Protocols.decode = decode;
233
- })(Protocols || (exports.Protocols = Protocols = {}));
222
+ })(Protocols || (Protocols = {}));
234
223
  ;
235
- class Datagram {
224
+ export class Datagram {
236
225
  constructor(protocol, payload, sessionTag) {
237
226
  this._version = Datagram.version;
238
- this.sessionTag = sessionTag instanceof Uint8Array ? (0, utils_1.decodeBase64)(sessionTag) : sessionTag;
227
+ this.sessionTag = sessionTag instanceof Uint8Array ? decodeBase64(sessionTag) : sessionTag;
239
228
  this.protocol = protocol;
240
229
  this.payload = payload instanceof Uint8Array ? payload : payload === null || payload === void 0 ? void 0 : payload.toBytes();
241
230
  }
@@ -243,50 +232,50 @@ class Datagram {
243
232
  return this._version;
244
233
  }
245
234
  get signature() {
246
- return this._signature ? (0, utils_1.decodeBase64)(this._signature) : undefined;
235
+ return this._signature ? decodeBase64(this._signature) : undefined;
247
236
  }
248
237
  get unsigned() {
249
238
  const data = this.toBytes();
250
239
  data[0] &= 127;
251
- return data.subarray(0, data.length - (this._signature ? crypto_1.default.EdDSA.signatureLength : 0));
240
+ return data.subarray(0, data.length - (this._signature ? crypto.EdDSA.signatureLength : 0));
252
241
  }
253
242
  toBytes() {
254
243
  var _a, _b;
255
- return (0, utils_1.concatBytes)(new Uint8Array(1).fill(this.version | (this.signature ? 128 : 0)), //1
244
+ return concatBytes(new Uint8Array(1).fill(this.version | (this.signature ? 128 : 0)), //1
256
245
  Protocols.encode(this.protocol), //1
257
- this.sessionTag ? (0, utils_1.encodeBase64)(this.sessionTag) : new Uint8Array(32).fill(0), //32
246
+ this.sessionTag ? encodeBase64(this.sessionTag) : new Uint8Array(32).fill(0), //32
258
247
  (_a = this.payload) !== null && _a !== void 0 ? _a : new Uint8Array(), (_b = this._signature) !== null && _b !== void 0 ? _b : new Uint8Array());
259
248
  }
260
249
  sign(secretKey) {
261
- this._signature = crypto_1.default.EdDSA.sign(this.unsigned, secretKey);
250
+ this._signature = crypto.EdDSA.sign(this.unsigned, secretKey);
262
251
  return this;
263
252
  }
264
253
  verify(publicKey) {
265
254
  if (!this._signature)
266
255
  throw new Error("Datagram not signed");
267
- return crypto_1.default.EdDSA.verify(this.unsigned, this._signature, publicKey);
256
+ return crypto.EdDSA.verify(this._signature, this.unsigned, publicKey);
268
257
  }
269
258
  toString() {
270
- return (0, utils_1.decodeBase64)(this.toBytes());
259
+ return decodeBase64(this.toBytes());
271
260
  }
272
261
  toJSON() {
273
262
  return {
274
263
  version: this.version,
275
264
  sessionTag: this.sessionTag,
276
265
  protocol: this.protocol,
277
- payload: this.payload ? (0, utils_1.decodeBase64)(this.payload) : undefined,
278
- signature: this._signature ? (0, utils_1.decodeBase64)(this._signature) : undefined
266
+ payload: this.payload ? decodeBase64(this.payload) : undefined,
267
+ signature: this._signature ? decodeBase64(this._signature) : undefined
279
268
  };
280
269
  }
281
270
  static from(data) {
282
271
  if (typeof data === 'string')
283
- data = (0, utils_1.encodeBase64)(data);
272
+ data = encodeBase64(data);
284
273
  if (data instanceof Uint8Array) {
285
274
  const authTag = data.subarray(2, Datagram.headerLength);
286
- const datagram = new Datagram(Protocols.decode(data.subarray(1, 2)), data.subarray(Datagram.headerLength, data.length - (data[0] & 128 ? crypto_1.default.EdDSA.signatureLength : 0)), (0, utils_1.compareBytes)(authTag, new Uint8Array(32).fill(0)) ? undefined : (0, utils_1.decodeBase64)(authTag));
275
+ const datagram = new Datagram(Protocols.decode(data.subarray(1, 2)), data.subarray(Datagram.headerLength, data.length - (data[0] & 128 ? crypto.EdDSA.signatureLength : 0)), compareBytes(authTag, new Uint8Array(32).fill(0)) ? undefined : decodeBase64(authTag));
287
276
  datagram._version = data[0] & 127;
288
277
  if (data[0] & 128)
289
- datagram._signature = data.subarray(data.length - crypto_1.default.EdDSA.signatureLength);
278
+ datagram._signature = data.subarray(data.length - crypto.EdDSA.signatureLength);
290
279
  return datagram;
291
280
  }
292
281
  else if (data instanceof Datagram) {
@@ -299,10 +288,9 @@ class Datagram {
299
288
  throw new Error('Invalid constructor arguments for Datagram');
300
289
  }
301
290
  }
302
- exports.Datagram = Datagram;
303
291
  Datagram.version = 1;
304
292
  Datagram.headerLength = 34;
305
- class EncryptedDatagram extends Datagram {
293
+ export class EncryptedDatagram extends Datagram {
306
294
  constructor(protocol, sessionTag, payload) {
307
295
  super(protocol, payload, sessionTag);
308
296
  }
@@ -313,8 +301,7 @@ class EncryptedDatagram extends Datagram {
313
301
  return datagram;
314
302
  }
315
303
  }
316
- exports.EncryptedDatagram = EncryptedDatagram;
317
- class EncryptionHeader {
304
+ export class EncryptionHeader {
318
305
  constructor(keys, nonce) {
319
306
  this.nonce = nonce;
320
307
  this.count = keys.count;
@@ -322,13 +309,13 @@ class EncryptionHeader {
322
309
  this.publicKey = keys.publicKey;
323
310
  }
324
311
  toBytes() {
325
- 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);
312
+ return concatBytes(numberToBytes(this.count, EncryptionHeader.countLength), numberToBytes(this.previous, EncryptionHeader.countLength), this.publicKey, this.nonce);
326
313
  }
327
314
  toJSON() {
328
315
  return {
329
316
  count: this.count,
330
317
  previous: this.previous,
331
- publicKey: (0, utils_1.decodeBase64)(this.publicKey)
318
+ publicKey: decodeBase64(this.publicKey)
332
319
  };
333
320
  }
334
321
  static from(data) {
@@ -336,17 +323,16 @@ class EncryptionHeader {
336
323
  data = data.toBytes();
337
324
  let offset = 0;
338
325
  return new EncryptionHeader({
339
- count: (0, utils_1.bytesToNumber)(data.subarray(offset, offset += EncryptionHeader.countLength)),
340
- previous: (0, utils_1.bytesToNumber)(data.subarray(offset, offset += EncryptionHeader.countLength)),
326
+ count: bytesToNumber(data.subarray(offset, offset += EncryptionHeader.countLength)),
327
+ previous: bytesToNumber(data.subarray(offset, offset += EncryptionHeader.countLength)),
341
328
  publicKey: data.subarray(offset, offset += EncryptionHeader.keyLength)
342
329
  }, data.subarray(offset, offset += EncryptedData.nonceLength));
343
330
  }
344
331
  }
345
- exports.EncryptionHeader = EncryptionHeader;
346
- EncryptionHeader.keyLength = crypto_1.default.box.keyLength;
347
- EncryptionHeader.nonceLength = crypto_1.default.box.nonceLength;
332
+ EncryptionHeader.keyLength = crypto.box.keyLength;
333
+ EncryptionHeader.nonceLength = crypto.box.nonceLength;
348
334
  EncryptionHeader.countLength = 2;
349
- class EncryptedData {
335
+ export class EncryptedData {
350
336
  constructor({ hashkey, header, nonce, payload }) {
351
337
  this._version = EncryptedData.version;
352
338
  this.header = header;
@@ -362,22 +348,22 @@ class EncryptedData {
362
348
  }
363
349
  toBytes() {
364
350
  var _a, _b;
365
- return (0, utils_1.concatBytes)((0, utils_1.numberToBytes)(this._version | (this.hashkey && this.nonce ? 128 : 0), 1), (0, utils_1.numberToBytes)(this.header.length, 3), this.header, (_a = this.hashkey) !== null && _a !== void 0 ? _a : new Uint8Array(), (_b = this.nonce) !== null && _b !== void 0 ? _b : new Uint8Array, this.payload);
351
+ return concatBytes(numberToBytes(this._version | (this.hashkey && this.nonce ? 128 : 0), 1), numberToBytes(this.header.length, 3), this.header, (_a = this.hashkey) !== null && _a !== void 0 ? _a : new Uint8Array(), (_b = this.nonce) !== null && _b !== void 0 ? _b : new Uint8Array, this.payload);
366
352
  }
367
353
  toJSON() {
368
354
  return {
369
355
  version: this._version,
370
- header: (0, utils_1.decodeBase64)(this.header),
371
- hashkey: this.hashkey ? (0, utils_1.decodeBase64)(this.hashkey) : undefined,
372
- nonce: this.nonce ? (0, utils_1.decodeBase64)(this.nonce) : undefined,
373
- payload: (0, utils_1.decodeBase64)(this.payload)
356
+ header: decodeBase64(this.header),
357
+ hashkey: this.hashkey ? decodeBase64(this.hashkey) : undefined,
358
+ nonce: this.nonce ? decodeBase64(this.nonce) : undefined,
359
+ payload: decodeBase64(this.payload)
374
360
  };
375
361
  }
376
362
  static from(data) {
377
363
  if (data instanceof EncryptedData)
378
364
  data = data.toBytes();
379
- const versionByte = (0, utils_1.bytesToNumber)(data.subarray(0, 1));
380
- const headerLength = (0, utils_1.bytesToNumber)(data.subarray(1, 4));
365
+ const versionByte = bytesToNumber(data.subarray(0, 1));
366
+ const headerLength = bytesToNumber(data.subarray(1, 4));
381
367
  let offset = 4;
382
368
  const header = data.subarray(offset, offset += headerLength);
383
369
  let hashkey, nonce;
@@ -394,10 +380,9 @@ class EncryptedData {
394
380
  return obj;
395
381
  }
396
382
  }
397
- exports.EncryptedData = EncryptedData;
398
383
  EncryptedData.version = 1;
399
- EncryptedData.nonceLength = crypto_1.default.box.nonceLength;
400
- class AsyncMap {
384
+ EncryptedData.nonceLength = crypto.box.nonceLength;
385
+ export class AsyncMap {
401
386
  constructor(iterable) {
402
387
  this.map = new Map(iterable);
403
388
  }
@@ -433,4 +418,3 @@ class AsyncMap {
433
418
  });
434
419
  }
435
420
  }
436
- exports.AsyncMap = AsyncMap;
package/dist/x3dh.d.ts CHANGED
@@ -17,8 +17,8 @@
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
19
  import { KeyExchangeData, KeyExchangeDataBundle, KeyExchangeSynMessage, LocalStorage, Crypto } from "@freesignal/interfaces";
20
- import { KeySession } from "./double-ratchet";
21
- import { IdentityKey, PrivateIdentityKey } from "./types";
20
+ import { KeySession } from "./double-ratchet.js";
21
+ import { IdentityKey, PrivateIdentityKey } from "./types.js";
22
22
  export interface ExportedKeyExchange {
23
23
  privateIdentityKey: PrivateIdentityKey;
24
24
  storage: Array<[string, Crypto.KeyPair]>;
package/dist/x3dh.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * FreeSignal Protocol
4
3
  *
@@ -26,34 +25,29 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
26
25
  step((generator = generator.apply(thisArg, _arguments || [])).next());
27
26
  });
28
27
  };
29
- var __importDefault = (this && this.__importDefault) || function (mod) {
30
- return (mod && mod.__esModule) ? mod : { "default": mod };
31
- };
32
- Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.KeyExchange = void 0;
34
- const crypto_1 = __importDefault(require("@freesignal/crypto"));
35
- const double_ratchet_1 = require("./double-ratchet");
36
- const utils_1 = require("@freesignal/utils");
37
- const types_1 = require("./types");
38
- const _1 = require(".");
39
- class KeyExchange {
28
+ import crypto from "@freesignal/crypto";
29
+ import { KeySession } from "./double-ratchet.js";
30
+ import { concatBytes, decodeBase64, encodeBase64, compareBytes } from "@freesignal/utils";
31
+ import { decryptData, encryptData, IdentityKey } from "./types.js";
32
+ import { createIdentity } from "./index.js";
33
+ export class KeyExchange {
40
34
  constructor(storage, privateIdentityKey) {
41
35
  this.storage = storage;
42
- this.privateIdentityKey = privateIdentityKey !== null && privateIdentityKey !== void 0 ? privateIdentityKey : (0, _1.createIdentity)();
36
+ this.privateIdentityKey = privateIdentityKey !== null && privateIdentityKey !== void 0 ? privateIdentityKey : createIdentity();
43
37
  }
44
38
  get identityKey() {
45
39
  return this.privateIdentityKey.identityKey;
46
40
  }
47
41
  generateSPK() {
48
- const signedPreKey = crypto_1.default.ECDH.keyPair();
49
- const signedPreKeyHash = crypto_1.default.hash(signedPreKey.publicKey);
50
- this.storage.set((0, utils_1.decodeBase64)(signedPreKeyHash), signedPreKey);
42
+ const signedPreKey = crypto.ECDH.keyPair();
43
+ const signedPreKeyHash = crypto.hash(signedPreKey.publicKey);
44
+ this.storage.set(decodeBase64(signedPreKeyHash), signedPreKey);
51
45
  return { signedPreKey, signedPreKeyHash };
52
46
  }
53
47
  generateOPK(spkHash) {
54
- const onetimePreKey = crypto_1.default.ECDH.keyPair();
55
- const onetimePreKeyHash = crypto_1.default.hash(onetimePreKey.publicKey);
56
- this.storage.set((0, utils_1.decodeBase64)(spkHash).concat((0, utils_1.decodeBase64)(onetimePreKeyHash)), onetimePreKey);
48
+ const onetimePreKey = crypto.ECDH.keyPair();
49
+ const onetimePreKeyHash = crypto.hash(onetimePreKey.publicKey);
50
+ this.storage.set(decodeBase64(spkHash).concat(decodeBase64(onetimePreKeyHash)), onetimePreKey);
57
51
  return { onetimePreKey, onetimePreKeyHash };
58
52
  }
59
53
  generateBundle(length) {
@@ -63,9 +57,9 @@ class KeyExchange {
63
57
  return {
64
58
  version: KeyExchange.version,
65
59
  identityKey: this.identityKey.toString(),
66
- signedPreKey: (0, utils_1.decodeBase64)(signedPreKey.publicKey),
67
- signature: (0, utils_1.decodeBase64)(crypto_1.default.EdDSA.sign(signedPreKeyHash, this.privateIdentityKey.signatureKey)),
68
- onetimePreKeys: onetimePreKey.map(opk => (0, utils_1.decodeBase64)(opk.publicKey))
60
+ signedPreKey: decodeBase64(signedPreKey.publicKey),
61
+ signature: decodeBase64(crypto.EdDSA.sign(signedPreKeyHash, this.privateIdentityKey.signatureKey)),
62
+ onetimePreKeys: onetimePreKey.map(opk => decodeBase64(opk.publicKey))
69
63
  };
70
64
  });
71
65
  }
@@ -76,31 +70,31 @@ class KeyExchange {
76
70
  return {
77
71
  version: KeyExchange.version,
78
72
  identityKey: this.identityKey.toString(),
79
- signedPreKey: (0, utils_1.decodeBase64)(signedPreKey.publicKey),
80
- signature: (0, utils_1.decodeBase64)(crypto_1.default.EdDSA.sign(signedPreKeyHash, this.privateIdentityKey.signatureKey)),
81
- onetimePreKey: (0, utils_1.decodeBase64)(onetimePreKey.publicKey)
73
+ signedPreKey: decodeBase64(signedPreKey.publicKey),
74
+ signature: decodeBase64(crypto.EdDSA.sign(signedPreKeyHash, this.privateIdentityKey.signatureKey)),
75
+ onetimePreKey: decodeBase64(onetimePreKey.publicKey)
82
76
  };
83
77
  });
84
78
  }
85
79
  digestData(message, associatedData) {
86
80
  return __awaiter(this, void 0, void 0, function* () {
87
81
  //console.debug("Digest Data")
88
- const ephemeralKey = crypto_1.default.ECDH.keyPair();
89
- const signedPreKey = (0, utils_1.encodeBase64)(message.signedPreKey);
90
- const identityKey = types_1.IdentityKey.from(message.identityKey);
91
- if (!crypto_1.default.EdDSA.verify(crypto_1.default.hash(signedPreKey), (0, utils_1.encodeBase64)(message.signature), identityKey.signatureKey))
82
+ const ephemeralKey = crypto.ECDH.keyPair();
83
+ const signedPreKey = encodeBase64(message.signedPreKey);
84
+ const identityKey = IdentityKey.from(message.identityKey);
85
+ if (!crypto.EdDSA.verify(encodeBase64(message.signature), crypto.hash(signedPreKey), identityKey.signatureKey))
92
86
  throw new Error("Signature verification failed");
93
- const onetimePreKey = message.onetimePreKey ? (0, utils_1.encodeBase64)(message.onetimePreKey) : undefined;
94
- const signedPreKeyHash = crypto_1.default.hash(signedPreKey);
95
- const onetimePreKeyHash = onetimePreKey ? crypto_1.default.hash(onetimePreKey) : new Uint8Array();
96
- const derivedKey = crypto_1.default.hkdf(new Uint8Array([
97
- ...crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, signedPreKey),
98
- ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, identityKey.exchangeKey),
99
- ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, signedPreKey),
100
- ...onetimePreKey ? crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, onetimePreKey) : new Uint8Array()
101
- ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength * 3);
102
- const session = new double_ratchet_1.KeySession({ identityKey, remoteKey: identityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength), headerKey: derivedKey.subarray(double_ratchet_1.KeySession.keyLength, double_ratchet_1.KeySession.keyLength * 2), nextHeaderKey: derivedKey.subarray(double_ratchet_1.KeySession.keyLength * 2) });
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()));
87
+ const onetimePreKey = message.onetimePreKey ? encodeBase64(message.onetimePreKey) : undefined;
88
+ const signedPreKeyHash = crypto.hash(signedPreKey);
89
+ const onetimePreKeyHash = onetimePreKey ? crypto.hash(onetimePreKey) : new Uint8Array();
90
+ const derivedKey = crypto.hkdf(new Uint8Array([
91
+ ...crypto.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, signedPreKey),
92
+ ...crypto.ECDH.scalarMult(ephemeralKey.secretKey, identityKey.exchangeKey),
93
+ ...crypto.ECDH.scalarMult(ephemeralKey.secretKey, signedPreKey),
94
+ ...onetimePreKey ? crypto.ECDH.scalarMult(ephemeralKey.secretKey, onetimePreKey) : new Uint8Array()
95
+ ]), new Uint8Array(KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, KeySession.keyLength * 3);
96
+ const session = new KeySession({ identityKey, remoteKey: identityKey.exchangeKey, rootKey: derivedKey.subarray(0, KeySession.keyLength), headerKey: derivedKey.subarray(KeySession.keyLength, KeySession.keyLength * 2), nextHeaderKey: derivedKey.subarray(KeySession.keyLength * 2) });
97
+ const encrypted = encryptData(session, concatBytes(crypto.hash(this.identityKey.toBytes()), crypto.hash(identityKey.toBytes()), associatedData !== null && associatedData !== void 0 ? associatedData : new Uint8Array()));
104
98
  if (!encrypted)
105
99
  throw new Error("Decryption error");
106
100
  return {
@@ -108,10 +102,10 @@ class KeyExchange {
108
102
  message: {
109
103
  version: KeyExchange.version,
110
104
  identityKey: this.identityKey.toString(),
111
- ephemeralKey: (0, utils_1.decodeBase64)(ephemeralKey.publicKey),
112
- signedPreKeyHash: (0, utils_1.decodeBase64)(signedPreKeyHash),
113
- onetimePreKeyHash: (0, utils_1.decodeBase64)(onetimePreKeyHash),
114
- associatedData: (0, utils_1.decodeBase64)(encrypted.toBytes())
105
+ ephemeralKey: decodeBase64(ephemeralKey.publicKey),
106
+ signedPreKeyHash: decodeBase64(signedPreKeyHash),
107
+ onetimePreKeyHash: decodeBase64(onetimePreKeyHash),
108
+ associatedData: decodeBase64(encrypted.toBytes())
115
109
  }
116
110
  };
117
111
  });
@@ -122,23 +116,23 @@ class KeyExchange {
122
116
  const signedPreKey = yield this.storage.get(message.signedPreKeyHash);
123
117
  const hash = message.signedPreKeyHash.concat(message.onetimePreKeyHash);
124
118
  const onetimePreKey = yield this.storage.get(hash);
125
- const identityKey = types_1.IdentityKey.from(message.identityKey);
119
+ const identityKey = IdentityKey.from(message.identityKey);
126
120
  if (!signedPreKey || !onetimePreKey || !message.identityKey || !message.ephemeralKey)
127
121
  throw new Error("ACK message malformed");
128
122
  if (!this.storage.delete(hash))
129
123
  throw new Error("Bundle store deleting error");
130
- const ephemeralKey = (0, utils_1.encodeBase64)(message.ephemeralKey);
131
- const derivedKey = crypto_1.default.hkdf(new Uint8Array([
132
- ...crypto_1.default.ECDH.scalarMult(signedPreKey.secretKey, identityKey.exchangeKey),
133
- ...crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, ephemeralKey),
134
- ...crypto_1.default.ECDH.scalarMult(signedPreKey.secretKey, ephemeralKey),
135
- ...onetimePreKey ? crypto_1.default.ECDH.scalarMult(onetimePreKey.secretKey, ephemeralKey) : new Uint8Array()
136
- ]), new Uint8Array(double_ratchet_1.KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.keyLength * 3);
137
- const session = new double_ratchet_1.KeySession({ identityKey, secretKey: this.privateIdentityKey.exchangeKey, rootKey: derivedKey.subarray(0, double_ratchet_1.KeySession.keyLength), nextHeaderKey: derivedKey.subarray(double_ratchet_1.KeySession.keyLength, double_ratchet_1.KeySession.keyLength * 2), headerKey: derivedKey.subarray(double_ratchet_1.KeySession.keyLength * 2) });
138
- const data = (0, types_1.decryptData)(session, (0, utils_1.encodeBase64)(message.associatedData));
124
+ const ephemeralKey = encodeBase64(message.ephemeralKey);
125
+ const derivedKey = crypto.hkdf(new Uint8Array([
126
+ ...crypto.ECDH.scalarMult(signedPreKey.secretKey, identityKey.exchangeKey),
127
+ ...crypto.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, ephemeralKey),
128
+ ...crypto.ECDH.scalarMult(signedPreKey.secretKey, ephemeralKey),
129
+ ...onetimePreKey ? crypto.ECDH.scalarMult(onetimePreKey.secretKey, ephemeralKey) : new Uint8Array()
130
+ ]), new Uint8Array(KeySession.keyLength).fill(0), KeyExchange.hkdfInfo, KeySession.keyLength * 3);
131
+ const session = new KeySession({ identityKey, secretKey: this.privateIdentityKey.exchangeKey, rootKey: derivedKey.subarray(0, KeySession.keyLength), nextHeaderKey: derivedKey.subarray(KeySession.keyLength, KeySession.keyLength * 2), headerKey: derivedKey.subarray(KeySession.keyLength * 2) });
132
+ const data = decryptData(session, encodeBase64(message.associatedData));
139
133
  if (!data)
140
134
  throw new Error("Error decrypting ACK message");
141
- if (!(0, utils_1.compareBytes)(data.subarray(0, 64), (0, utils_1.concatBytes)(crypto_1.default.hash(identityKey.toBytes()), crypto_1.default.hash(this.identityKey.toBytes()))))
135
+ if (!compareBytes(data.subarray(0, 64), concatBytes(crypto.hash(identityKey.toBytes()), crypto.hash(this.identityKey.toBytes()))))
142
136
  throw new Error("Error verifing Associated Data");
143
137
  return {
144
138
  session,
@@ -147,7 +141,6 @@ class KeyExchange {
147
141
  });
148
142
  }
149
143
  }
150
- exports.KeyExchange = KeyExchange;
151
144
  KeyExchange.version = 1;
152
145
  KeyExchange.hkdfInfo = "freesignal/x3dh/v." + KeyExchange.version;
153
146
  KeyExchange.maxOPK = 10;