@freesignal/protocol 0.7.10 → 0.8.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.
@@ -16,7 +16,7 @@
16
16
  * You should have received a copy of the GNU General Public License
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
- import { IdentityKey, UserId } from "./types";
19
+ import { IdentityKey, UserId } from "./types.js";
20
20
  export interface ExportedKeySession {
21
21
  identityKey: string;
22
22
  secretKey: string;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * FreeSignal Protocol
4
3
  *
@@ -17,31 +16,26 @@
17
16
  * You should have received a copy of the GNU General Public License
18
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
19
18
  */
20
- var __importDefault = (this && this.__importDefault) || function (mod) {
21
- return (mod && mod.__esModule) ? mod : { "default": mod };
22
- };
23
- Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.KeySession = void 0;
25
- const crypto_1 = __importDefault(require("@freesignal/crypto"));
26
- const utils_1 = require("@freesignal/utils");
27
- const types_1 = require("./types");
19
+ import crypto from "@freesignal/crypto";
20
+ import { decodeBase64, encodeBase64, compareBytes } from "@freesignal/utils";
21
+ import { IdentityKey } from "./types.js";
28
22
  /**
29
23
  * Represents a secure Double Ratchet session.
30
24
  * Used for forward-secure encryption and decryption of messages.
31
25
  */
32
- class KeySession {
26
+ export class KeySession {
33
27
  constructor({ identityKey, secretKey, remoteKey, rootKey, headerKey, nextHeaderKey }) {
34
28
  this.headerKeys = new Map();
35
29
  this.previousKeys = new KeyMap();
36
30
  this.identityKey = identityKey;
37
31
  this.rootKey = rootKey;
38
- this.sessionTag = (0, utils_1.decodeBase64)(crypto_1.default.hkdf(rootKey, new Uint8Array(32).fill(0), "/freesignal/session-authtag", 32));
39
- this.keyPair = crypto_1.default.ECDH.keyPair(secretKey);
32
+ this.sessionTag = decodeBase64(crypto.hkdf(rootKey, new Uint8Array(32).fill(0), "/freesignal/session-authtag", 32));
33
+ this.keyPair = crypto.ECDH.keyPair(secretKey);
40
34
  if (headerKey)
41
35
  this.headerKey = headerKey;
42
36
  if (nextHeaderKey) {
43
37
  this.nextHeaderKey = nextHeaderKey;
44
- this.headerKeys.set((0, utils_1.decodeBase64)(crypto_1.default.hash(nextHeaderKey)), nextHeaderKey);
38
+ this.headerKeys.set(decodeBase64(crypto.hash(nextHeaderKey)), nextHeaderKey);
45
39
  }
46
40
  if (remoteKey) {
47
41
  this.sendingChain = this.getChain(remoteKey, this.headerKey);
@@ -52,10 +46,10 @@ class KeySession {
52
46
  return this.identityKey.userId;
53
47
  }
54
48
  getChain(remoteKey, headerKey, previousCount) {
55
- const sharedKey = crypto_1.default.ECDH.scalarMult(this.keyPair.secretKey, remoteKey);
49
+ const sharedKey = crypto.ECDH.scalarMult(this.keyPair.secretKey, remoteKey);
56
50
  if (!this.rootKey)
57
- this.rootKey = crypto_1.default.hash(sharedKey);
58
- const hashkey = crypto_1.default.hkdf(sharedKey, this.rootKey, KeySession.info, KeySession.keyLength * 3);
51
+ this.rootKey = crypto.hash(sharedKey);
52
+ const hashkey = crypto.hkdf(sharedKey, this.rootKey, KeySession.info, KeySession.keyLength * 3);
59
53
  this.rootKey = hashkey.subarray(0, KeySession.keyLength);
60
54
  return new KeyChain(this.publicKey, remoteKey, hashkey.subarray(KeySession.keyLength, KeySession.keyLength * 2), hashkey.subarray(KeySession.keyLength * 2), headerKey, previousCount);
61
55
  }
@@ -79,17 +73,17 @@ class KeySession {
79
73
  }
80
74
  getReceivingKey(encryptionKeys) {
81
75
  var _a, _b, _c, _d, _e, _f, _g, _h;
82
- if (!this.previousKeys.has((0, utils_1.decodeBase64)(encryptionKeys.publicKey) + encryptionKeys.count.toString())) {
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())) {
76
+ if (!this.previousKeys.has(decodeBase64(encryptionKeys.publicKey) + encryptionKeys.count.toString())) {
77
+ if (!compareBytes(encryptionKeys.publicKey, (_b = (_a = this.receivingChain) === null || _a === void 0 ? void 0 : _a.remoteKey) !== null && _b !== void 0 ? _b : new Uint8Array())) {
84
78
  while (this.receivingChain && this.receivingChain.count < encryptionKeys.previous) {
85
79
  const key = this.receivingChain.getKey();
86
- this.previousKeys.set((0, utils_1.decodeBase64)(this.receivingChain.remoteKey) + this.receivingChain.count.toString(), key);
80
+ this.previousKeys.set(decodeBase64(this.receivingChain.remoteKey) + this.receivingChain.count.toString(), key);
87
81
  }
88
82
  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, (_e = this.receivingChain) === null || _e === void 0 ? void 0 : _e.count);
89
- this.headerKeys.set((0, utils_1.decodeBase64)(crypto_1.default.hash(this.receivingChain.nextHeaderKey)), this.receivingChain.nextHeaderKey);
83
+ this.headerKeys.set(decodeBase64(crypto.hash(this.receivingChain.nextHeaderKey)), this.receivingChain.nextHeaderKey);
90
84
  if (this.nextHeaderKey)
91
85
  this.nextHeaderKey = undefined;
92
- this.keyPair = crypto_1.default.ECDH.keyPair();
86
+ this.keyPair = crypto.ECDH.keyPair();
93
87
  this.sendingChain = this.getChain(encryptionKeys.publicKey, (_f = this.headerKey) !== null && _f !== void 0 ? _f : (_g = this.sendingChain) === null || _g === void 0 ? void 0 : _g.nextHeaderKey, (_h = this.sendingChain) === null || _h === void 0 ? void 0 : _h.count);
94
88
  if (this.headerKey)
95
89
  this.headerKey = undefined;
@@ -98,10 +92,10 @@ class KeySession {
98
92
  throw new Error("Error initializing receivingChain");
99
93
  while (this.receivingChain.count < encryptionKeys.count) {
100
94
  const key = this.receivingChain.getKey();
101
- this.previousKeys.set((0, utils_1.decodeBase64)(this.receivingChain.remoteKey) + this.receivingChain.count.toString(), key);
95
+ this.previousKeys.set(decodeBase64(this.receivingChain.remoteKey) + this.receivingChain.count.toString(), key);
102
96
  }
103
97
  }
104
- return this.previousKeys.get((0, utils_1.decodeBase64)(encryptionKeys.publicKey) + encryptionKeys.count.toString());
98
+ return this.previousKeys.get(decodeBase64(encryptionKeys.publicKey) + encryptionKeys.count.toString());
105
99
  }
106
100
  /**
107
101
  * Whether both the sending and receiving chains are initialized.
@@ -118,11 +112,11 @@ class KeySession {
118
112
  var _a, _b;
119
113
  return {
120
114
  identityKey: this.identityKey.toString(),
121
- secretKey: (0, utils_1.decodeBase64)(this.keyPair.secretKey),
122
- rootKey: (0, utils_1.decodeBase64)(this.rootKey),
115
+ secretKey: decodeBase64(this.keyPair.secretKey),
116
+ rootKey: decodeBase64(this.rootKey),
123
117
  sendingChain: (_a = this.sendingChain) === null || _a === void 0 ? void 0 : _a.toJSON(),
124
118
  receivingChain: (_b = this.receivingChain) === null || _b === void 0 ? void 0 : _b.toJSON(),
125
- headerKey: this.headerKey ? (0, utils_1.decodeBase64)(this.headerKey) : undefined,
119
+ headerKey: this.headerKey ? decodeBase64(this.headerKey) : undefined,
126
120
  headerKeys: Array.from(this.headerKeys.entries()),
127
121
  previousKeys: Array.from(this.previousKeys.entries())
128
122
  };
@@ -134,14 +128,13 @@ class KeySession {
134
128
  * @returns session with the state parsed.
135
129
  */
136
130
  static from(data) {
137
- const session = new KeySession({ identityKey: types_1.IdentityKey.from(data.identityKey), secretKey: (0, utils_1.encodeBase64)(data.secretKey), rootKey: (0, utils_1.encodeBase64)(data.rootKey) });
131
+ const session = new KeySession({ identityKey: IdentityKey.from(data.identityKey), secretKey: encodeBase64(data.secretKey), rootKey: encodeBase64(data.rootKey) });
138
132
  session.sendingChain = data.sendingChain ? KeyChain.from(data.sendingChain) : undefined;
139
133
  session.receivingChain = data.receivingChain ? KeyChain.from(data.receivingChain) : undefined;
140
134
  session.previousKeys = new KeyMap(data.previousKeys);
141
135
  return session;
142
136
  }
143
137
  }
144
- exports.KeySession = KeySession;
145
138
  KeySession.keyLength = 32;
146
139
  KeySession.version = 1;
147
140
  KeySession.info = "/freesignal/double-ratchet/v0." + KeySession.version;
@@ -159,7 +152,7 @@ class KeyChain {
159
152
  getKey() {
160
153
  if (++this._count >= KeySession.maxCount)
161
154
  throw new Error("SendingChain count too big");
162
- const hash = crypto_1.default.hkdf(this.chainKey, new Uint8Array(KeySession.keyLength).fill(0), KeySession.info, KeySession.keyLength * 2);
155
+ const hash = crypto.hkdf(this.chainKey, new Uint8Array(KeySession.keyLength).fill(0), KeySession.info, KeySession.keyLength * 2);
163
156
  this.chainKey = hash.subarray(0, KeySession.keyLength);
164
157
  return hash.subarray(KeySession.keyLength);
165
158
  }
@@ -171,18 +164,18 @@ class KeyChain {
171
164
  }
172
165
  toJSON() {
173
166
  return {
174
- publicKey: (0, utils_1.decodeBase64)(this.publicKey),
175
- remoteKey: (0, utils_1.decodeBase64)(this.remoteKey),
176
- headerKey: this.headerKey ? (0, utils_1.decodeBase64)(this.headerKey) : undefined,
177
- nextHeaderKey: (0, utils_1.decodeBase64)(this.nextHeaderKey),
178
- chainKey: (0, utils_1.decodeBase64)(this.chainKey),
167
+ publicKey: decodeBase64(this.publicKey),
168
+ remoteKey: decodeBase64(this.remoteKey),
169
+ headerKey: this.headerKey ? decodeBase64(this.headerKey) : undefined,
170
+ nextHeaderKey: decodeBase64(this.nextHeaderKey),
171
+ chainKey: decodeBase64(this.chainKey),
179
172
  count: this.count,
180
173
  previousCount: this.previousCount
181
174
  };
182
175
  }
183
176
  static from(obj) {
184
177
  //
185
- 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);
178
+ const chain = new KeyChain(encodeBase64(obj.publicKey), encodeBase64(obj.remoteKey), encodeBase64(obj.chainKey), encodeBase64(obj.nextHeaderKey), obj.headerKey ? encodeBase64(obj.headerKey) : undefined, obj.previousCount);
186
179
  chain._count = obj.count;
187
180
  return chain;
188
181
  }
package/dist/index.d.ts CHANGED
@@ -17,9 +17,9 @@
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
19
  import { LocalStorage, Crypto, Database, KeyExchangeDataBundle } from "@freesignal/interfaces";
20
- import { ExportedKeySession } from "./double-ratchet";
21
- import { PrivateIdentityKey } from "./types";
22
- import { BootstrapRequest, FreeSignalNode } from "./node";
20
+ import { ExportedKeySession } from "./double-ratchet.js";
21
+ import { PrivateIdentityKey } from "./types.js";
22
+ import { BootstrapRequest, FreeSignalNode } from "./node.js";
23
23
  /**
24
24
  * Generates identity key
25
25
  *
@@ -35,4 +35,4 @@ export declare function createNode(storage: Database<{
35
35
  bundles: LocalStorage<string, KeyExchangeDataBundle>;
36
36
  bootstraps: LocalStorage<string, BootstrapRequest>;
37
37
  }>, privateIdentityKey?: PrivateIdentityKey): FreeSignalNode;
38
- export * from "./types";
38
+ export * from "./types.js";
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * FreeSignal Protocol
4
3
  *
@@ -17,45 +16,26 @@
17
16
  * You should have received a copy of the GNU General Public License
18
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
19
18
  */
20
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
- if (k2 === undefined) k2 = k;
22
- var desc = Object.getOwnPropertyDescriptor(m, k);
23
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
- desc = { enumerable: true, get: function() { return m[k]; } };
25
- }
26
- Object.defineProperty(o, k2, desc);
27
- }) : (function(o, m, k, k2) {
28
- if (k2 === undefined) k2 = k;
29
- o[k2] = m[k];
30
- }));
31
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
32
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
33
- };
34
- var __importDefault = (this && this.__importDefault) || function (mod) {
35
- return (mod && mod.__esModule) ? mod : { "default": mod };
36
- };
37
- Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.createIdentity = createIdentity;
39
- exports.createNode = createNode;
40
- const crypto_1 = __importDefault(require("@freesignal/crypto"));
41
- const types_1 = require("./types");
42
- const node_1 = require("./node");
19
+ import crypto from "@freesignal/crypto";
20
+ import { PrivateIdentityKey } from "./types.js";
21
+ import { FreeSignalNode } from "./node.js";
43
22
  /**
44
23
  * Generates identity key
45
24
  *
46
25
  * @param seed - Seed to generate the key.
47
26
  * @returns An object containing readonly signing and box key pairs.
48
27
  */
