@libp2p/pnet 2.0.47-6059227cb → 2.0.47-87bc8d4fb
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/index.min.js +2 -2
- package/dist/index.min.js.map +4 -4
- package/dist/src/crypto.d.ts +9 -20
- package/dist/src/crypto.d.ts.map +1 -1
- package/dist/src/crypto.js +21 -57
- package/dist/src/crypto.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +29 -24
- package/dist/src/index.js.map +1 -1
- package/package.json +14 -6
- package/src/crypto.ts +21 -69
- package/src/index.ts +42 -27
package/dist/src/crypto.d.ts
CHANGED
|
@@ -1,24 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { AbortOptions, MultiaddrConnection } from '@libp2p/interface';
|
|
3
|
-
import type { MessageStreamInit, SendResult } from '@libp2p/utils';
|
|
1
|
+
import type { Source } from 'it-stream-types';
|
|
4
2
|
import type { Uint8ArrayList } from 'uint8arraylist';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
private inboundXor;
|
|
14
|
-
private outboundXor;
|
|
15
|
-
constructor(init: BoxMessageStreamInit);
|
|
16
|
-
sendClose(options?: AbortOptions): Promise<void>;
|
|
17
|
-
sendData(data: Uint8ArrayList): SendResult;
|
|
18
|
-
sendReset(err: Error): void;
|
|
19
|
-
sendPause(): void;
|
|
20
|
-
sendResume(): void;
|
|
21
|
-
}
|
|
3
|
+
/**
|
|
4
|
+
* Creates a stream iterable to encrypt messages in a private network
|
|
5
|
+
*/
|
|
6
|
+
export declare function createBoxStream(nonce: Uint8Array, psk: Uint8Array): (source: Source<Uint8Array | Uint8ArrayList>) => AsyncGenerator<Uint8Array | Uint8ArrayList>;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a stream iterable to decrypt messages in a private network
|
|
9
|
+
*/
|
|
10
|
+
export declare function createUnboxStream(nonce: Uint8Array, psk: Uint8Array): (source: Source<Uint8Array>) => AsyncGenerator<Uint8Array<ArrayBuffer>, void, unknown>;
|
|
22
11
|
/**
|
|
23
12
|
* Decode the version 1 psk from the given Uint8Array
|
|
24
13
|
*/
|
package/dist/src/crypto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD;;GAEG;AACH,wBAAgB,eAAe,CAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,GAAG,cAAc,CAAC,KAAK,cAAc,CAAC,UAAU,GAAG,cAAc,CAAC,CAQjK;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,IAC3D,QAAQ,MAAM,CAAC,UAAU,CAAC,4DAOnC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAE,SAAS,EAAE,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,GAAG,EAAE,UAAU,CAAA;CAAE,CAyB/H"}
|
package/dist/src/crypto.js
CHANGED
|
@@ -1,65 +1,29 @@
|
|
|
1
|
-
import { AbstractMultiaddrConnection } from '@libp2p/utils';
|
|
2
1
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
|
|
3
2
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
|
|
4
3
|
import xsalsa20 from 'xsalsa20';
|
|
5
4
|
import * as Errors from './errors.js';
|
|
6
5
|
import { KEY_LENGTH } from './key-generator.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
this.maConn.addEventListener('close', (evt) => {
|
|
32
|
-
if (evt.error != null) {
|
|
33
|
-
if (evt.local) {
|
|
34
|
-
this.abort(evt.error);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
this.onRemoteReset();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
this.onTransportClosed();
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
async sendClose(options) {
|
|
46
|
-
await this.maConn.close(options);
|
|
47
|
-
}
|
|
48
|
-
sendData(data) {
|
|
49
|
-
return {
|
|
50
|
-
sentBytes: data.byteLength,
|
|
51
|
-
canSendMore: this.maConn.send(this.outboundXor.update(data.subarray()))
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
sendReset(err) {
|
|
55
|
-
this.maConn.abort(err);
|
|
56
|
-
}
|
|
57
|
-
sendPause() {
|
|
58
|
-
this.maConn.pause();
|
|
59
|
-
}
|
|
60
|
-
sendResume() {
|
|
61
|
-
this.maConn.resume();
|
|
62
|
-
}
|
|
6
|
+
/**
|
|
7
|
+
* Creates a stream iterable to encrypt messages in a private network
|
|
8
|
+
*/
|
|
9
|
+
export function createBoxStream(nonce, psk) {
|
|
10
|
+
const xor = xsalsa20(nonce, psk);
|
|
11
|
+
return (source) => (async function* () {
|
|
12
|
+
for await (const chunk of source) {
|
|
13
|
+
yield Uint8Array.from(xor.update(chunk.subarray()));
|
|
14
|
+
}
|
|
15
|
+
})();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a stream iterable to decrypt messages in a private network
|
|
19
|
+
*/
|
|
20
|
+
export function createUnboxStream(nonce, psk) {
|
|
21
|
+
return (source) => (async function* () {
|
|
22
|
+
const xor = xsalsa20(nonce, psk);
|
|
23
|
+
for await (const chunk of source) {
|
|
24
|
+
yield Uint8Array.from(xor.update(chunk.subarray()));
|
|
25
|
+
}
|
|
26
|
+
})();
|
|
63
27
|
}
|
|
64
28
|
/**
|
|
65
29
|
* Decode the version 1 psk from the given Uint8Array
|
package/dist/src/crypto.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,QAAQ,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAI/C;;GAEG;AACH,MAAM,UAAU,eAAe,CAAE,KAAiB,EAAE,GAAe;IACjE,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAEhC,OAAO,CAAC,MAA2C,EAAE,EAAE,CAAC,CAAC,KAAK,SAAU,CAAC;QACvE,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QACrD,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAE,KAAiB,EAAE,GAAe;IACnE,OAAO,CAAC,MAA0B,EAAE,EAAE,CAAC,CAAC,KAAK,SAAU,CAAC;QACtD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAEhC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QACrD,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAE,SAAqB;IAChD,IAAI,CAAC;QACH,0DAA0D;QAC1D,6DAA6D;QAC7D,yDAAyD;QACzD,2DAA2D;QAC3D,0BAA0B;QAC1B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;QACvE,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAA;QAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAA;QAC9B,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAA;QAClC,MAAM,GAAG,GAAG,oBAAoB,CAAC,SAAS,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAA;QAE3D,IAAI,GAAG,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACrC,CAAC;QAED,OAAO;YACL,GAAG,EAAE,MAAM;YACX,SAAS,EAAE,KAAK;YAChB,GAAG;SACJ,CAAA;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IACrC,CAAC;AACH,CAAC"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -73,5 +73,5 @@ export interface ProtectorInit {
|
|
|
73
73
|
export interface ProtectorComponents {
|
|
74
74
|
logger: ComponentLogger;
|
|
75
75
|
}
|
|
76
|
-
export declare function preSharedKey(init: ProtectorInit): () => ConnectionProtector;
|
|
76
|
+
export declare function preSharedKey(init: ProtectorInit): (components: ProtectorComponents) => ConnectionProtector;
|
|
77
77
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAcH,OAAO,KAAK,EAAE,eAAe,EAAU,mBAAmB,EAAuB,MAAM,mBAAmB,CAAA;AAG1G,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,GAAG,EAAE,UAAU,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAA;CACxB;AA4ED,wBAAgB,YAAY,CAAE,IAAI,EAAE,aAAa,GAAG,CAAC,UAAU,EAAE,mBAAmB,KAAK,mBAAmB,CAE3G"}
|
package/dist/src/index.js
CHANGED
|
@@ -57,19 +57,24 @@
|
|
|
57
57
|
*/
|
|
58
58
|
import { randomBytes } from '@libp2p/crypto';
|
|
59
59
|
import { InvalidParametersError } from '@libp2p/interface';
|
|
60
|
-
import { byteStream } from '
|
|
61
|
-
import
|
|
60
|
+
import { byteStream } from 'it-byte-stream';
|
|
61
|
+
import map from 'it-map';
|
|
62
|
+
import { duplexPair } from 'it-pair/duplex';
|
|
63
|
+
import { pipe } from 'it-pipe';
|
|
64
|
+
import { createBoxStream, createUnboxStream, decodeV1PSK } from './crypto.js';
|
|
62
65
|
import { NONCE_LENGTH } from './key-generator.js';
|
|
63
66
|
export { generateKey } from './key-generator.js';
|
|
64
67
|
class PreSharedKeyConnectionProtector {
|
|
65
68
|
tag;
|
|
69
|
+
log;
|
|
66
70
|
psk;
|
|
67
71
|
timeout;
|
|
68
72
|
/**
|
|
69
73
|
* Takes a Private Shared Key (psk) and provides a `protect` method
|
|
70
74
|
* for wrapping existing connections in a private encryption stream.
|
|
71
75
|
*/
|
|
72
|
-
constructor(init) {
|
|
76
|
+
constructor(components, init) {
|
|
77
|
+
this.log = components.logger.forComponent('libp2p:pnet');
|
|
73
78
|
this.timeout = init.timeout ?? 1000;
|
|
74
79
|
const decodedPSK = decodeV1PSK(init.psk);
|
|
75
80
|
this.psk = decodedPSK.psk;
|
|
@@ -81,40 +86,40 @@ class PreSharedKeyConnectionProtector {
|
|
|
81
86
|
* between its two peers from the PSK the Protector instance was
|
|
82
87
|
* created with.
|
|
83
88
|
*/
|
|
84
|
-
async protect(connection
|
|
89
|
+
async protect(connection) {
|
|
85
90
|
if (connection == null) {
|
|
86
91
|
throw new InvalidParametersError('No connection for the handshake provided');
|
|
87
92
|
}
|
|
88
93
|
// Exchange nonces
|
|
89
|
-
|
|
90
|
-
log('protecting the connection');
|
|
94
|
+
this.log('protecting the connection');
|
|
91
95
|
const localNonce = randomBytes(NONCE_LENGTH);
|
|
92
|
-
|
|
93
|
-
options = {
|
|
94
|
-
signal: AbortSignal.timeout(this.timeout)
|
|
95
|
-
};
|
|
96
|
-
}
|
|
96
|
+
const signal = AbortSignal.timeout(this.timeout);
|
|
97
97
|
const bytes = byteStream(connection);
|
|
98
|
-
const [result] = await Promise.all([
|
|
98
|
+
const [, result] = await Promise.all([
|
|
99
|
+
bytes.write(localNonce, {
|
|
100
|
+
signal
|
|
101
|
+
}),
|
|
99
102
|
bytes.read({
|
|
100
103
|
bytes: NONCE_LENGTH,
|
|
101
|
-
|
|
102
|
-
})
|
|
103
|
-
bytes.write(localNonce, options)
|
|
104
|
+
signal
|
|
105
|
+
})
|
|
104
106
|
]);
|
|
105
107
|
const remoteNonce = result.subarray();
|
|
106
108
|
// Create the boxing/unboxing pipe
|
|
107
|
-
log('exchanged nonces');
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
this.log('exchanged nonces');
|
|
110
|
+
const [internal, external] = duplexPair();
|
|
111
|
+
pipe(external,
|
|
112
|
+
// Encrypt all outbound traffic
|
|
113
|
+
createBoxStream(localNonce, this.psk), bytes.unwrap(), (source) => map(source, (buf) => buf.subarray()),
|
|
114
|
+
// Decrypt all inbound traffic
|
|
115
|
+
createUnboxStream(remoteNonce, this.psk), external).catch(this.log.error);
|
|
116
|
+
return {
|
|
117
|
+
...connection,
|
|
118
|
+
...internal
|
|
119
|
+
};
|
|
115
120
|
}
|
|
116
121
|
}
|
|
117
122
|
export function preSharedKey(init) {
|
|
118
|
-
return () => new PreSharedKeyConnectionProtector(init);
|
|
123
|
+
return (components) => new PreSharedKeyConnectionProtector(components, init);
|
|
119
124
|
}
|
|
120
125
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/pnet",
|
|
3
|
-
"version": "2.0.47-
|
|
3
|
+
"version": "2.0.47-87bc8d4fb",
|
|
4
4
|
"description": "Implementation of Connection protection management via a shared secret",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/pnet#readme",
|
|
@@ -43,17 +43,25 @@
|
|
|
43
43
|
"doc-check": "aegir doc-check"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@libp2p/crypto": "5.1.8-
|
|
47
|
-
"@libp2p/interface": "2.11.0-
|
|
48
|
-
"
|
|
46
|
+
"@libp2p/crypto": "5.1.8-87bc8d4fb",
|
|
47
|
+
"@libp2p/interface": "2.11.0-87bc8d4fb",
|
|
48
|
+
"it-byte-stream": "^2.0.2",
|
|
49
|
+
"it-map": "^3.1.3",
|
|
50
|
+
"it-pair": "^2.0.6",
|
|
51
|
+
"it-pipe": "^3.0.1",
|
|
52
|
+
"it-stream-types": "^2.0.2",
|
|
49
53
|
"uint8arraylist": "^2.4.8",
|
|
50
54
|
"uint8arrays": "^5.1.0",
|
|
51
55
|
"xsalsa20": "^1.2.0"
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
58
|
+
"@libp2p/interface-compliance-tests": "6.5.0-87bc8d4fb",
|
|
59
|
+
"@libp2p/logger": "5.2.0-87bc8d4fb",
|
|
60
|
+
"@libp2p/peer-id": "5.1.9-87bc8d4fb",
|
|
61
|
+
"@multiformats/multiaddr": "^12.4.4",
|
|
54
62
|
"@types/xsalsa20": "^1.1.3",
|
|
55
|
-
"aegir": "^47.0.
|
|
56
|
-
"
|
|
63
|
+
"aegir": "^47.0.14",
|
|
64
|
+
"it-all": "^3.0.8"
|
|
57
65
|
},
|
|
58
66
|
"sideEffects": false
|
|
59
67
|
}
|
package/src/crypto.ts
CHANGED
|
@@ -1,83 +1,35 @@
|
|
|
1
|
-
import { AbstractMultiaddrConnection } from '@libp2p/utils'
|
|
2
1
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
3
2
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
4
3
|
import xsalsa20 from 'xsalsa20'
|
|
5
4
|
import * as Errors from './errors.js'
|
|
6
5
|
import { KEY_LENGTH } from './key-generator.js'
|
|
7
|
-
import type {
|
|
8
|
-
import type { MessageStreamInit, SendResult } from '@libp2p/utils'
|
|
6
|
+
import type { Source } from 'it-stream-types'
|
|
9
7
|
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
psk
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class BoxMessageStream extends AbstractMultiaddrConnection {
|
|
19
|
-
private maConn: MultiaddrConnection
|
|
20
|
-
private inboundXor: xsalsa20.Xor
|
|
21
|
-
private outboundXor: xsalsa20.Xor
|
|
22
|
-
|
|
23
|
-
constructor (init: BoxMessageStreamInit) {
|
|
24
|
-
super({
|
|
25
|
-
...init,
|
|
26
|
-
remoteAddr: init.maConn.remoteAddr,
|
|
27
|
-
direction: init.maConn.direction
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
this.inboundXor = xsalsa20(init.remoteNonce, init.psk)
|
|
31
|
-
this.outboundXor = xsalsa20(init.localNonce, init.psk)
|
|
32
|
-
this.maConn = init.maConn
|
|
33
|
-
|
|
34
|
-
this.maConn.addEventListener('message', (evt) => {
|
|
35
|
-
const data = evt.data
|
|
36
|
-
|
|
37
|
-
if (data instanceof Uint8Array) {
|
|
38
|
-
this.onData(this.inboundXor.update(data))
|
|
39
|
-
} else {
|
|
40
|
-
for (const buf of data) {
|
|
41
|
-
this.onData(this.inboundXor.update(buf))
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
this.maConn.addEventListener('close', (evt) => {
|
|
47
|
-
if (evt.error != null) {
|
|
48
|
-
if (evt.local) {
|
|
49
|
-
this.abort(evt.error)
|
|
50
|
-
} else {
|
|
51
|
-
this.onRemoteReset()
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
this.onTransportClosed()
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async sendClose (options?: AbortOptions): Promise<void> {
|
|
60
|
-
await this.maConn.close(options)
|
|
61
|
-
}
|
|
9
|
+
/**
|
|
10
|
+
* Creates a stream iterable to encrypt messages in a private network
|
|
11
|
+
*/
|
|
12
|
+
export function createBoxStream (nonce: Uint8Array, psk: Uint8Array): (source: Source<Uint8Array | Uint8ArrayList>) => AsyncGenerator<Uint8Array | Uint8ArrayList> {
|
|
13
|
+
const xor = xsalsa20(nonce, psk)
|
|
62
14
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
canSendMore: this.maConn.send(this.outboundXor.update(data.subarray()))
|
|
15
|
+
return (source: Source<Uint8Array | Uint8ArrayList>) => (async function * () {
|
|
16
|
+
for await (const chunk of source) {
|
|
17
|
+
yield Uint8Array.from(xor.update(chunk.subarray()))
|
|
67
18
|
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
sendReset (err: Error): void {
|
|
71
|
-
this.maConn.abort(err)
|
|
72
|
-
}
|
|
19
|
+
})()
|
|
20
|
+
}
|
|
73
21
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Creates a stream iterable to decrypt messages in a private network
|
|
24
|
+
*/
|
|
25
|
+
export function createUnboxStream (nonce: Uint8Array, psk: Uint8Array) {
|
|
26
|
+
return (source: Source<Uint8Array>) => (async function * () {
|
|
27
|
+
const xor = xsalsa20(nonce, psk)
|
|
77
28
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
29
|
+
for await (const chunk of source) {
|
|
30
|
+
yield Uint8Array.from(xor.update(chunk.subarray()))
|
|
31
|
+
}
|
|
32
|
+
})()
|
|
81
33
|
}
|
|
82
34
|
|
|
83
35
|
/**
|
package/src/index.ts
CHANGED
|
@@ -58,10 +58,18 @@
|
|
|
58
58
|
|
|
59
59
|
import { randomBytes } from '@libp2p/crypto'
|
|
60
60
|
import { InvalidParametersError } from '@libp2p/interface'
|
|
61
|
-
import { byteStream } from '
|
|
62
|
-
import
|
|
61
|
+
import { byteStream } from 'it-byte-stream'
|
|
62
|
+
import map from 'it-map'
|
|
63
|
+
import { duplexPair } from 'it-pair/duplex'
|
|
64
|
+
import { pipe } from 'it-pipe'
|
|
65
|
+
import {
|
|
66
|
+
createBoxStream,
|
|
67
|
+
createUnboxStream,
|
|
68
|
+
decodeV1PSK
|
|
69
|
+
} from './crypto.js'
|
|
63
70
|
import { NONCE_LENGTH } from './key-generator.js'
|
|
64
|
-
import type { ComponentLogger, ConnectionProtector, MultiaddrConnection
|
|
71
|
+
import type { ComponentLogger, Logger, ConnectionProtector, MultiaddrConnection } from '@libp2p/interface'
|
|
72
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
65
73
|
|
|
66
74
|
export { generateKey } from './key-generator.js'
|
|
67
75
|
|
|
@@ -85,6 +93,7 @@ export interface ProtectorComponents {
|
|
|
85
93
|
|
|
86
94
|
class PreSharedKeyConnectionProtector implements ConnectionProtector {
|
|
87
95
|
public tag: string
|
|
96
|
+
private readonly log: Logger
|
|
88
97
|
private readonly psk: Uint8Array
|
|
89
98
|
private readonly timeout: number
|
|
90
99
|
|
|
@@ -92,7 +101,8 @@ class PreSharedKeyConnectionProtector implements ConnectionProtector {
|
|
|
92
101
|
* Takes a Private Shared Key (psk) and provides a `protect` method
|
|
93
102
|
* for wrapping existing connections in a private encryption stream.
|
|
94
103
|
*/
|
|
95
|
-
constructor (init: ProtectorInit) {
|
|
104
|
+
constructor (components: ProtectorComponents, init: ProtectorInit) {
|
|
105
|
+
this.log = components.logger.forComponent('libp2p:pnet')
|
|
96
106
|
this.timeout = init.timeout ?? 1000
|
|
97
107
|
|
|
98
108
|
const decodedPSK = decodeV1PSK(init.psk)
|
|
@@ -107,49 +117,54 @@ class PreSharedKeyConnectionProtector implements ConnectionProtector {
|
|
|
107
117
|
* between its two peers from the PSK the Protector instance was
|
|
108
118
|
* created with.
|
|
109
119
|
*/
|
|
110
|
-
async protect (connection: MultiaddrConnection
|
|
120
|
+
async protect (connection: MultiaddrConnection): Promise<MultiaddrConnection> {
|
|
111
121
|
if (connection == null) {
|
|
112
122
|
throw new InvalidParametersError('No connection for the handshake provided')
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
// Exchange nonces
|
|
116
|
-
|
|
117
|
-
log('protecting the connection')
|
|
126
|
+
this.log('protecting the connection')
|
|
118
127
|
const localNonce = randomBytes(NONCE_LENGTH)
|
|
119
128
|
|
|
120
|
-
|
|
121
|
-
options = {
|
|
122
|
-
signal: AbortSignal.timeout(this.timeout)
|
|
123
|
-
}
|
|
124
|
-
}
|
|
129
|
+
const signal = AbortSignal.timeout(this.timeout)
|
|
125
130
|
|
|
126
131
|
const bytes = byteStream(connection)
|
|
127
132
|
|
|
128
133
|
const [
|
|
129
|
-
result
|
|
134
|
+
, result
|
|
130
135
|
] = await Promise.all([
|
|
136
|
+
bytes.write(localNonce, {
|
|
137
|
+
signal
|
|
138
|
+
}),
|
|
131
139
|
bytes.read({
|
|
132
140
|
bytes: NONCE_LENGTH,
|
|
133
|
-
|
|
134
|
-
})
|
|
135
|
-
bytes.write(localNonce, options)
|
|
141
|
+
signal
|
|
142
|
+
})
|
|
136
143
|
])
|
|
137
144
|
|
|
138
145
|
const remoteNonce = result.subarray()
|
|
139
146
|
|
|
140
147
|
// Create the boxing/unboxing pipe
|
|
141
|
-
log('exchanged nonces')
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
this.log('exchanged nonces')
|
|
149
|
+
const [internal, external] = duplexPair<Uint8Array | Uint8ArrayList>()
|
|
150
|
+
pipe(
|
|
151
|
+
external,
|
|
152
|
+
// Encrypt all outbound traffic
|
|
153
|
+
createBoxStream(localNonce, this.psk),
|
|
154
|
+
bytes.unwrap(),
|
|
155
|
+
(source) => map(source, (buf) => buf.subarray()),
|
|
156
|
+
// Decrypt all inbound traffic
|
|
157
|
+
createUnboxStream(remoteNonce, this.psk),
|
|
158
|
+
external
|
|
159
|
+
).catch(this.log.error)
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
...connection,
|
|
163
|
+
...internal
|
|
164
|
+
}
|
|
150
165
|
}
|
|
151
166
|
}
|
|
152
167
|
|
|
153
|
-
export function preSharedKey (init: ProtectorInit): () => ConnectionProtector {
|
|
154
|
-
return () => new PreSharedKeyConnectionProtector(init)
|
|
168
|
+
export function preSharedKey (init: ProtectorInit): (components: ProtectorComponents) => ConnectionProtector {
|
|
169
|
+
return (components) => new PreSharedKeyConnectionProtector(components, init)
|
|
155
170
|
}
|