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