49
- function createIdentity(seed) {
50
- seed !== null && seed !== void 0 ? seed : (seed = crypto_1.default.randomBytes(crypto_1.default.EdDSA.seedLength));
51
- const signatureSeed = crypto_1.default.hkdf(seed, new Uint8Array(crypto_1.default.EdDSA.seedLength).fill(0), "identity-ed25519", crypto_1.default.EdDSA.seedLength);
52
- const exchangeSeed = crypto_1.default.hkdf(seed, new Uint8Array(crypto_1.default.ECDH.secretKeyLength).fill(0), "identity-x25519", crypto_1.default.ECDH.secretKeyLength);
53
- const signatureKeyPair = crypto_1.default.EdDSA.keyPairFromSeed(signatureSeed);
54
- const exchangeKeyPair = crypto_1.default.ECDH.keyPair(exchangeSeed);
55
- return types_1.PrivateIdentityKey.from(signatureKeyPair.secretKey, exchangeKeyPair.secretKey);
28
+ export function createIdentity(seed) {
29
+ const seedLength = 32;
30
+ seed !== null && seed !== void 0 ? seed : (seed = crypto.randomBytes(seedLength));
31
+ const signatureSeed = crypto.hkdf(seed, new Uint8Array(seedLength).fill(0), "identity-ed25519", seedLength);
32
+ const exchangeSeed = crypto.hkdf(seed, new Uint8Array(crypto.ECDH.secretKeyLength).fill(0), "identity-x25519", crypto.ECDH.secretKeyLength);
33
+ const signatureKeyPair = crypto.EdDSA.keyPairFromSeed(signatureSeed);
34
+ const exchangeKeyPair = crypto.ECDH.keyPair(exchangeSeed);
35
+ return PrivateIdentityKey.from(signatureKeyPair.secretKey, exchangeKeyPair.secretKey);
56
36
  }
57
37
  /** */
58
- function createNode(storage, privateIdentityKey) {
59
- return new node_1.FreeSignalNode(storage, privateIdentityKey);
38
+ export function createNode(storage, privateIdentityKey) {
39
+ return new FreeSignalNode(storage, privateIdentityKey);
60
40
  }
61
- __exportStar(require("./types"), exports);
41
+ export * from "./types.js";
package/dist/node.d.ts CHANGED
@@ -17,18 +17,17 @@
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, EncryptedDatagram, IdentityKey, PrivateIdentityKey, Protocols, UserId } from "./types";
21
- import { KeyExchange } from "./x3dh";
22
- import { ExportedKeySession, KeySession } from "./double-ratchet";
23
- import EventEmitter, { EventCallback } from "easyemitter.ts";
20
+ import { Datagram, EncryptedDatagram, IdentityKey, PrivateIdentityKey, Protocols, UserId } from "./types.js";
21
+ import { KeyExchange } from "./x3dh.js";
22
+ import { ExportedKeySession, KeySession } from "./double-ratchet.js";
23
+ import { EventEmitter, EventCallback } from "easyemitter.ts";
24
24
  export declare class BootstrapRequest extends EventEmitter<'change', BootstrapRequest> {
25
25
  #private;
26
26
  readonly senderId: UserId | string;
27
- private readonly keyExchangeData;
28
- constructor(senderId: UserId | string, keyExchangeData: KeyExchangeData);
27
+ readonly data: KeyExchangeData;
28
+ constructor(senderId: UserId | string, data: KeyExchangeData);
29
29
  onChange: EventCallback<BootstrapRequest, this>;
30
30
  get status(): "pending" | "accepted" | "denied";
31
- get data(): KeyExchangeData | undefined;
32
31
  accept(): void;
33
32
  deny(): void;
34
33
  }
package/dist/node.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * FreeSignal Protocol
4
3
  *
@@ -37,24 +36,19 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
37
36
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
38
37
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
39
38
  };
