@libp2p/pnet 1.0.1 → 2.0.0-18dd3cb26
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 +20 -5
- package/dist/index.min.js +2 -15
- package/dist/src/crypto.d.ts +2 -1
- package/dist/src/crypto.d.ts.map +1 -1
- package/dist/src/crypto.js +2 -2
- package/dist/src/crypto.js.map +1 -1
- package/dist/src/errors.d.ts +0 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +0 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +11 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +22 -28
- package/dist/src/index.js.map +1 -1
- package/dist/src/key-generator.js.map +1 -1
- package/package.json +24 -17
- package/src/crypto.ts +5 -4
- package/src/errors.ts +0 -1
- package/src/index.ts +38 -33
package/dist/src/crypto.d.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import type { Source } from 'it-stream-types';
|
2
|
+
import type { Uint8ArrayList } from 'uint8arraylist';
|
2
3
|
/**
|
3
4
|
* Creates a stream iterable to encrypt messages in a private network
|
4
5
|
*/
|
5
|
-
export declare function createBoxStream(nonce: Uint8Array, psk: Uint8Array): (source: Source<Uint8Array>) =>
|
6
|
+
export declare function createBoxStream(nonce: Uint8Array, psk: Uint8Array): (source: Source<Uint8Array | Uint8ArrayList>) => AsyncGenerator<Uint8Array | Uint8ArrayList>;
|
6
7
|
/**
|
7
8
|
* Creates a stream iterable to decrypt messages in a private network
|
8
9
|
*/
|
package/dist/src/crypto.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;
|
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,YACnD,OAAO,UAAU,CAAC,+CAOnC;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
@@ -10,7 +10,7 @@ export function createBoxStream(nonce, psk) {
|
|
10
10
|
const xor = xsalsa20(nonce, psk);
|
11
11
|
return (source) => (async function* () {
|
12
12
|
for await (const chunk of source) {
|
13
|
-
yield Uint8Array.from(xor.update(chunk.
|
13
|
+
yield Uint8Array.from(xor.update(chunk.subarray()));
|
14
14
|
}
|
15
15
|
})();
|
16
16
|
}
|
@@ -21,7 +21,7 @@ export function createUnboxStream(nonce, psk) {
|
|
21
21
|
return (source) => (async function* () {
|
22
22
|
const xor = xsalsa20(nonce, psk);
|
23
23
|
for await (const chunk of source) {
|
24
|
-
yield Uint8Array.from(xor.update(chunk.
|
24
|
+
yield Uint8Array.from(xor.update(chunk.subarray()));
|
25
25
|
}
|
26
26
|
})();
|
27
27
|
}
|
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,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;
|
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/errors.d.ts
CHANGED
@@ -3,5 +3,4 @@ export declare const INVALID_PSK = "Your private shared key is invalid";
|
|
3
3
|
export declare const NO_LOCAL_ID = "No local private key provided";
|
4
4
|
export declare const NO_HANDSHAKE_CONNECTION = "No connection for the handshake provided";
|
5
5
|
export declare const STREAM_ENDED = "Stream ended prematurely";
|
6
|
-
export declare const ERR_INVALID_PARAMETERS = "ERR_INVALID_PARAMETERS";
|
7
6
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/src/errors.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,gCAAgC,CAAA;AACzD,eAAO,MAAM,WAAW,uCAAuC,CAAA;AAC/D,eAAO,MAAM,WAAW,kCAAkC,CAAA;AAC1D,eAAO,MAAM,uBAAuB,6CAA6C,CAAA;AACjF,eAAO,MAAM,YAAY,6BAA6B,CAAA
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,gCAAgC,CAAA;AACzD,eAAO,MAAM,WAAW,uCAAuC,CAAA;AAC/D,eAAO,MAAM,WAAW,kCAAkC,CAAA;AAC1D,eAAO,MAAM,uBAAuB,6CAA6C,CAAA;AACjF,eAAO,MAAM,YAAY,6BAA6B,CAAA"}
|
package/dist/src/errors.js
CHANGED
@@ -3,5 +3,4 @@ export const INVALID_PSK = 'Your private shared key is invalid';
|
|
3
3
|
export const NO_LOCAL_ID = 'No local private key provided';
|
4
4
|
export const NO_HANDSHAKE_CONNECTION = 'No connection for the handshake provided';
|
5
5
|
export const STREAM_ENDED = 'Stream ended prematurely';
|
6
|
-
export const ERR_INVALID_PARAMETERS = 'ERR_INVALID_PARAMETERS';
|
7
6
|
//# sourceMappingURL=errors.js.map
|
package/dist/src/errors.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,6BAA6B,CAAA;AACzD,MAAM,CAAC,MAAM,WAAW,GAAG,oCAAoC,CAAA;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,+BAA+B,CAAA;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,0CAA0C,CAAA;AACjF,MAAM,CAAC,MAAM,YAAY,GAAG,0BAA0B,CAAA
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,6BAA6B,CAAA;AACzD,MAAM,CAAC,MAAM,WAAW,GAAG,oCAAoC,CAAA;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,+BAA+B,CAAA;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,0CAA0C,CAAA;AACjF,MAAM,CAAC,MAAM,YAAY,GAAG,0BAA0B,CAAA"}
|
package/dist/src/index.d.ts
CHANGED
@@ -45,7 +45,7 @@
|
|
45
45
|
*
|
46
46
|
* ### Programmatically
|
47
47
|
*
|
48
|
-
* ```
|
48
|
+
* ```TypeScript
|
49
49
|
* import fs from 'fs'
|
50
50
|
* import { generateKey } from '@libp2p/pnet'
|
51
51
|
*
|
@@ -55,12 +55,19 @@
|
|
55
55
|
* fs.writeFileSync('swarm.key', swarmKey)
|
56
56
|
* ```
|
57
57
|
*/
|
58
|
-
import type { ComponentLogger } from '@libp2p/interface';
|
59
|
-
import type { ConnectionProtector } from '@libp2p/interface/connection';
|
58
|
+
import type { ComponentLogger, ConnectionProtector } from '@libp2p/interface';
|
60
59
|
export { generateKey } from './key-generator.js';
|
61
60
|
export interface ProtectorInit {
|
62
|
-
|
61
|
+
/**
|
62
|
+
* A pre-shared key. This must be the same byte value for all peers in the
|
63
|
+
* swarm in order for them to communicate.
|
64
|
+
*/
|
63
65
|
psk: Uint8Array;
|
66
|
+
/**
|
67
|
+
* The initial nonce exchange must complete within this many milliseconds
|
68
|
+
* (default: 1000)
|
69
|
+
*/
|
70
|
+
timeout?: number;
|
64
71
|
}
|
65
72
|
export interface ProtectorComponents {
|
66
73
|
logger: ComponentLogger;
|
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;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAA;CACxB;AA2ED,wBAAgB,YAAY,CAAE,IAAI,EAAE,aAAa,GAAG,CAAC,UAAU,EAAE,mBAAmB,KAAK,mBAAmB,CAE3G"}
|
package/dist/src/index.js
CHANGED
@@ -45,7 +45,7 @@
|
|
45
45
|
*
|
46
46
|
* ### Programmatically
|
47
47
|
*
|
48
|
-
* ```
|
48
|
+
* ```TypeScript
|
49
49
|
* import fs from 'fs'
|
50
50
|
* import { generateKey } from '@libp2p/pnet'
|
51
51
|
*
|
@@ -56,66 +56,60 @@
|
|
56
56
|
* ```
|
57
57
|
*/
|
58
58
|
import { randomBytes } from '@libp2p/crypto';
|
59
|
-
import {
|
60
|
-
import {
|
59
|
+
import { InvalidParametersError } from '@libp2p/interface';
|
60
|
+
import { byteStream } from 'it-byte-stream';
|
61
61
|
import map from 'it-map';
|
62
62
|
import { duplexPair } from 'it-pair/duplex';
|
63
63
|
import { pipe } from 'it-pipe';
|
64
64
|
import { createBoxStream, createUnboxStream, decodeV1PSK } from './crypto.js';
|
65
|
-
import * as Errors from './errors.js';
|
66
65
|
import { NONCE_LENGTH } from './key-generator.js';
|
67
66
|
export { generateKey } from './key-generator.js';
|
68
67
|
class PreSharedKeyConnectionProtector {
|
69
68
|
tag;
|
70
69
|
log;
|
71
70
|
psk;
|
72
|
-
|
71
|
+
timeout;
|
73
72
|
/**
|
74
73
|
* Takes a Private Shared Key (psk) and provides a `protect` method
|
75
74
|
* for wrapping existing connections in a private encryption stream.
|
76
75
|
*/
|
77
76
|
constructor(components, init) {
|
78
77
|
this.log = components.logger.forComponent('libp2p:pnet');
|
79
|
-
this.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
this.tag = decodedPSK.tag ?? '';
|
84
|
-
}
|
85
|
-
else {
|
86
|
-
this.psk = new Uint8Array();
|
87
|
-
this.tag = '';
|
88
|
-
}
|
78
|
+
this.timeout = init.timeout ?? 1000;
|
79
|
+
const decodedPSK = decodeV1PSK(init.psk);
|
80
|
+
this.psk = decodedPSK.psk;
|
81
|
+
this.tag = decodedPSK.tag ?? '';
|
89
82
|
}
|
83
|
+
[Symbol.toStringTag] = '@libp2p/pnet';
|
90
84
|
/**
|
91
85
|
* Takes a given Connection and creates a private encryption stream
|
92
86
|
* between its two peers from the PSK the Protector instance was
|
93
87
|
* created with.
|
94
88
|
*/
|
95
89
|
async protect(connection) {
|
96
|
-
if (!this.enabled) {
|
97
|
-
return connection;
|
98
|
-
}
|
99
90
|
if (connection == null) {
|
100
|
-
throw new
|
91
|
+
throw new InvalidParametersError('No connection for the handshake provided');
|
101
92
|
}
|
102
93
|
// Exchange nonces
|
103
94
|
this.log('protecting the connection');
|
104
95
|
const localNonce = randomBytes(NONCE_LENGTH);
|
105
|
-
const
|
106
|
-
|
107
|
-
const result = await
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
96
|
+
const signal = AbortSignal.timeout(this.timeout);
|
97
|
+
const bytes = byteStream(connection);
|
98
|
+
const [, result] = await Promise.all([
|
99
|
+
bytes.write(localNonce, {
|
100
|
+
signal
|
101
|
+
}),
|
102
|
+
bytes.read(NONCE_LENGTH, {
|
103
|
+
signal
|
104
|
+
})
|
105
|
+
]);
|
106
|
+
const remoteNonce = result.subarray();
|
113
107
|
// Create the boxing/unboxing pipe
|
114
108
|
this.log('exchanged nonces');
|
115
109
|
const [internal, external] = duplexPair();
|
116
110
|
pipe(external,
|
117
111
|
// Encrypt all outbound traffic
|
118
|
-
createBoxStream(localNonce, this.psk),
|
112
|
+
createBoxStream(localNonce, this.psk), bytes.unwrap(), (source) => map(source, (buf) => buf.subarray()),
|
119
113
|
// Decrypt all inbound traffic
|
120
114
|
createUnboxStream(remoteNonce, this.psk), external).catch(this.log.error);
|
121
115
|
return {
|
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,
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"key-generator.js","sourceRoot":"","sources":["../../src/key-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAEtE;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAE,KAAsC;IACjE,MAAM,GAAG,GAAG,kBAAkB,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;IACjE,MAAM,GAAG,GAAG,oBAAoB,CAAC,mCAAmC,GAAG,GAAG,CAAC,CAAA;IAE3E,IAAI,KAAK,YAAY,UAAU,EAAE;
|
1
|
+
{"version":3,"file":"key-generator.js","sourceRoot":"","sources":["../../src/key-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAEtE;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAE,KAAsC;IACjE,MAAM,GAAG,GAAG,kBAAkB,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;IACjE,MAAM,GAAG,GAAG,oBAAoB,CAAC,mCAAmC,GAAG,GAAG,CAAC,CAAA;IAE3E,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAChB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAA;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAA"}
|
package/package.json
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
{
|
2
2
|
"name": "@libp2p/pnet",
|
3
|
-
"version": "
|
3
|
+
"version": "2.0.0-18dd3cb26",
|
4
4
|
"description": "Implementation of Connection protection management via a shared secret",
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
6
|
-
"homepage": "https://github.com/libp2p/js-libp2p/tree/
|
6
|
+
"homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/pnet#readme",
|
7
7
|
"repository": {
|
8
8
|
"type": "git",
|
9
9
|
"url": "git+https://github.com/libp2p/js-libp2p.git"
|
@@ -11,6 +11,10 @@
|
|
11
11
|
"bugs": {
|
12
12
|
"url": "https://github.com/libp2p/js-libp2p/issues"
|
13
13
|
},
|
14
|
+
"publishConfig": {
|
15
|
+
"access": "public",
|
16
|
+
"provenance": true
|
17
|
+
},
|
14
18
|
"type": "module",
|
15
19
|
"types": "./dist/src/index.d.ts",
|
16
20
|
"files": [
|
@@ -42,26 +46,29 @@
|
|
42
46
|
"test:firefox": "aegir test -t browser -- --browser firefox",
|
43
47
|
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
|
44
48
|
"test:node": "aegir test -t node --cov",
|
45
|
-
"dep-check": "aegir dep-check"
|
49
|
+
"dep-check": "aegir dep-check",
|
50
|
+
"doc-check": "aegir doc-check"
|
46
51
|
},
|
47
52
|
"dependencies": {
|
48
|
-
"@libp2p/crypto": "
|
49
|
-
"@libp2p/interface": "
|
50
|
-
"it-
|
51
|
-
"it-map": "^3.0
|
53
|
+
"@libp2p/crypto": "5.0.0-18dd3cb26",
|
54
|
+
"@libp2p/interface": "2.0.0-18dd3cb26",
|
55
|
+
"it-byte-stream": "^1.0.10",
|
56
|
+
"it-map": "^3.1.0",
|
52
57
|
"it-pair": "^2.0.6",
|
53
58
|
"it-pipe": "^3.0.1",
|
54
59
|
"it-stream-types": "^2.0.1",
|
55
|
-
"
|
56
|
-
"
|
60
|
+
"uint8arraylist": "^2.4.8",
|
61
|
+
"uint8arrays": "^5.1.0",
|
62
|
+
"xsalsa20": "^1.2.0"
|
57
63
|
},
|
58
64
|
"devDependencies": {
|
59
|
-
"@libp2p/interface-compliance-tests": "
|
60
|
-
"@libp2p/logger": "
|
61
|
-
"@libp2p/peer-id
|
62
|
-
"@multiformats/multiaddr": "^12.
|
63
|
-
"@types/xsalsa20": "^1.1.
|
64
|
-
"aegir": "^
|
65
|
-
"it-all": "^3.0.
|
66
|
-
}
|
65
|
+
"@libp2p/interface-compliance-tests": "6.0.0-18dd3cb26",
|
66
|
+
"@libp2p/logger": "5.0.0-18dd3cb26",
|
67
|
+
"@libp2p/peer-id": "5.0.0-18dd3cb26",
|
68
|
+
"@multiformats/multiaddr": "^12.2.3",
|
69
|
+
"@types/xsalsa20": "^1.1.3",
|
70
|
+
"aegir": "^44.0.1",
|
71
|
+
"it-all": "^3.0.6"
|
72
|
+
},
|
73
|
+
"sideEffects": false
|
67
74
|
}
|
package/src/crypto.ts
CHANGED
@@ -4,16 +4,17 @@ import xsalsa20 from 'xsalsa20'
|
|
4
4
|
import * as Errors from './errors.js'
|
5
5
|
import { KEY_LENGTH } from './key-generator.js'
|
6
6
|
import type { Source } from 'it-stream-types'
|
7
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
7
8
|
|
8
9
|
/**
|
9
10
|
* Creates a stream iterable to encrypt messages in a private network
|
10
11
|
*/
|
11
|
-
export function createBoxStream (nonce: Uint8Array, psk: Uint8Array): (source: Source<Uint8Array>) =>
|
12
|
+
export function createBoxStream (nonce: Uint8Array, psk: Uint8Array): (source: Source<Uint8Array | Uint8ArrayList>) => AsyncGenerator<Uint8Array | Uint8ArrayList> {
|
12
13
|
const xor = xsalsa20(nonce, psk)
|
13
14
|
|
14
|
-
return (source: Source<Uint8Array>) => (async function * () {
|
15
|
+
return (source: Source<Uint8Array | Uint8ArrayList>) => (async function * () {
|
15
16
|
for await (const chunk of source) {
|
16
|
-
yield Uint8Array.from(xor.update(chunk.
|
17
|
+
yield Uint8Array.from(xor.update(chunk.subarray()))
|
17
18
|
}
|
18
19
|
})()
|
19
20
|
}
|
@@ -26,7 +27,7 @@ export function createUnboxStream (nonce: Uint8Array, psk: Uint8Array) {
|
|
26
27
|
const xor = xsalsa20(nonce, psk)
|
27
28
|
|
28
29
|
for await (const chunk of source) {
|
29
|
-
yield Uint8Array.from(xor.update(chunk.
|
30
|
+
yield Uint8Array.from(xor.update(chunk.subarray()))
|
30
31
|
}
|
31
32
|
})()
|
32
33
|
}
|
package/src/errors.ts
CHANGED
@@ -3,4 +3,3 @@ export const INVALID_PSK = 'Your private shared key is invalid'
|
|
3
3
|
export const NO_LOCAL_ID = 'No local private key provided'
|
4
4
|
export const NO_HANDSHAKE_CONNECTION = 'No connection for the handshake provided'
|
5
5
|
export const STREAM_ENDED = 'Stream ended prematurely'
|
6
|
-
export const ERR_INVALID_PARAMETERS = 'ERR_INVALID_PARAMETERS'
|
package/src/index.ts
CHANGED
@@ -45,7 +45,7 @@
|
|
45
45
|
*
|
46
46
|
* ### Programmatically
|
47
47
|
*
|
48
|
-
* ```
|
48
|
+
* ```TypeScript
|
49
49
|
* import fs from 'fs'
|
50
50
|
* import { generateKey } from '@libp2p/pnet'
|
51
51
|
*
|
@@ -57,8 +57,8 @@
|
|
57
57
|
*/
|
58
58
|
|
59
59
|
import { randomBytes } from '@libp2p/crypto'
|
60
|
-
import {
|
61
|
-
import {
|
60
|
+
import { InvalidParametersError } from '@libp2p/interface'
|
61
|
+
import { byteStream } from 'it-byte-stream'
|
62
62
|
import map from 'it-map'
|
63
63
|
import { duplexPair } from 'it-pair/duplex'
|
64
64
|
import { pipe } from 'it-pipe'
|
@@ -67,16 +67,23 @@ import {
|
|
67
67
|
createUnboxStream,
|
68
68
|
decodeV1PSK
|
69
69
|
} from './crypto.js'
|
70
|
-
import * as Errors from './errors.js'
|
71
70
|
import { NONCE_LENGTH } from './key-generator.js'
|
72
|
-
import type { ComponentLogger, Logger } from '@libp2p/interface'
|
73
|
-
import type {
|
71
|
+
import type { ComponentLogger, Logger, ConnectionProtector, MultiaddrConnection } from '@libp2p/interface'
|
72
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
74
73
|
|
75
74
|
export { generateKey } from './key-generator.js'
|
76
75
|
|
77
76
|
export interface ProtectorInit {
|
78
|
-
|
77
|
+
/**
|
78
|
+
* A pre-shared key. This must be the same byte value for all peers in the
|
79
|
+
* swarm in order for them to communicate.
|
80
|
+
*/
|
79
81
|
psk: Uint8Array
|
82
|
+
/**
|
83
|
+
* The initial nonce exchange must complete within this many milliseconds
|
84
|
+
* (default: 1000)
|
85
|
+
*/
|
86
|
+
timeout?: number
|
80
87
|
}
|
81
88
|
|
82
89
|
export interface ProtectorComponents {
|
@@ -87,7 +94,7 @@ class PreSharedKeyConnectionProtector implements ConnectionProtector {
|
|
87
94
|
public tag: string
|
88
95
|
private readonly log: Logger
|
89
96
|
private readonly psk: Uint8Array
|
90
|
-
private readonly
|
97
|
+
private readonly timeout: number
|
91
98
|
|
92
99
|
/**
|
93
100
|
* Takes a Private Shared Key (psk) and provides a `protect` method
|
@@ -95,56 +102,54 @@ class PreSharedKeyConnectionProtector implements ConnectionProtector {
|
|
95
102
|
*/
|
96
103
|
constructor (components: ProtectorComponents, init: ProtectorInit) {
|
97
104
|
this.log = components.logger.forComponent('libp2p:pnet')
|
98
|
-
this.
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
this.tag = decodedPSK.tag ?? ''
|
104
|
-
} else {
|
105
|
-
this.psk = new Uint8Array()
|
106
|
-
this.tag = ''
|
107
|
-
}
|
105
|
+
this.timeout = init.timeout ?? 1000
|
106
|
+
|
107
|
+
const decodedPSK = decodeV1PSK(init.psk)
|
108
|
+
this.psk = decodedPSK.psk
|
109
|
+
this.tag = decodedPSK.tag ?? ''
|
108
110
|
}
|
109
111
|
|
112
|
+
readonly [Symbol.toStringTag] = '@libp2p/pnet'
|
113
|
+
|
110
114
|
/**
|
111
115
|
* Takes a given Connection and creates a private encryption stream
|
112
116
|
* between its two peers from the PSK the Protector instance was
|
113
117
|
* created with.
|
114
118
|
*/
|
115
119
|
async protect (connection: MultiaddrConnection): Promise<MultiaddrConnection> {
|
116
|
-
if (!this.enabled) {
|
117
|
-
return connection
|
118
|
-
}
|
119
|
-
|
120
120
|
if (connection == null) {
|
121
|
-
throw new
|
121
|
+
throw new InvalidParametersError('No connection for the handshake provided')
|
122
122
|
}
|
123
123
|
|
124
124
|
// Exchange nonces
|
125
125
|
this.log('protecting the connection')
|
126
126
|
const localNonce = randomBytes(NONCE_LENGTH)
|
127
127
|
|
128
|
-
const
|
129
|
-
shake.write(localNonce)
|
128
|
+
const signal = AbortSignal.timeout(this.timeout)
|
130
129
|
|
131
|
-
const
|
130
|
+
const bytes = byteStream(connection)
|
132
131
|
|
133
|
-
|
134
|
-
|
135
|
-
|
132
|
+
const [
|
133
|
+
, result
|
134
|
+
] = await Promise.all([
|
135
|
+
bytes.write(localNonce, {
|
136
|
+
signal
|
137
|
+
}),
|
138
|
+
bytes.read(NONCE_LENGTH, {
|
139
|
+
signal
|
140
|
+
})
|
141
|
+
])
|
136
142
|
|
137
|
-
const remoteNonce = result.
|
138
|
-
shake.rest()
|
143
|
+
const remoteNonce = result.subarray()
|
139
144
|
|
140
145
|
// Create the boxing/unboxing pipe
|
141
146
|
this.log('exchanged nonces')
|
142
|
-
const [internal, external] = duplexPair<Uint8Array>()
|
147
|
+
const [internal, external] = duplexPair<Uint8Array | Uint8ArrayList>()
|
143
148
|
pipe(
|
144
149
|
external,
|
145
150
|
// Encrypt all outbound traffic
|
146
151
|
createBoxStream(localNonce, this.psk),
|
147
|
-
|
152
|
+
bytes.unwrap(),
|
148
153
|
(source) => map(source, (buf) => buf.subarray()),
|
149
154
|
// Decrypt all inbound traffic
|
150
155
|
createUnboxStream(remoteNonce, this.psk),
|