react-native-ble-mesh 1.1.1 → 2.0.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.
- package/README.md +288 -172
- package/docs/IOS-BACKGROUND-BLE.md +231 -0
- package/docs/OPTIMIZATION.md +70 -0
- package/docs/SPEC-v2.1.md +308 -0
- package/package.json +1 -1
- package/src/MeshNetwork.js +659 -465
- package/src/constants/index.js +1 -0
- package/src/crypto/AutoCrypto.js +79 -0
- package/src/crypto/CryptoProvider.js +99 -0
- package/src/crypto/index.js +15 -63
- package/src/crypto/providers/ExpoCryptoProvider.js +125 -0
- package/src/crypto/providers/QuickCryptoProvider.js +134 -0
- package/src/crypto/providers/TweetNaClProvider.js +124 -0
- package/src/crypto/providers/index.js +11 -0
- package/src/errors/MeshError.js +2 -1
- package/src/expo/withBLEMesh.js +102 -0
- package/src/hooks/useMesh.js +30 -9
- package/src/hooks/useMessages.js +2 -0
- package/src/index.js +23 -8
- package/src/mesh/dedup/DedupManager.js +36 -10
- package/src/mesh/fragment/Assembler.js +5 -0
- package/src/mesh/index.js +1 -1
- package/src/mesh/monitor/ConnectionQuality.js +408 -0
- package/src/mesh/monitor/NetworkMonitor.js +327 -316
- package/src/mesh/monitor/index.js +7 -3
- package/src/mesh/peer/PeerManager.js +6 -1
- package/src/mesh/router/MessageRouter.js +26 -15
- package/src/mesh/router/RouteTable.js +7 -1
- package/src/mesh/store/StoreAndForwardManager.js +295 -297
- package/src/mesh/store/index.js +1 -1
- package/src/service/BatteryOptimizer.js +282 -278
- package/src/service/EmergencyManager.js +224 -214
- package/src/service/HandshakeManager.js +167 -13
- package/src/service/MeshService.js +72 -6
- package/src/service/SessionManager.js +77 -2
- package/src/service/audio/AudioManager.js +8 -2
- package/src/service/file/FileAssembler.js +106 -0
- package/src/service/file/FileChunker.js +79 -0
- package/src/service/file/FileManager.js +307 -0
- package/src/service/file/FileMessage.js +122 -0
- package/src/service/file/index.js +15 -0
- package/src/service/text/broadcast/BroadcastManager.js +16 -0
- package/src/transport/BLETransport.js +131 -9
- package/src/transport/MockTransport.js +1 -1
- package/src/transport/MultiTransport.js +305 -0
- package/src/transport/WiFiDirectTransport.js +295 -0
- package/src/transport/adapters/NodeBLEAdapter.js +34 -0
- package/src/transport/adapters/RNBLEAdapter.js +56 -1
- package/src/transport/index.js +6 -0
- package/src/utils/compression.js +291 -291
- package/src/crypto/aead.js +0 -189
- package/src/crypto/chacha20.js +0 -181
- package/src/crypto/hkdf.js +0 -187
- package/src/crypto/hmac.js +0 -143
- package/src/crypto/keys/KeyManager.js +0 -271
- package/src/crypto/keys/KeyPair.js +0 -216
- package/src/crypto/keys/SecureStorage.js +0 -219
- package/src/crypto/keys/index.js +0 -32
- package/src/crypto/noise/handshake.js +0 -410
- package/src/crypto/noise/index.js +0 -27
- package/src/crypto/noise/session.js +0 -253
- package/src/crypto/noise/state.js +0 -268
- package/src/crypto/poly1305.js +0 -113
- package/src/crypto/sha256.js +0 -240
- package/src/crypto/x25519.js +0 -154
package/src/crypto/keys/index.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Keys Module
|
|
5
|
-
* Re-exports all key management components.
|
|
6
|
-
* @module crypto/keys
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { KeyPair, KEY_SIZE } = require('./KeyPair');
|
|
10
|
-
const { KeyManager, DEFAULT_IDENTITY_KEY } = require('./KeyManager');
|
|
11
|
-
const {
|
|
12
|
-
SecureStorage,
|
|
13
|
-
MemorySecureStorage,
|
|
14
|
-
createAsyncStorageAdapter,
|
|
15
|
-
createExpoSecureStoreAdapter
|
|
16
|
-
} = require('./SecureStorage');
|
|
17
|
-
|
|
18
|
-
module.exports = {
|
|
19
|
-
// KeyPair
|
|
20
|
-
KeyPair,
|
|
21
|
-
KEY_SIZE,
|
|
22
|
-
|
|
23
|
-
// KeyManager
|
|
24
|
-
KeyManager,
|
|
25
|
-
DEFAULT_IDENTITY_KEY,
|
|
26
|
-
|
|
27
|
-
// SecureStorage
|
|
28
|
-
SecureStorage,
|
|
29
|
-
MemorySecureStorage,
|
|
30
|
-
createAsyncStorageAdapter,
|
|
31
|
-
createExpoSecureStoreAdapter
|
|
32
|
-
};
|
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Noise Protocol XX Handshake Implementation
|
|
5
|
-
*
|
|
6
|
-
* XX Pattern (mutual authentication with transmitted static keys):
|
|
7
|
-
* -> e (initiator sends ephemeral public key)
|
|
8
|
-
* <- e, ee, s, es (responder: ephemeral, DH, encrypted static)
|
|
9
|
-
* -> s, se (initiator: encrypted static, final DH)
|
|
10
|
-
*
|
|
11
|
-
* @module crypto/noise/handshake
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const { SymmetricState, PROTOCOL_NAME } = require('./state');
|
|
15
|
-
const { generateKeyPair, scalarMult } = require('../x25519');
|
|
16
|
-
const { concat } = require('../../utils/bytes');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Handshake state machine states
|
|
20
|
-
* @enum {string}
|
|
21
|
-
*/
|
|
22
|
-
const HandshakeState = {
|
|
23
|
-
INITIAL: 'INITIAL',
|
|
24
|
-
MSG1_WRITTEN: 'MSG1_WRITTEN',
|
|
25
|
-
MSG1_READ: 'MSG1_READ',
|
|
26
|
-
MSG2_WRITTEN: 'MSG2_WRITTEN',
|
|
27
|
-
MSG2_READ: 'MSG2_READ',
|
|
28
|
-
MSG3_WRITTEN: 'MSG3_WRITTEN',
|
|
29
|
-
MSG3_READ: 'MSG3_READ',
|
|
30
|
-
COMPLETE: 'COMPLETE',
|
|
31
|
-
ERROR: 'ERROR'
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Role in the handshake
|
|
36
|
-
* @enum {string}
|
|
37
|
-
*/
|
|
38
|
-
const Role = {
|
|
39
|
-
INITIATOR: 'INITIATOR',
|
|
40
|
-
RESPONDER: 'RESPONDER'
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Public key size in bytes
|
|
45
|
-
* @constant {number}
|
|
46
|
-
*/
|
|
47
|
-
const PUBLIC_KEY_SIZE = 32;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* AEAD tag size in bytes
|
|
51
|
-
* @constant {number}
|
|
52
|
-
*/
|
|
53
|
-
const TAG_SIZE = 16;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* NoiseHandshake implements the XX handshake pattern.
|
|
57
|
-
* @class
|
|
58
|
-
*/
|
|
59
|
-
class NoiseHandshake {
|
|
60
|
-
constructor() {
|
|
61
|
-
/** @type {SymmetricState|null} */
|
|
62
|
-
this._symmetricState = null;
|
|
63
|
-
|
|
64
|
-
/** @type {string} */
|
|
65
|
-
this._state = HandshakeState.INITIAL;
|
|
66
|
-
|
|
67
|
-
/** @type {string|null} */
|
|
68
|
-
this._role = null;
|
|
69
|
-
|
|
70
|
-
/** @type {{publicKey: Uint8Array, secretKey: Uint8Array}|null} */
|
|
71
|
-
this._staticKeyPair = null;
|
|
72
|
-
|
|
73
|
-
/** @type {{publicKey: Uint8Array, secretKey: Uint8Array}|null} */
|
|
74
|
-
this._ephemeralKeyPair = null;
|
|
75
|
-
|
|
76
|
-
/** @type {Uint8Array|null} */
|
|
77
|
-
this._remoteStaticPublicKey = null;
|
|
78
|
-
|
|
79
|
-
/** @type {Uint8Array|null} */
|
|
80
|
-
this._remoteEphemeralPublicKey = null;
|
|
81
|
-
|
|
82
|
-
/** @type {{sendKey: Uint8Array, receiveKey: Uint8Array}|null} */
|
|
83
|
-
this._transportKeys = null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Initializes the handshake as the initiator.
|
|
88
|
-
* @param {{publicKey: Uint8Array, secretKey: Uint8Array}} staticKeyPair
|
|
89
|
-
*/
|
|
90
|
-
initializeInitiator(staticKeyPair) {
|
|
91
|
-
if (this._role !== null) {
|
|
92
|
-
throw new Error('Invalid state: handshake already initialized');
|
|
93
|
-
}
|
|
94
|
-
this._validateState(HandshakeState.INITIAL, 'initializeInitiator');
|
|
95
|
-
this._validateKeyPair(staticKeyPair, 'static');
|
|
96
|
-
|
|
97
|
-
this._role = Role.INITIATOR;
|
|
98
|
-
this._staticKeyPair = staticKeyPair;
|
|
99
|
-
this._symmetricState = new SymmetricState(PROTOCOL_NAME);
|
|
100
|
-
|
|
101
|
-
// Prologue can be empty for basic use
|
|
102
|
-
this._symmetricState.mixHash(new Uint8Array(0));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Initializes the handshake as the responder.
|
|
107
|
-
* @param {{publicKey: Uint8Array, secretKey: Uint8Array}} staticKeyPair
|
|
108
|
-
*/
|
|
109
|
-
initializeResponder(staticKeyPair) {
|
|
110
|
-
if (this._role !== null) {
|
|
111
|
-
throw new Error('Invalid state: handshake already initialized');
|
|
112
|
-
}
|
|
113
|
-
this._validateState(HandshakeState.INITIAL, 'initializeResponder');
|
|
114
|
-
this._validateKeyPair(staticKeyPair, 'static');
|
|
115
|
-
|
|
116
|
-
this._role = Role.RESPONDER;
|
|
117
|
-
this._staticKeyPair = staticKeyPair;
|
|
118
|
-
this._symmetricState = new SymmetricState(PROTOCOL_NAME);
|
|
119
|
-
|
|
120
|
-
// Prologue can be empty for basic use
|
|
121
|
-
this._symmetricState.mixHash(new Uint8Array(0));
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Writes message 1: -> e
|
|
126
|
-
* Initiator sends ephemeral public key.
|
|
127
|
-
* @returns {Uint8Array} Message 1 data
|
|
128
|
-
*/
|
|
129
|
-
writeMessage1() {
|
|
130
|
-
this._validateRole(Role.INITIATOR, 'writeMessage1');
|
|
131
|
-
this._validateState(HandshakeState.INITIAL, 'writeMessage1');
|
|
132
|
-
|
|
133
|
-
// Generate ephemeral key pair
|
|
134
|
-
this._ephemeralKeyPair = generateKeyPair();
|
|
135
|
-
|
|
136
|
-
// e: Mix ephemeral public key into hash
|
|
137
|
-
this._symmetricState.mixHash(this._ephemeralKeyPair.publicKey);
|
|
138
|
-
|
|
139
|
-
this._state = HandshakeState.MSG1_WRITTEN;
|
|
140
|
-
return new Uint8Array(this._ephemeralKeyPair.publicKey);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Reads message 1: -> e
|
|
145
|
-
* Responder receives initiator's ephemeral public key.
|
|
146
|
-
* @param {Uint8Array} data - Message 1 data
|
|
147
|
-
*/
|
|
148
|
-
readMessage1(data) {
|
|
149
|
-
this._validateRole(Role.RESPONDER, 'readMessage1');
|
|
150
|
-
this._validateState(HandshakeState.INITIAL, 'readMessage1');
|
|
151
|
-
|
|
152
|
-
if (data.length < PUBLIC_KEY_SIZE) {
|
|
153
|
-
throw new Error('Message 1 too short');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Extract remote ephemeral public key
|
|
157
|
-
this._remoteEphemeralPublicKey = data.subarray(0, PUBLIC_KEY_SIZE);
|
|
158
|
-
|
|
159
|
-
// e: Mix remote ephemeral into hash
|
|
160
|
-
this._symmetricState.mixHash(this._remoteEphemeralPublicKey);
|
|
161
|
-
|
|
162
|
-
this._state = HandshakeState.MSG1_READ;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Writes message 2: <- e, ee, s, es
|
|
167
|
-
* Responder sends ephemeral, performs DH, sends encrypted static.
|
|
168
|
-
* @returns {Uint8Array} Message 2 data
|
|
169
|
-
*/
|
|
170
|
-
writeMessage2() {
|
|
171
|
-
this._validateRole(Role.RESPONDER, 'writeMessage2');
|
|
172
|
-
this._validateState(HandshakeState.MSG1_READ, 'writeMessage2');
|
|
173
|
-
|
|
174
|
-
// Generate ephemeral key pair
|
|
175
|
-
this._ephemeralKeyPair = generateKeyPair();
|
|
176
|
-
|
|
177
|
-
// e: Mix our ephemeral public key into hash
|
|
178
|
-
this._symmetricState.mixHash(this._ephemeralKeyPair.publicKey);
|
|
179
|
-
|
|
180
|
-
// ee: DH(ephemeral, remoteEphemeral)
|
|
181
|
-
const ee = scalarMult(
|
|
182
|
-
this._ephemeralKeyPair.secretKey,
|
|
183
|
-
this._remoteEphemeralPublicKey
|
|
184
|
-
);
|
|
185
|
-
this._symmetricState.mixKey(ee);
|
|
186
|
-
|
|
187
|
-
// s: Encrypt and send static public key
|
|
188
|
-
const encryptedStatic = this._symmetricState.encryptAndHash(
|
|
189
|
-
this._staticKeyPair.publicKey
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
// es: DH(ephemeral, remoteStatic) - but we dont have it yet in XX
|
|
193
|
-
// Actually in XX responder pattern: es = DH(s, re)
|
|
194
|
-
const es = scalarMult(
|
|
195
|
-
this._staticKeyPair.secretKey,
|
|
196
|
-
this._remoteEphemeralPublicKey
|
|
197
|
-
);
|
|
198
|
-
this._symmetricState.mixKey(es);
|
|
199
|
-
|
|
200
|
-
// Combine: e || encrypted_s
|
|
201
|
-
const message = concat(this._ephemeralKeyPair.publicKey, encryptedStatic);
|
|
202
|
-
|
|
203
|
-
this._state = HandshakeState.MSG2_WRITTEN;
|
|
204
|
-
return message;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Reads message 2: <- e, ee, s, es
|
|
209
|
-
* Initiator receives and processes responder's message 2.
|
|
210
|
-
* @param {Uint8Array} data - Message 2 data
|
|
211
|
-
*/
|
|
212
|
-
readMessage2(data) {
|
|
213
|
-
this._validateRole(Role.INITIATOR, 'readMessage2');
|
|
214
|
-
this._validateState(HandshakeState.MSG1_WRITTEN, 'readMessage2');
|
|
215
|
-
|
|
216
|
-
const expectedSize = PUBLIC_KEY_SIZE + PUBLIC_KEY_SIZE + TAG_SIZE;
|
|
217
|
-
if (data.length < expectedSize) {
|
|
218
|
-
throw new Error('Message 2 too short');
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// e: Extract and mix remote ephemeral
|
|
222
|
-
this._remoteEphemeralPublicKey = data.subarray(0, PUBLIC_KEY_SIZE);
|
|
223
|
-
this._symmetricState.mixHash(this._remoteEphemeralPublicKey);
|
|
224
|
-
|
|
225
|
-
// ee: DH(ephemeral, remoteEphemeral)
|
|
226
|
-
const ee = scalarMult(
|
|
227
|
-
this._ephemeralKeyPair.secretKey,
|
|
228
|
-
this._remoteEphemeralPublicKey
|
|
229
|
-
);
|
|
230
|
-
this._symmetricState.mixKey(ee);
|
|
231
|
-
|
|
232
|
-
// s: Decrypt remote static public key
|
|
233
|
-
const encryptedStatic = data.subarray(
|
|
234
|
-
PUBLIC_KEY_SIZE,
|
|
235
|
-
PUBLIC_KEY_SIZE + PUBLIC_KEY_SIZE + TAG_SIZE
|
|
236
|
-
);
|
|
237
|
-
this._remoteStaticPublicKey = this._symmetricState.decryptAndHash(
|
|
238
|
-
encryptedStatic
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
// es: DH(e, rs)
|
|
242
|
-
const es = scalarMult(
|
|
243
|
-
this._ephemeralKeyPair.secretKey,
|
|
244
|
-
this._remoteStaticPublicKey
|
|
245
|
-
);
|
|
246
|
-
this._symmetricState.mixKey(es);
|
|
247
|
-
|
|
248
|
-
this._state = HandshakeState.MSG2_READ;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Writes message 3: -> s, se
|
|
253
|
-
* Initiator sends encrypted static and performs final DH.
|
|
254
|
-
* @returns {Uint8Array} Message 3 data
|
|
255
|
-
*/
|
|
256
|
-
writeMessage3() {
|
|
257
|
-
this._validateRole(Role.INITIATOR, 'writeMessage3');
|
|
258
|
-
this._validateState(HandshakeState.MSG2_READ, 'writeMessage3');
|
|
259
|
-
|
|
260
|
-
// s: Encrypt and send static public key
|
|
261
|
-
const encryptedStatic = this._symmetricState.encryptAndHash(
|
|
262
|
-
this._staticKeyPair.publicKey
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
// se: DH(s, re)
|
|
266
|
-
const se = scalarMult(
|
|
267
|
-
this._staticKeyPair.secretKey,
|
|
268
|
-
this._remoteEphemeralPublicKey
|
|
269
|
-
);
|
|
270
|
-
this._symmetricState.mixKey(se);
|
|
271
|
-
|
|
272
|
-
// Split to get transport keys
|
|
273
|
-
const { sendKey, receiveKey } = this._symmetricState.split();
|
|
274
|
-
this._transportKeys = { sendKey, receiveKey };
|
|
275
|
-
|
|
276
|
-
this._state = HandshakeState.MSG3_WRITTEN;
|
|
277
|
-
return encryptedStatic;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Reads message 3: -> s, se
|
|
282
|
-
* Responder receives and processes initiator's message 3.
|
|
283
|
-
* @param {Uint8Array} data - Message 3 data
|
|
284
|
-
*/
|
|
285
|
-
readMessage3(data) {
|
|
286
|
-
this._validateRole(Role.RESPONDER, 'readMessage3');
|
|
287
|
-
this._validateState(HandshakeState.MSG2_WRITTEN, 'readMessage3');
|
|
288
|
-
|
|
289
|
-
const expectedSize = PUBLIC_KEY_SIZE + TAG_SIZE;
|
|
290
|
-
if (data.length < expectedSize) {
|
|
291
|
-
throw new Error('Message 3 too short');
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// s: Decrypt remote static public key
|
|
295
|
-
this._remoteStaticPublicKey = this._symmetricState.decryptAndHash(data);
|
|
296
|
-
|
|
297
|
-
// se: DH(e, rs)
|
|
298
|
-
const se = scalarMult(
|
|
299
|
-
this._ephemeralKeyPair.secretKey,
|
|
300
|
-
this._remoteStaticPublicKey
|
|
301
|
-
);
|
|
302
|
-
this._symmetricState.mixKey(se);
|
|
303
|
-
|
|
304
|
-
// Split to get transport keys (reversed for responder)
|
|
305
|
-
const { sendKey, receiveKey } = this._symmetricState.split();
|
|
306
|
-
this._transportKeys = { sendKey: receiveKey, receiveKey: sendKey };
|
|
307
|
-
|
|
308
|
-
this._state = HandshakeState.MSG3_READ;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Checks if the handshake is complete.
|
|
313
|
-
* @returns {boolean} True if handshake is complete
|
|
314
|
-
*/
|
|
315
|
-
isComplete() {
|
|
316
|
-
return this._state === HandshakeState.MSG3_WRITTEN ||
|
|
317
|
-
this._state === HandshakeState.MSG3_READ;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Gets the NoiseSession for transport encryption.
|
|
322
|
-
* @returns {NoiseSession} Transport session
|
|
323
|
-
* @throws {Error} If handshake is not complete
|
|
324
|
-
*/
|
|
325
|
-
getSession() {
|
|
326
|
-
if (!this.isComplete()) {
|
|
327
|
-
throw new Error('Handshake not complete');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const { NoiseSession } = require('./session');
|
|
331
|
-
return new NoiseSession(
|
|
332
|
-
this._transportKeys.sendKey,
|
|
333
|
-
this._transportKeys.receiveKey,
|
|
334
|
-
this._role === Role.INITIATOR
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Gets the remote peer's static public key.
|
|
340
|
-
* @returns {Uint8Array|null} Remote static public key or null
|
|
341
|
-
*/
|
|
342
|
-
getRemotePublicKey() {
|
|
343
|
-
return this._remoteStaticPublicKey
|
|
344
|
-
? new Uint8Array(this._remoteStaticPublicKey)
|
|
345
|
-
: null;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Gets the current handshake hash (channel binding).
|
|
350
|
-
* @returns {Uint8Array} Handshake hash
|
|
351
|
-
*/
|
|
352
|
-
getHandshakeHash() {
|
|
353
|
-
if (!this._symmetricState) {
|
|
354
|
-
throw new Error('Handshake not initialized');
|
|
355
|
-
}
|
|
356
|
-
return this._symmetricState.getHandshakeHash();
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Validates that the current state matches expected.
|
|
361
|
-
* @param {string} expected - Expected state
|
|
362
|
-
* @param {string} operation - Operation name for error message
|
|
363
|
-
* @private
|
|
364
|
-
*/
|
|
365
|
-
_validateState(expected, operation) {
|
|
366
|
-
if (this._state !== expected) {
|
|
367
|
-
throw new Error(
|
|
368
|
-
`Invalid state for ${operation}: expected ${expected}, got ${this._state}`
|
|
369
|
-
);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Validates that the role matches expected.
|
|
375
|
-
* @param {string} expected - Expected role
|
|
376
|
-
* @param {string} operation - Operation name for error message
|
|
377
|
-
* @private
|
|
378
|
-
*/
|
|
379
|
-
_validateRole(expected, operation) {
|
|
380
|
-
if (this._role !== expected) {
|
|
381
|
-
throw new Error(
|
|
382
|
-
`Invalid role for ${operation}: expected ${expected}, got ${this._role}`
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* Validates a key pair.
|
|
389
|
-
* @param {object} keyPair - Key pair to validate
|
|
390
|
-
* @param {string} name - Name for error message
|
|
391
|
-
* @private
|
|
392
|
-
*/
|
|
393
|
-
_validateKeyPair(keyPair, name) {
|
|
394
|
-
if (!keyPair || !keyPair.publicKey || !keyPair.secretKey) {
|
|
395
|
-
throw new Error(`Invalid ${name} key pair`);
|
|
396
|
-
}
|
|
397
|
-
if (keyPair.publicKey.length !== PUBLIC_KEY_SIZE) {
|
|
398
|
-
throw new Error(`${name} public key must be ${PUBLIC_KEY_SIZE} bytes`);
|
|
399
|
-
}
|
|
400
|
-
if (keyPair.secretKey.length !== PUBLIC_KEY_SIZE) {
|
|
401
|
-
throw new Error(`${name} secret key must be ${PUBLIC_KEY_SIZE} bytes`);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
module.exports = {
|
|
407
|
-
NoiseHandshake,
|
|
408
|
-
HandshakeState,
|
|
409
|
-
Role
|
|
410
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Noise Protocol Module
|
|
5
|
-
* Re-exports all Noise Protocol components.
|
|
6
|
-
* @module crypto/noise
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { SymmetricState, PROTOCOL_NAME } = require('./state');
|
|
10
|
-
const { NoiseHandshake, HandshakeState, Role } = require('./handshake');
|
|
11
|
-
const { NoiseSession, MAX_NONCE, REKEY_THRESHOLD } = require('./session');
|
|
12
|
-
|
|
13
|
-
module.exports = {
|
|
14
|
-
// State management
|
|
15
|
-
SymmetricState,
|
|
16
|
-
PROTOCOL_NAME,
|
|
17
|
-
|
|
18
|
-
// Handshake
|
|
19
|
-
NoiseHandshake,
|
|
20
|
-
HandshakeState,
|
|
21
|
-
Role,
|
|
22
|
-
|
|
23
|
-
// Transport session
|
|
24
|
-
NoiseSession,
|
|
25
|
-
MAX_NONCE,
|
|
26
|
-
REKEY_THRESHOLD
|
|
27
|
-
};
|