40
- var __importDefault = (this && this.__importDefault) || function (mod) {
41
- return (mod && mod.__esModule) ? mod : { "default": mod };
42
- };
43
39
  var _BootstrapRequest_status;
44
- Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.FreeSignalNode = exports.BootstrapRequest = void 0;
46
- const types_1 = require("./types");
47
- const x3dh_1 = require("./x3dh");
48
- const double_ratchet_1 = require("./double-ratchet");
49
- const _1 = require(".");
50
- const utils_1 = require("@freesignal/utils");
51
- const crypto_1 = __importDefault(require("@freesignal/crypto"));
52
- const easyemitter_ts_1 = __importDefault(require("easyemitter.ts"));
53
- class BootstrapRequest extends easyemitter_ts_1.default {
54
- constructor(senderId, keyExchangeData) {
40
+ import { Datagram, decryptData, DiscoverType, encryptData, EncryptedDatagram, IdentityKey, Protocols, UserId } from "./types.js";
41
+ import { KeyExchange } from "./x3dh.js";
42
+ import { KeySession } from "./double-ratchet.js";
43
+ import { createIdentity } from "./index.js";
44
+ import { decodeData, encodeData, compareBytes, concatBytes, decodeBase64 } from "@freesignal/utils";
45
+ import crypto from "@freesignal/crypto";
46
+ import { EventEmitter } from "easyemitter.ts";
47
+ export class BootstrapRequest extends EventEmitter {
48
+ constructor(senderId, data) {
55
49
  super();
56
50
  this.senderId = senderId;
57
- this.keyExchangeData = keyExchangeData;
51
+ this.data = data;
58
52
  _BootstrapRequest_status.set(this, 'pending');
59
53
  this.onChange = () => { };
60
54
  this.on('change', (data, emitter) => this.onChange(data, emitter));
@@ -62,9 +56,6 @@ class BootstrapRequest extends easyemitter_ts_1.default {
62
56
  get status() {
63
57
  return __classPrivateFieldGet(this, _BootstrapRequest_status, "f");
64
58
  }
65
- get data() {
66
- return __classPrivateFieldGet(this, _BootstrapRequest_status, "f") === 'accepted' ? this.keyExchangeData : undefined;
67
- }
68
59
  accept() {
69
60
  if (this.status === 'pending') {
70
61
  __classPrivateFieldSet(this, _BootstrapRequest_status, 'accepted', "f");
@@ -78,24 +69,23 @@ class BootstrapRequest extends easyemitter_ts_1.default {
78
69
  }
79
70
  }
80
71
  }
81
- exports.BootstrapRequest = BootstrapRequest;
82
72
  _BootstrapRequest_status = new WeakMap();
83
- class FreeSignalNode {
73
+ export class FreeSignalNode {
84
74
  constructor(storage, privateIdentityKey) {
85
75
  this.discovers = new Set();
86
- this.emitter = new easyemitter_ts_1.default();
76
+ this.emitter = new EventEmitter();
87
77
  this.messageHandler = (data) => this.onMessage({ session: data.session, payload: data.payload });
88
78
  this.sendHandler = (data) => this.onSend(data.datagram.toBytes());
89
- this.handshakeHandler = (data) => { var _a; return this.onHandshake(types_1.UserId.from((_a = data.session) === null || _a === void 0 ? void 0 : _a.userId)); };
79
+ this.handshakeHandler = (data) => { var _a; return this.onHandshake(UserId.from((_a = data.session) === null || _a === void 0 ? void 0 : _a.userId)); };
90
80
  this.bootstrapHandler = (data) => this.onRequest(data.request);
91
81
  this.onMessage = () => { };
92
82
  this.onSend = () => { };
93
83
  this.onHandshake = () => { };
94
84
  this.onRequest = () => { };
95
- this.privateIdentityKey = privateIdentityKey !== null && privateIdentityKey !== void 0 ? privateIdentityKey : (0, _1.createIdentity)();
85
+ this.privateIdentityKey = privateIdentityKey !== null && privateIdentityKey !== void 0 ? privateIdentityKey : createIdentity();
96
86
  this.sessions = new SessionMap(storage.sessions);
97
87
  this.users = storage.users;
98
- this.keyExchange = new x3dh_1.KeyExchange(storage.keyExchange, this.privateIdentityKey);
88
+ this.keyExchange = new KeyExchange(storage.keyExchange, this.privateIdentityKey);
99
89
  this.bundles = storage.bundles;
100
90
  this.bootstraps = storage.bootstraps;
101
91
  this.emitter.on('message', this.messageHandler);
@@ -129,39 +119,39 @@ class FreeSignalNode {
129
119
  const session = yield this.sessions.get(sessionTag);
130
120
  if (!session)
131
121
  throw new Error("Session not found for sessionTag: " + sessionTag);
132
- const encrypted = (0, types_1.encryptData)(session, data);
122
+ const encrypted = encryptData(session, data);
133
123
  this.sessions.set(receiverId.toString(), session);
134
- return { session, userId: types_1.UserId.from(receiverId), datagram: new types_1.EncryptedDatagram(protocol, session.sessionTag, encrypted).sign(this.privateIdentityKey.signatureKey) };
124
+ return { session, userId: UserId.from(receiverId), datagram: new EncryptedDatagram(protocol, session.sessionTag, encrypted).sign(this.privateIdentityKey.signatureKey) };
135
125
  });
136
126
  }
137
127
  sendHandshake(data) {
138
128
  return __awaiter(this, void 0, void 0, function* () {
139
- if (data instanceof double_ratchet_1.KeySession) {
129
+ if (data instanceof KeySession) {
140
130
  //console.debug("Sending Handshake Ack");
141
131
  const session = yield this.sessions.get(data.sessionTag);
142
132
  if (!session)
143
133
  throw new Error("Session not found for sessionTag: " + data.sessionTag);
144
- this.emitter.emit('send', yield this.encrypt(session.userId, types_1.Protocols.HANDSHAKE, crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, session.identityKey.exchangeKey)));
134
+ this.emitter.emit('send', yield this.encrypt(session.userId, Protocols.HANDSHAKE, crypto.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, session.identityKey.exchangeKey)));
145
135
  return;
146
136
  }
147
137
  //console.debug("Sending Handshake Syn");
148
- const { session, message } = yield this.keyExchange.digestData(data, (0, utils_1.encodeData)(yield this.keyExchange.generateBundle()));
138
+ const { session, message } = yield this.keyExchange.digestData(data, encodeData(yield this.keyExchange.generateBundle()));
149
139
  yield this.sessions.set(session.sessionTag, session);
150
140
  yield this.users.set(session.userId.toString(), session.sessionTag);
151
- const datagram = new types_1.Datagram(types_1.Protocols.HANDSHAKE, (0, utils_1.encodeData)(message), session.sessionTag).sign(this.privateIdentityKey.signatureKey);
141
+ const datagram = new Datagram(Protocols.HANDSHAKE, encodeData(message), session.sessionTag).sign(this.privateIdentityKey.signatureKey);
152
142
  this.emitter.emit('send', { session, datagram, userId: session.userId });
153
143
  });
154
144
  }
155
145
  sendData(receiverId, data) {
156
146
  return __awaiter(this, void 0, void 0, function* () {
157
147
  //console.debug("Sending Data");
158
- this.emitter.emit('send', yield this.encrypt(receiverId, types_1.Protocols.MESSAGE, (0, utils_1.encodeData)(data)));
148
+ this.emitter.emit('send', yield this.encrypt(receiverId, Protocols.MESSAGE, encodeData(data)));
159
149
  });
160
150
  }
161
151
  sendRelay(relayId, receiverId, data) {
162
152
  return __awaiter(this, void 0, void 0, function* () {
163
153
  //console.debug("Sending Relay");
164
- this.emitter.emit('send', yield this.encrypt(relayId, types_1.Protocols.RELAY, (0, utils_1.concatBytes)(types_1.UserId.from(receiverId).toBytes(), data.toBytes())));
154
+ this.emitter.emit('send', yield this.encrypt(relayId, Protocols.RELAY, concatBytes(UserId.from(receiverId).toBytes(), data.toBytes())));
165
155
  });
166
156
  }
167
157
  sendPing(receiverId) {
@@ -173,28 +163,28 @@ class FreeSignalNode {
173
163
  const session = yield this.sessions.get(sessionTag);
174
164
  if (!session)
175
165
  throw new Error("Session not found for sessionTag: " + sessionTag);
176
- const datagram = new types_1.Datagram(types_1.Protocols.PING, undefined, session.sessionTag);
166
+ const datagram = new Datagram(Protocols.PING, undefined, session.sessionTag);
177
167
  this.emitter.emit('send', { session, datagram, userId: session.userId });
178
168
  });
179
169
  }
180
170
  sendDiscover(receiverId, discoverId) {
181
171
  return __awaiter(this, void 0, void 0, function* () {
182
172
  //console.debug("Sending Discover");
183
- if (receiverId instanceof types_1.UserId)
173
+ if (receiverId instanceof UserId)
184
174
  receiverId = receiverId.toString();
185
- if (discoverId instanceof types_1.UserId)
175
+ if (discoverId instanceof UserId)
186
176
  discoverId = discoverId.toString();
187
177
  const message = {
188
- type: types_1.DiscoverType.REQUEST,
178
+ type: DiscoverType.REQUEST,
189
179
  discoverId
190
180
  };
191
181
  this.discovers.add(receiverId);
192
- this.emitter.emit('send', yield this.encrypt(receiverId, types_1.Protocols.DISCOVER, (0, utils_1.encodeData)(message)));
182
+ this.emitter.emit('send', yield this.encrypt(receiverId, Protocols.DISCOVER, encodeData(message)));
193
183
  });
194
184
  }
195
185
  packBootstrap() {
196
186
  return __awaiter(this, void 0, void 0, function* () {
197
- return new types_1.Datagram(types_1.Protocols.BOOTSTRAP, (0, utils_1.encodeData)(yield this.keyExchange.generateData()));
187
+ return new Datagram(Protocols.BOOTSTRAP, encodeData(yield this.keyExchange.generateData()));
198
188
  });
199
189
  }
200
190
  sendBootstrap(receiverId) {
@@ -203,12 +193,12 @@ class FreeSignalNode {
203
193
  if (yield this.sessions.has(receiverId.toString()))
204
194
  throw new Error("Session exists");
205
195
  const datagram = yield this.packBootstrap();
206
- this.emitter.emit('send', { datagram, userId: types_1.UserId.from(receiverId) });
196
+ this.emitter.emit('send', { datagram, userId: UserId.from(receiverId) });
207
197
  });
208
198
  }
209
199
  decrypt(datagram) {
210
200
  return __awaiter(this, void 0, void 0, function* () {
211
- datagram = types_1.EncryptedDatagram.from(datagram);
201
+ datagram = EncryptedDatagram.from(datagram);
212
202
  if (!datagram.sessionTag)
213
203
  throw new Error("Datagram not encrypted");
214
204
  const session = yield this.sessions.get(datagram.sessionTag);
@@ -218,14 +208,14 @@ class FreeSignalNode {
218
208
  throw new Error("Signature not verified");
219
209
  if (!datagram.payload)
220
210
  throw new Error("Missing payload");
221
- const decrypted = (0, types_1.decryptData)(session, datagram.payload);
211
+ const decrypted = decryptData(session, datagram.payload);
222
212
  this.sessions.set(datagram.sessionTag, session);
223
213
  return { session, payload: decrypted };
224
214
  });
225
215
  }
226
216
  openHandshake(datagram) {
227
217
  return __awaiter(this, void 0, void 0, function* () {
228
- const encrypted = types_1.EncryptedDatagram.from(datagram);
218
+ const encrypted = EncryptedDatagram.from(datagram);
229
219
  if (!encrypted.payload)
230
220
  throw new Error("Missing payload");
231
221
  if (yield this.sessions.has(encrypted.sessionTag)) {
@@ -234,28 +224,28 @@ class FreeSignalNode {
234
224
  const { payload } = yield this.decrypt(encrypted);
235
225
  if (!session)
236
226
  throw new Error("Session not found for sessionTag: " + encrypted.sessionTag);
237
- if (!(0, utils_1.compareBytes)(payload, crypto_1.default.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, session.identityKey.exchangeKey)))
227
+ if (!compareBytes(payload, crypto.ECDH.scalarMult(this.privateIdentityKey.exchangeKey, session.identityKey.exchangeKey)))
238
228
  throw new Error("Error validating handshake data");
239
229
  return 'ack';
240
230
  }
241
231
  //console.debug("Opening Handshake Syn");
242
- const data = (0, utils_1.decodeData)(encrypted.payload);
243
- if (!encrypted.verify(types_1.IdentityKey.from(data.identityKey).signatureKey))
232
+ const data = decodeData(encrypted.payload);
233
+ if (!encrypted.verify(IdentityKey.from(data.identityKey).signatureKey))
244
234
  throw new Error("Signature not verified");
245
235
  const { session, associatedData } = yield this.keyExchange.digestMessage(data);
246
236
  yield this.sessions.set(session.sessionTag, session);
247
237
  yield this.users.set(session.userId.toString(), session.sessionTag);
248
- yield this.bundles.set(session.userId.toString(), (0, utils_1.decodeData)(associatedData));
238
+ yield this.bundles.set(session.userId.toString(), decodeData(associatedData));
249
239
  return 'syn';
250
240
  });
251
241
  }
252
242
  open(datagram) {
253
243
  return __awaiter(this, void 0, void 0, function* () {
254
244
  if (datagram instanceof Uint8Array)
255
- datagram = types_1.Datagram.from(datagram);
245
+ datagram = Datagram.from(datagram);
256
246
  switch (datagram.protocol) {
257
- case types_1.Protocols.HANDSHAKE: {
258
- const encrypted = types_1.EncryptedDatagram.from(datagram);
247
+ case Protocols.HANDSHAKE: {
248
+ const encrypted = EncryptedDatagram.from(datagram);
259
249
  if (!encrypted.payload)
260
250
  throw new Error("Missing payload");
261
251
  if ((yield this.openHandshake(datagram)) === 'ack')
@@ -267,28 +257,28 @@ class FreeSignalNode {
267
257
  this.emitter.emit('handshake', { session });
268
258
  return;
269
259
  }
270
- case types_1.Protocols.MESSAGE:
260
+ case Protocols.MESSAGE:
271
261
  //console.debug("Opening Message");
272
262
  this.emitter.emit('message', yield this.decrypt(datagram));
273
263
  return;
274
- case types_1.Protocols.RELAY: {
264
+ case Protocols.RELAY: {
275
265
  //console.debug("Opening Relay");
276
266
  const opened = yield this.decrypt(datagram);
277
- const userId = (0, utils_1.decodeBase64)(opened.payload.subarray(0, types_1.UserId.keyLength));
267
+ const userId = decodeBase64(opened.payload.subarray(0, UserId.keyLength));
278
268
  const sessionTag = yield this.users.get(userId);
279
269
  if (!sessionTag)
280
270
  throw new Error("Session not found for user: " + userId);
281
271
  const session = yield this.sessions.get(sessionTag);
282
272
  if (!session)
283
273
  throw new Error("Session not found for sessionTag: " + datagram.sessionTag);
284
- this.emitter.emit('send', { session, datagram: types_1.Datagram.from(opened.payload.slice(types_1.UserId.keyLength)), userId: session.userId });
274
+ this.emitter.emit('send', { session, datagram: Datagram.from(opened.payload.slice(UserId.keyLength)), userId: session.userId });
285
275
  return;
286
276
  }
287
- case types_1.Protocols.DISCOVER: {
277
+ case Protocols.DISCOVER: {
288
278
  //console.debug("Opening Discover");
289
279
  const { session, payload } = yield this.decrypt(datagram);
290
- const message = (0, utils_1.decodeData)(payload);
291
- if (message.type === types_1.DiscoverType.REQUEST && message.discoverId && !(yield this.sessions.has(message.discoverId))) {
280
+ const message = decodeData(payload);
281
+ if (message.type === DiscoverType.REQUEST && message.discoverId && !(yield this.sessions.has(message.discoverId))) {
292
282
  let data;
293
283
  if (message.discoverId === this.userId.toString()) {
294
284
  data = yield this.keyExchange.generateData();
@@ -311,34 +301,36 @@ class FreeSignalNode {
311
301
  onetimePreKey
312
302
  };
313
303
  }
314
- const response = { type: types_1.DiscoverType.RESPONSE, discoverId: message.discoverId, data };
315
- this.emitter.emit('send', yield this.encrypt(session.userId, types_1.Protocols.DISCOVER, (0, utils_1.encodeData)(response)));
304
+ const response = { type: DiscoverType.RESPONSE, discoverId: message.discoverId, data };
305
+ this.emitter.emit('send', yield this.encrypt(session.userId, Protocols.DISCOVER, encodeData(response)));
316
306
  }
317
- else if (message.type === types_1.DiscoverType.RESPONSE && this.discovers.has(message.discoverId)) {
307
+ else if (message.type === DiscoverType.RESPONSE && this.discovers.has(message.discoverId)) {
318
308
  this.discovers.delete(message.discoverId);
319
309
  if (message.data)
320
310
  yield this.sendHandshake(message.data);
321
311
  }
322
312
  return;
323
313
  }
324
- case types_1.Protocols.BOOTSTRAP: {
314
+ case Protocols.BOOTSTRAP: {
325
315
  //console.debug("Opening Bootstrap");
326
316
  if (!datagram.payload)
327
317
  throw new Error("Invalid Bootstrap");
328
- const keyExchangeData = (0, utils_1.decodeData)(datagram.payload);
329
- const userId = types_1.UserId.fromKey(keyExchangeData.identityKey);
318
+ const keyExchangeData = decodeData(datagram.payload);
319
+ const userId = UserId.fromKey(keyExchangeData.identityKey);
330
320
  const request = new BootstrapRequest(userId, keyExchangeData);
321
+ let sended = false;
331
322
  request.onChange = (request) => {
332
- if (!request.data)
333
- throw new Error("Error sending handshake");
334
- this.sendHandshake(request.data);
323
+ if (request.status === 'accepted' && !sended) {
324
+ sended = true;
325
+ this.sendHandshake(request.data);
326
+ }
335
327
  };
336
328
  yield this.bootstraps.set(userId.toString(), request);
337
329
  this.emitter.emit('bootstrap', { request });
338
330
  return;
339
331
  }
340
- case types_1.Protocols.PING:
341
- datagram = types_1.EncryptedDatagram.from(datagram);
332
+ case Protocols.PING:
333
+ datagram = EncryptedDatagram.from(datagram);
342
334
  const session = yield this.sessions.get(datagram.sessionTag);
343
335
  if (!session)
344
336
  throw new Error("Session not found for sessionTag: " + datagram.sessionTag);
@@ -350,7 +342,6 @@ class FreeSignalNode {
350
342
  });
351
343
  }
352
344
  }
353
- exports.FreeSignalNode = FreeSignalNode;
354
345
  class SessionMap {
355
346
  constructor(storage, maxSize = 50) {
356
347
  this.storage = storage;
@@ -368,7 +359,7 @@ class SessionMap {
368
359
  const sessionData = yield this.storage.get(key);
369
360
  if (!sessionData)
370
361
  return undefined;
371
- return double_ratchet_1.KeySession.from(sessionData);
362
+ return KeySession.from(sessionData);
372
363
  }
373
364
  return session;
374
365
  });
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 type { LocalStorage, Encodable, KeyExchangeData } from "@freesignal/interfaces";
20
- import { EncryptionKeys, KeySession } from "./double-ratchet";
20
+ import { EncryptionKeys, KeySession } from "./double-ratchet.js";
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 {
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;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@freesignal/protocol",
3
- "version": "0.7.10",
3
+ "version": "0.8.0",
4
4
  "description": "Signal Protocol implementation in javascript",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "author": "Christian Braghette",
7
- "type": "commonjs",
7
+ "type": "module",
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/index.js",
@@ -34,10 +34,10 @@
34
34
  "prepare": "tsc"
35
35
  },
36
36
  "dependencies": {
37
- "@freesignal/crypto": "^0.3.0",
38
- "@freesignal/interfaces": "^0.2.0",
39
- "@freesignal/utils": "^1.4.1",
40
- "easyemitter.ts": "^1.0.3"
37
+ "@freesignal/crypto": "^0.4.2",
38
+ "@freesignal/interfaces": "^0.3.0",
39
+ "@freesignal/utils": "^1.5.1",
40
+ "easyemitter.ts": "^1.1.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^24.2.1"