@libp2p/noise 12.0.1
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 +27 -0
- package/dist/src/@types/basic.d.ts +5 -0
- package/dist/src/@types/basic.d.ts.map +1 -0
- package/dist/src/@types/basic.js +2 -0
- package/dist/src/@types/basic.js.map +1 -0
- package/dist/src/@types/handshake-interface.d.ts +15 -0
- package/dist/src/@types/handshake-interface.d.ts.map +1 -0
- package/dist/src/@types/handshake-interface.js +2 -0
- package/dist/src/@types/handshake-interface.js.map +1 -0
- package/dist/src/@types/handshake.d.ts +40 -0
- package/dist/src/@types/handshake.d.ts.map +1 -0
- package/dist/src/@types/handshake.js +2 -0
- package/dist/src/@types/handshake.js.map +1 -0
- package/dist/src/@types/libp2p.d.ts +10 -0
- package/dist/src/@types/libp2p.d.ts.map +1 -0
- package/dist/src/@types/libp2p.js +2 -0
- package/dist/src/@types/libp2p.js.map +1 -0
- package/dist/src/constants.d.ts +4 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +4 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/crypto/js.d.ts +3 -0
- package/dist/src/crypto/js.d.ts.map +1 -0
- package/dist/src/crypto/js.js +42 -0
- package/dist/src/crypto/js.js.map +1 -0
- package/dist/src/crypto/streaming.d.ts +7 -0
- package/dist/src/crypto/streaming.d.ts.map +1 -0
- package/dist/src/crypto/streaming.js +50 -0
- package/dist/src/crypto/streaming.js.map +1 -0
- package/dist/src/crypto.d.ts +13 -0
- package/dist/src/crypto.d.ts.map +1 -0
- package/dist/src/crypto.js +2 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/encoder.d.ts +15 -0
- package/dist/src/encoder.d.ts.map +1 -0
- package/dist/src/encoder.js +63 -0
- package/dist/src/encoder.js.map +1 -0
- package/dist/src/handshake-xx.d.ts +33 -0
- package/dist/src/handshake-xx.d.ts.map +1 -0
- package/dist/src/handshake-xx.js +139 -0
- package/dist/src/handshake-xx.js.map +1 -0
- package/dist/src/handshakes/abstract-handshake.d.ts +36 -0
- package/dist/src/handshakes/abstract-handshake.d.ts.map +1 -0
- package/dist/src/handshakes/abstract-handshake.js +140 -0
- package/dist/src/handshakes/abstract-handshake.js.map +1 -0
- package/dist/src/handshakes/xx.d.ts +18 -0
- package/dist/src/handshakes/xx.d.ts.map +1 -0
- package/dist/src/handshakes/xx.js +161 -0
- package/dist/src/handshakes/xx.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logger.d.ts +11 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +45 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/metrics.d.ts +4 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +20 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/noise.d.ts +55 -0
- package/dist/src/noise.d.ts.map +1 -0
- package/dist/src/noise.js +130 -0
- package/dist/src/noise.js.map +1 -0
- package/dist/src/nonce.d.ts +18 -0
- package/dist/src/nonce.d.ts.map +1 -0
- package/dist/src/nonce.js +41 -0
- package/dist/src/nonce.js.map +1 -0
- package/dist/src/proto/payload.d.ts +21 -0
- package/dist/src/proto/payload.d.ts.map +1 -0
- package/dist/src/proto/payload.js +114 -0
- package/dist/src/proto/payload.js.map +1 -0
- package/dist/src/utils.d.ts +20 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +74 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +99 -0
- package/src/@types/basic.ts +5 -0
- package/src/@types/handshake-interface.ts +12 -0
- package/src/@types/handshake.ts +48 -0
- package/src/@types/libp2p.ts +10 -0
- package/src/constants.ts +4 -0
- package/src/crypto/js.ts +58 -0
- package/src/crypto/streaming.ts +58 -0
- package/src/crypto.ts +16 -0
- package/src/encoder.ts +81 -0
- package/src/handshake-xx.ts +177 -0
- package/src/handshakes/abstract-handshake.ts +180 -0
- package/src/handshakes/xx.ts +184 -0
- package/src/index.ts +10 -0
- package/src/logger.ts +51 -0
- package/src/metrics.ts +32 -0
- package/src/noise.ts +192 -0
- package/src/nonce.ts +49 -0
- package/src/proto/payload.proto +11 -0
- package/src/proto/payload.ts +148 -0
- package/src/utils.ts +111 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { decode } from 'it-length-prefixed';
|
|
2
|
+
import { lpStream } from 'it-length-prefixed-stream';
|
|
3
|
+
import { duplexPair } from 'it-pair/duplex';
|
|
4
|
+
import { pipe } from 'it-pipe';
|
|
5
|
+
import { NOISE_MSG_MAX_LENGTH_BYTES } from './constants.js';
|
|
6
|
+
import { pureJsCrypto } from './crypto/js.js';
|
|
7
|
+
import { decryptStream, encryptStream } from './crypto/streaming.js';
|
|
8
|
+
import { uint16BEDecode, uint16BEEncode } from './encoder.js';
|
|
9
|
+
import { XXHandshake } from './handshake-xx.js';
|
|
10
|
+
import { registerMetrics } from './metrics.js';
|
|
11
|
+
import { getPayload } from './utils.js';
|
|
12
|
+
export class Noise {
|
|
13
|
+
protocol = '/noise';
|
|
14
|
+
crypto;
|
|
15
|
+
prologue;
|
|
16
|
+
staticKeys;
|
|
17
|
+
extensions;
|
|
18
|
+
metrics;
|
|
19
|
+
constructor(init = {}) {
|
|
20
|
+
const { staticNoiseKey, extensions, crypto, prologueBytes, metrics } = init;
|
|
21
|
+
this.crypto = crypto ?? pureJsCrypto;
|
|
22
|
+
this.extensions = extensions;
|
|
23
|
+
this.metrics = metrics ? registerMetrics(metrics) : undefined;
|
|
24
|
+
if (staticNoiseKey) {
|
|
25
|
+
// accepts x25519 private key of length 32
|
|
26
|
+
this.staticKeys = this.crypto.generateX25519KeyPairFromSeed(staticNoiseKey);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.staticKeys = this.crypto.generateX25519KeyPair();
|
|
30
|
+
}
|
|
31
|
+
this.prologue = prologueBytes ?? new Uint8Array(0);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Encrypt outgoing data to the remote party (handshake as initiator)
|
|
35
|
+
*
|
|
36
|
+
* @param {PeerId} localPeer - PeerId of the receiving peer
|
|
37
|
+
* @param {Duplex<AsyncGenerator<Uint8Array>, AsyncIterable<Uint8Array>, Promise<void>>} connection - streaming iterable duplex that will be encrypted
|
|
38
|
+
* @param {PeerId} remotePeer - PeerId of the remote peer. Used to validate the integrity of the remote peer.
|
|
39
|
+
* @returns {Promise<SecuredConnection>}
|
|
40
|
+
*/
|
|
41
|
+
async secureOutbound(localPeer, connection, remotePeer) {
|
|
42
|
+
const wrappedConnection = lpStream(connection, {
|
|
43
|
+
lengthEncoder: uint16BEEncode,
|
|
44
|
+
lengthDecoder: uint16BEDecode,
|
|
45
|
+
maxDataLength: NOISE_MSG_MAX_LENGTH_BYTES
|
|
46
|
+
});
|
|
47
|
+
const handshake = await this.performHandshake({
|
|
48
|
+
connection: wrappedConnection,
|
|
49
|
+
isInitiator: true,
|
|
50
|
+
localPeer,
|
|
51
|
+
remotePeer
|
|
52
|
+
});
|
|
53
|
+
const conn = await this.createSecureConnection(wrappedConnection, handshake);
|
|
54
|
+
return {
|
|
55
|
+
conn,
|
|
56
|
+
remoteExtensions: handshake.remoteExtensions,
|
|
57
|
+
remotePeer: handshake.remotePeer
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Decrypt incoming data (handshake as responder).
|
|
62
|
+
*
|
|
63
|
+
* @param {PeerId} localPeer - PeerId of the receiving peer.
|
|
64
|
+
* @param {Duplex<AsyncGenerator<Uint8Array>, AsyncIterable<Uint8Array>, Promise<void>>} connection - streaming iterable duplex that will be encryption.
|
|
65
|
+
* @param {PeerId} remotePeer - optional PeerId of the initiating peer, if known. This may only exist during transport upgrades.
|
|
66
|
+
* @returns {Promise<SecuredConnection>}
|
|
67
|
+
*/
|
|
68
|
+
async secureInbound(localPeer, connection, remotePeer) {
|
|
69
|
+
const wrappedConnection = lpStream(connection, {
|
|
70
|
+
lengthEncoder: uint16BEEncode,
|
|
71
|
+
lengthDecoder: uint16BEDecode,
|
|
72
|
+
maxDataLength: NOISE_MSG_MAX_LENGTH_BYTES
|
|
73
|
+
});
|
|
74
|
+
const handshake = await this.performHandshake({
|
|
75
|
+
connection: wrappedConnection,
|
|
76
|
+
isInitiator: false,
|
|
77
|
+
localPeer,
|
|
78
|
+
remotePeer
|
|
79
|
+
});
|
|
80
|
+
const conn = await this.createSecureConnection(wrappedConnection, handshake);
|
|
81
|
+
return {
|
|
82
|
+
conn,
|
|
83
|
+
remotePeer: handshake.remotePeer,
|
|
84
|
+
remoteExtensions: handshake.remoteExtensions
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* If Noise pipes supported, tries IK handshake first with XX as fallback if it fails.
|
|
89
|
+
* If noise pipes disabled or remote peer static key is unknown, use XX.
|
|
90
|
+
*
|
|
91
|
+
* @param {HandshakeParams} params
|
|
92
|
+
*/
|
|
93
|
+
async performHandshake(params) {
|
|
94
|
+
const payload = await getPayload(params.localPeer, this.staticKeys.publicKey, this.extensions);
|
|
95
|
+
// run XX handshake
|
|
96
|
+
return this.performXXHandshake(params, payload);
|
|
97
|
+
}
|
|
98
|
+
async performXXHandshake(params, payload) {
|
|
99
|
+
const { isInitiator, remotePeer, connection } = params;
|
|
100
|
+
const handshake = new XXHandshake(isInitiator, payload, this.prologue, this.crypto, this.staticKeys, connection, remotePeer);
|
|
101
|
+
try {
|
|
102
|
+
await handshake.propose();
|
|
103
|
+
await handshake.exchange();
|
|
104
|
+
await handshake.finish();
|
|
105
|
+
this.metrics?.xxHandshakeSuccesses.increment();
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
this.metrics?.xxHandshakeErrors.increment();
|
|
109
|
+
if (e instanceof Error) {
|
|
110
|
+
e.message = `Error occurred during XX handshake: ${e.message}`;
|
|
111
|
+
throw e;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return handshake;
|
|
115
|
+
}
|
|
116
|
+
async createSecureConnection(connection, handshake) {
|
|
117
|
+
// Create encryption box/unbox wrapper
|
|
118
|
+
const [secure, user] = duplexPair();
|
|
119
|
+
const network = connection.unwrap();
|
|
120
|
+
await pipe(secure, // write to wrapper
|
|
121
|
+
encryptStream(handshake, this.metrics), // encrypt data + prefix with message length
|
|
122
|
+
network, // send to the remote peer
|
|
123
|
+
(source) => decode(source, { lengthDecoder: uint16BEDecode }), // read message length prefix
|
|
124
|
+
decryptStream(handshake, this.metrics), // decrypt the incoming data
|
|
125
|
+
secure // pipe to the wrapper
|
|
126
|
+
);
|
|
127
|
+
return user;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=noise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noise.js","sourceRoot":"","sources":["../../src/noise.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { bytes, uint64 } from './@types/basic.js';
|
|
2
|
+
export declare const MIN_NONCE = 0;
|
|
3
|
+
export declare const MAX_NONCE = 4294967295;
|
|
4
|
+
/**
|
|
5
|
+
* The nonce is an uint that's increased over time.
|
|
6
|
+
* Maintaining different representations help improve performance.
|
|
7
|
+
*/
|
|
8
|
+
export declare class Nonce {
|
|
9
|
+
private n;
|
|
10
|
+
private readonly bytes;
|
|
11
|
+
private readonly view;
|
|
12
|
+
constructor(n?: number);
|
|
13
|
+
increment(): void;
|
|
14
|
+
getBytes(): bytes;
|
|
15
|
+
getUint64(): uint64;
|
|
16
|
+
assertValue(): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=nonce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonce.d.ts","sourceRoot":"","sources":["../../src/nonce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAEtD,eAAO,MAAM,SAAS,IAAI,CAAA;AAO1B,eAAO,MAAM,SAAS,aAAa,CAAA;AAInC;;;GAGG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,CAAC,CAAQ;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;gBAElB,CAAC,SAAY;IAO1B,SAAS,IAAK,IAAI;IAMlB,QAAQ,IAAK,KAAK;IAIlB,SAAS,IAAK,MAAM;IAIpB,WAAW,IAAK,IAAI;CAKrB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export const MIN_NONCE = 0;
|
|
2
|
+
// For performance reasons, the nonce is represented as a JS `number`
|
|
3
|
+
// Although JS `number` can safely represent integers up to 2 ** 53 - 1, we choose to only use
|
|
4
|
+
// 4 bytes to store the data for performance reason.
|
|
5
|
+
// This is a slight deviation from the noise spec, which describes the max nonce as 2 ** 64 - 2
|
|
6
|
+
// The effect is that this implementation will need a new handshake to be performed after fewer messages are exchanged than other implementations with full uint64 nonces.
|
|
7
|
+
// this MAX_NONCE is still a large number of messages, so the practical effect of this is negligible.
|
|
8
|
+
export const MAX_NONCE = 0xffffffff;
|
|
9
|
+
const ERR_MAX_NONCE = 'Cipherstate has reached maximum n, a new handshake must be performed';
|
|
10
|
+
/**
|
|
11
|
+
* The nonce is an uint that's increased over time.
|
|
12
|
+
* Maintaining different representations help improve performance.
|
|
13
|
+
*/
|
|
14
|
+
export class Nonce {
|
|
15
|
+
n;
|
|
16
|
+
bytes;
|
|
17
|
+
view;
|
|
18
|
+
constructor(n = MIN_NONCE) {
|
|
19
|
+
this.n = n;
|
|
20
|
+
this.bytes = new Uint8Array(12);
|
|
21
|
+
this.view = new DataView(this.bytes.buffer, this.bytes.byteOffset, this.bytes.byteLength);
|
|
22
|
+
this.view.setUint32(4, n, true);
|
|
23
|
+
}
|
|
24
|
+
increment() {
|
|
25
|
+
this.n++;
|
|
26
|
+
// Even though we're treating the nonce as 8 bytes, RFC7539 specifies 12 bytes for a nonce.
|
|
27
|
+
this.view.setUint32(4, this.n, true);
|
|
28
|
+
}
|
|
29
|
+
getBytes() {
|
|
30
|
+
return this.bytes;
|
|
31
|
+
}
|
|
32
|
+
getUint64() {
|
|
33
|
+
return this.n;
|
|
34
|
+
}
|
|
35
|
+
assertValue() {
|
|
36
|
+
if (this.n > MAX_NONCE) {
|
|
37
|
+
throw new Error(ERR_MAX_NONCE);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=nonce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonce.js","sourceRoot":"","sources":["../../src/nonce.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAA;AAC1B,qEAAqE;AACrE,8FAA8F;AAC9F,oDAAoD;AACpD,+FAA+F;AAC/F,0KAA0K;AAC1K,qGAAqG;AACrG,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAA;AAEnC,MAAM,aAAa,GAAG,sEAAsE,CAAA;AAE5F;;;GAGG;AACH,MAAM,OAAO,KAAK;IACR,CAAC,CAAQ;IACA,KAAK,CAAO;IACZ,IAAI,CAAU;IAE/B,YAAa,CAAC,GAAG,SAAS;QACxB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;QACV,IAAI,CAAC,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAA;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QACzF,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;IACjC,CAAC;IAED,SAAS;QACP,IAAI,CAAC,CAAC,EAAE,CAAA;QACR,2FAA2F;QAC3F,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;IACtC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,CAAC,CAAA;IACf,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,CAAC,GAAG,SAAS,EAAE;YACtB,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAA;SAC/B;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Codec } from 'protons-runtime';
|
|
2
|
+
import type { Uint8ArrayList } from 'uint8arraylist';
|
|
3
|
+
export interface NoiseExtensions {
|
|
4
|
+
webtransportCerthashes: Uint8Array[];
|
|
5
|
+
}
|
|
6
|
+
export declare namespace NoiseExtensions {
|
|
7
|
+
const codec: () => Codec<NoiseExtensions>;
|
|
8
|
+
const encode: (obj: Partial<NoiseExtensions>) => Uint8Array;
|
|
9
|
+
const decode: (buf: Uint8Array | Uint8ArrayList) => NoiseExtensions;
|
|
10
|
+
}
|
|
11
|
+
export interface NoiseHandshakePayload {
|
|
12
|
+
identityKey: Uint8Array;
|
|
13
|
+
identitySig: Uint8Array;
|
|
14
|
+
extensions?: NoiseExtensions;
|
|
15
|
+
}
|
|
16
|
+
export declare namespace NoiseHandshakePayload {
|
|
17
|
+
const codec: () => Codec<NoiseHandshakePayload>;
|
|
18
|
+
const encode: (obj: Partial<NoiseHandshakePayload>) => Uint8Array;
|
|
19
|
+
const decode: (buf: Uint8Array | Uint8ArrayList) => NoiseHandshakePayload;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=payload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/proto/payload.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,MAAM,WAAW,eAAe;IAC9B,sBAAsB,EAAE,UAAU,EAAE,CAAA;CACrC;AAED,yBAAiB,eAAe,CAAC;IAGxB,MAAM,KAAK,QAAO,MAAM,eAAe,CA0C7C,CAAA;IAEM,MAAM,MAAM,QAAS,QAAQ,eAAe,CAAC,KAAG,UAEtD,CAAA;IAEM,MAAM,MAAM,QAAS,UAAU,GAAG,cAAc,KAAG,eAEzD,CAAA;CACF;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,UAAU,CAAA;IACvB,WAAW,EAAE,UAAU,CAAA;IACvB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B;AAED,yBAAiB,qBAAqB,CAAC;IAG9B,MAAM,KAAK,QAAO,MAAM,qBAAqB,CA2DnD,CAAA;IAEM,MAAM,MAAM,QAAS,QAAQ,qBAAqB,CAAC,KAAG,UAE5D,CAAA;IAEM,MAAM,MAAM,QAAS,UAAU,GAAG,cAAc,KAAG,qBAEzD,CAAA;CACF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* eslint-disable import/export */
|
|
2
|
+
/* eslint-disable complexity */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
6
|
+
import { encodeMessage, decodeMessage, message } from 'protons-runtime';
|
|
7
|
+
export var NoiseExtensions;
|
|
8
|
+
(function (NoiseExtensions) {
|
|
9
|
+
let _codec;
|
|
10
|
+
NoiseExtensions.codec = () => {
|
|
11
|
+
if (_codec == null) {
|
|
12
|
+
_codec = message((obj, w, opts = {}) => {
|
|
13
|
+
if (opts.lengthDelimited !== false) {
|
|
14
|
+
w.fork();
|
|
15
|
+
}
|
|
16
|
+
if (obj.webtransportCerthashes != null) {
|
|
17
|
+
for (const value of obj.webtransportCerthashes) {
|
|
18
|
+
w.uint32(10);
|
|
19
|
+
w.bytes(value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (opts.lengthDelimited !== false) {
|
|
23
|
+
w.ldelim();
|
|
24
|
+
}
|
|
25
|
+
}, (reader, length) => {
|
|
26
|
+
const obj = {
|
|
27
|
+
webtransportCerthashes: []
|
|
28
|
+
};
|
|
29
|
+
const end = length == null ? reader.len : reader.pos + length;
|
|
30
|
+
while (reader.pos < end) {
|
|
31
|
+
const tag = reader.uint32();
|
|
32
|
+
switch (tag >>> 3) {
|
|
33
|
+
case 1:
|
|
34
|
+
obj.webtransportCerthashes.push(reader.bytes());
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
reader.skipType(tag & 7);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return obj;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return _codec;
|
|
45
|
+
};
|
|
46
|
+
NoiseExtensions.encode = (obj) => {
|
|
47
|
+
return encodeMessage(obj, NoiseExtensions.codec());
|
|
48
|
+
};
|
|
49
|
+
NoiseExtensions.decode = (buf) => {
|
|
50
|
+
return decodeMessage(buf, NoiseExtensions.codec());
|
|
51
|
+
};
|
|
52
|
+
})(NoiseExtensions || (NoiseExtensions = {}));
|
|
53
|
+
export var NoiseHandshakePayload;
|
|
54
|
+
(function (NoiseHandshakePayload) {
|
|
55
|
+
let _codec;
|
|
56
|
+
NoiseHandshakePayload.codec = () => {
|
|
57
|
+
if (_codec == null) {
|
|
58
|
+
_codec = message((obj, w, opts = {}) => {
|
|
59
|
+
if (opts.lengthDelimited !== false) {
|
|
60
|
+
w.fork();
|
|
61
|
+
}
|
|
62
|
+
if (opts.writeDefaults === true || (obj.identityKey != null && obj.identityKey.byteLength > 0)) {
|
|
63
|
+
w.uint32(10);
|
|
64
|
+
w.bytes(obj.identityKey ?? new Uint8Array(0));
|
|
65
|
+
}
|
|
66
|
+
if (opts.writeDefaults === true || (obj.identitySig != null && obj.identitySig.byteLength > 0)) {
|
|
67
|
+
w.uint32(18);
|
|
68
|
+
w.bytes(obj.identitySig ?? new Uint8Array(0));
|
|
69
|
+
}
|
|
70
|
+
if (obj.extensions != null) {
|
|
71
|
+
w.uint32(34);
|
|
72
|
+
NoiseExtensions.codec().encode(obj.extensions, w, {
|
|
73
|
+
writeDefaults: false
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (opts.lengthDelimited !== false) {
|
|
77
|
+
w.ldelim();
|
|
78
|
+
}
|
|
79
|
+
}, (reader, length) => {
|
|
80
|
+
const obj = {
|
|
81
|
+
identityKey: new Uint8Array(0),
|
|
82
|
+
identitySig: new Uint8Array(0)
|
|
83
|
+
};
|
|
84
|
+
const end = length == null ? reader.len : reader.pos + length;
|
|
85
|
+
while (reader.pos < end) {
|
|
86
|
+
const tag = reader.uint32();
|
|
87
|
+
switch (tag >>> 3) {
|
|
88
|
+
case 1:
|
|
89
|
+
obj.identityKey = reader.bytes();
|
|
90
|
+
break;
|
|
91
|
+
case 2:
|
|
92
|
+
obj.identitySig = reader.bytes();
|
|
93
|
+
break;
|
|
94
|
+
case 4:
|
|
95
|
+
obj.extensions = NoiseExtensions.codec().decode(reader, reader.uint32());
|
|
96
|
+
break;
|
|
97
|
+
default:
|
|
98
|
+
reader.skipType(tag & 7);
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return obj;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return _codec;
|
|
106
|
+
};
|
|
107
|
+
NoiseHandshakePayload.encode = (obj) => {
|
|
108
|
+
return encodeMessage(obj, NoiseHandshakePayload.codec());
|
|
109
|
+
};
|
|
110
|
+
NoiseHandshakePayload.decode = (buf) => {
|
|
111
|
+
return decodeMessage(buf, NoiseHandshakePayload.codec());
|
|
112
|
+
};
|
|
113
|
+
})(NoiseHandshakePayload || (NoiseHandshakePayload = {}));
|
|
114
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../src/proto/payload.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,+BAA+B;AAC/B,oDAAoD;AACpD,8EAA8E;AAC9E,0DAA0D;AAE1D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAQvE,MAAM,KAAW,eAAe,CAsD/B;AAtDD,WAAiB,eAAe;IAC9B,IAAI,MAA8B,CAAA;IAErB,qBAAK,GAAG,GAA2B,EAAE;QAChD,IAAI,MAAM,IAAI,IAAI,EAAE;YAClB,MAAM,GAAG,OAAO,CAAkB,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE;gBACtD,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK,EAAE;oBAClC,CAAC,CAAC,IAAI,EAAE,CAAA;iBACT;gBAED,IAAI,GAAG,CAAC,sBAAsB,IAAI,IAAI,EAAE;oBACtC,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,sBAAsB,EAAE;wBAC9C,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;wBACZ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;qBACf;iBACF;gBAED,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK,EAAE;oBAClC,CAAC,CAAC,MAAM,EAAE,CAAA;iBACX;YACH,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;gBACpB,MAAM,GAAG,GAAQ;oBACf,sBAAsB,EAAE,EAAE;iBAC3B,CAAA;gBAED,MAAM,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,MAAM,CAAA;gBAE7D,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;oBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;oBAE3B,QAAQ,GAAG,KAAK,CAAC,EAAE;wBACjB,KAAK,CAAC;4BACJ,GAAG,CAAC,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;4BAC/C,MAAK;wBACP;4BACE,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;4BACxB,MAAK;qBACR;iBACF;gBAED,OAAO,GAAG,CAAA;YACZ,CAAC,CAAC,CAAA;SACH;QAED,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IAEY,sBAAM,GAAG,CAAC,GAA6B,EAAc,EAAE;QAClE,OAAO,aAAa,CAAC,GAAG,EAAE,eAAe,CAAC,KAAK,EAAE,CAAC,CAAA;IACpD,CAAC,CAAA;IAEY,sBAAM,GAAG,CAAC,GAAgC,EAAmB,EAAE;QAC1E,OAAO,aAAa,CAAC,GAAG,EAAE,eAAe,CAAC,KAAK,EAAE,CAAC,CAAA;IACpD,CAAC,CAAA;AACH,CAAC,EAtDgB,eAAe,KAAf,eAAe,QAsD/B;AAQD,MAAM,KAAW,qBAAqB,CAuErC;AAvED,WAAiB,qBAAqB;IACpC,IAAI,MAAoC,CAAA;IAE3B,2BAAK,GAAG,GAAiC,EAAE;QACtD,IAAI,MAAM,IAAI,IAAI,EAAE;YAClB,MAAM,GAAG,OAAO,CAAwB,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE;gBAC5D,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK,EAAE;oBAClC,CAAC,CAAC,IAAI,EAAE,CAAA;iBACT;gBAED,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE;oBAC9F,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;oBACZ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;iBAC9C;gBAED,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE;oBAC9F,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;oBACZ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;iBAC9C;gBAED,IAAI,GAAG,CAAC,UAAU,IAAI,IAAI,EAAE;oBAC1B,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;oBACZ,eAAe,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE;wBAChD,aAAa,EAAE,KAAK;qBACrB,CAAC,CAAA;iBACH;gBAED,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK,EAAE;oBAClC,CAAC,CAAC,MAAM,EAAE,CAAA;iBACX;YACH,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;gBACpB,MAAM,GAAG,GAAQ;oBACf,WAAW,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC;oBAC9B,WAAW,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC;iBAC/B,CAAA;gBAED,MAAM,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,MAAM,CAAA;gBAE7D,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;oBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;oBAE3B,QAAQ,GAAG,KAAK,CAAC,EAAE;wBACjB,KAAK,CAAC;4BACJ,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,EAAE,CAAA;4BAChC,MAAK;wBACP,KAAK,CAAC;4BACJ,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,EAAE,CAAA;4BAChC,MAAK;wBACP,KAAK,CAAC;4BACJ,GAAG,CAAC,UAAU,GAAG,eAAe,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;4BACxE,MAAK;wBACP;4BACE,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;4BACxB,MAAK;qBACR;iBACF;gBAED,OAAO,GAAG,CAAA;YACZ,CAAC,CAAC,CAAA;SACH;QAED,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IAEY,4BAAM,GAAG,CAAC,GAAmC,EAAc,EAAE;QACxE,OAAO,aAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAA;IAC1D,CAAC,CAAA;IAEY,4BAAM,GAAG,CAAC,GAAgC,EAAyB,EAAE;QAChF,OAAO,aAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAA;IAC1D,CAAC,CAAA;AACH,CAAC,EAvEgB,qBAAqB,KAArB,qBAAqB,QAuErC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type NoiseExtensions, NoiseHandshakePayload } from './proto/payload.js';
|
|
2
|
+
import type { bytes } from './@types/basic.js';
|
|
3
|
+
import type { PeerId } from '@libp2p/interface/peer-id';
|
|
4
|
+
export declare function getPayload(localPeer: PeerId, staticPublicKey: bytes, extensions?: NoiseExtensions): Promise<bytes>;
|
|
5
|
+
export declare function createHandshakePayload(libp2pPublicKey: Uint8Array, signedPayload: Uint8Array, extensions?: NoiseExtensions): bytes;
|
|
6
|
+
export declare function signPayload(peerId: PeerId, payload: bytes): Promise<bytes>;
|
|
7
|
+
export declare function getPeerIdFromPayload(payload: NoiseHandshakePayload): Promise<PeerId>;
|
|
8
|
+
export declare function decodePayload(payload: bytes | Uint8Array): NoiseHandshakePayload;
|
|
9
|
+
export declare function getHandshakePayload(publicKey: bytes): bytes;
|
|
10
|
+
/**
|
|
11
|
+
* Verifies signed payload, throws on any irregularities.
|
|
12
|
+
*
|
|
13
|
+
* @param {bytes} noiseStaticKey - owner's noise static key
|
|
14
|
+
* @param {bytes} payload - decoded payload
|
|
15
|
+
* @param {PeerId} remotePeer - owner's libp2p peer ID
|
|
16
|
+
* @returns {Promise<PeerId>} - peer ID of payload owner
|
|
17
|
+
*/
|
|
18
|
+
export declare function verifySignedPayload(noiseStaticKey: bytes, payload: NoiseHandshakePayload, remotePeer: PeerId): Promise<PeerId>;
|
|
19
|
+
export declare function isValidPublicKey(pk: bytes): boolean;
|
|
20
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAEvD,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,KAAK,EACtB,UAAU,CAAC,EAAE,eAAe,GAC3B,OAAO,CAAC,KAAK,CAAC,CAYhB;AAED,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,UAAU,EACzB,UAAU,CAAC,EAAE,eAAe,GAC3B,KAAK,CAMP;AAED,wBAAsB,WAAW,CAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAQjF;AAED,wBAAsB,oBAAoB,CAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE3F;AAED,wBAAgB,aAAa,CAAE,OAAO,EAAE,KAAK,GAAG,UAAU,GAAG,qBAAqB,CAEjF;AAED,wBAAgB,mBAAmB,CAAE,SAAS,EAAE,KAAK,GAAG,KAAK,CAG5D;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,cAAc,EAAE,KAAK,EACrB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED,wBAAgB,gBAAgB,CAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAUpD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { unmarshalPublicKey, unmarshalPrivateKey } from '@libp2p/crypto/keys';
|
|
2
|
+
import { peerIdFromKeys } from '@libp2p/peer-id';
|
|
3
|
+
import { concat as uint8ArrayConcat } from 'uint8arrays/concat';
|
|
4
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
|
|
5
|
+
import { NoiseHandshakePayload } from './proto/payload.js';
|
|
6
|
+
export async function getPayload(localPeer, staticPublicKey, extensions) {
|
|
7
|
+
const signedPayload = await signPayload(localPeer, getHandshakePayload(staticPublicKey));
|
|
8
|
+
if (localPeer.publicKey == null) {
|
|
9
|
+
throw new Error('PublicKey was missing from local PeerId');
|
|
10
|
+
}
|
|
11
|
+
return createHandshakePayload(localPeer.publicKey, signedPayload, extensions);
|
|
12
|
+
}
|
|
13
|
+
export function createHandshakePayload(libp2pPublicKey, signedPayload, extensions) {
|
|
14
|
+
return NoiseHandshakePayload.encode({
|
|
15
|
+
identityKey: libp2pPublicKey,
|
|
16
|
+
identitySig: signedPayload,
|
|
17
|
+
extensions: extensions ?? { webtransportCerthashes: [] }
|
|
18
|
+
}).subarray();
|
|
19
|
+
}
|
|
20
|
+
export async function signPayload(peerId, payload) {
|
|
21
|
+
if (peerId.privateKey == null) {
|
|
22
|
+
throw new Error('PrivateKey was missing from PeerId');
|
|
23
|
+
}
|
|
24
|
+
const privateKey = await unmarshalPrivateKey(peerId.privateKey);
|
|
25
|
+
return privateKey.sign(payload);
|
|
26
|
+
}
|
|
27
|
+
export async function getPeerIdFromPayload(payload) {
|
|
28
|
+
return peerIdFromKeys(payload.identityKey);
|
|
29
|
+
}
|
|
30
|
+
export function decodePayload(payload) {
|
|
31
|
+
return NoiseHandshakePayload.decode(payload);
|
|
32
|
+
}
|
|
33
|
+
export function getHandshakePayload(publicKey) {
|
|
34
|
+
const prefix = uint8ArrayFromString('noise-libp2p-static-key:');
|
|
35
|
+
return uint8ArrayConcat([prefix, publicKey], prefix.length + publicKey.length);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Verifies signed payload, throws on any irregularities.
|
|
39
|
+
*
|
|
40
|
+
* @param {bytes} noiseStaticKey - owner's noise static key
|
|
41
|
+
* @param {bytes} payload - decoded payload
|
|
42
|
+
* @param {PeerId} remotePeer - owner's libp2p peer ID
|
|
43
|
+
* @returns {Promise<PeerId>} - peer ID of payload owner
|
|
44
|
+
*/
|
|
45
|
+
export async function verifySignedPayload(noiseStaticKey, payload, remotePeer) {
|
|
46
|
+
// Unmarshaling from PublicKey protobuf
|
|
47
|
+
const payloadPeerId = await peerIdFromKeys(payload.identityKey);
|
|
48
|
+
if (!payloadPeerId.equals(remotePeer)) {
|
|
49
|
+
throw new Error(`Payload identity key ${payloadPeerId.toString()} does not match expected remote peer ${remotePeer.toString()}`);
|
|
50
|
+
}
|
|
51
|
+
const generatedPayload = getHandshakePayload(noiseStaticKey);
|
|
52
|
+
if (payloadPeerId.publicKey == null) {
|
|
53
|
+
throw new Error('PublicKey was missing from PeerId');
|
|
54
|
+
}
|
|
55
|
+
if (payload.identitySig == null) {
|
|
56
|
+
throw new Error('Signature was missing from message');
|
|
57
|
+
}
|
|
58
|
+
const publicKey = unmarshalPublicKey(payloadPeerId.publicKey);
|
|
59
|
+
const valid = await publicKey.verify(generatedPayload, payload.identitySig);
|
|
60
|
+
if (!valid) {
|
|
61
|
+
throw new Error("Static key doesn't match to peer that signed payload!");
|
|
62
|
+
}
|
|
63
|
+
return payloadPeerId;
|
|
64
|
+
}
|
|
65
|
+
export function isValidPublicKey(pk) {
|
|
66
|
+
if (!(pk instanceof Uint8Array)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (pk.length !== 32) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@libp2p/noise",
|
|
3
|
+
"version": "12.0.1",
|
|
4
|
+
"author": "ChainSafe <info@chainsafe.io>",
|
|
5
|
+
"license": "Apache-2.0 OR MIT",
|
|
6
|
+
"homepage": "https://github.com/ChainSafe/js-libp2p-noise#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ChainSafe/js-libp2p-noise.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/ChainSafe/js-libp2p-noise/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"crypto",
|
|
16
|
+
"libp2p",
|
|
17
|
+
"noise"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=16.0.0",
|
|
21
|
+
"npm": ">=7.0.0"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"types": "./dist/src/index.d.ts",
|
|
25
|
+
"files": [
|
|
26
|
+
"src",
|
|
27
|
+
"dist",
|
|
28
|
+
"!dist/test",
|
|
29
|
+
"!**/*.tsbuildinfo"
|
|
30
|
+
],
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/src/index.d.ts",
|
|
34
|
+
"import": "./dist/src/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"eslintConfig": {
|
|
38
|
+
"extends": "ipfs",
|
|
39
|
+
"parserOptions": {
|
|
40
|
+
"sourceType": "module"
|
|
41
|
+
},
|
|
42
|
+
"rules": {
|
|
43
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
44
|
+
"@typescript-eslint/explicit-function-return-type": "warn",
|
|
45
|
+
"@typescript-eslint/strict-boolean-expressions": "off"
|
|
46
|
+
},
|
|
47
|
+
"ignorePatterns": [
|
|
48
|
+
"src/proto/payload.js",
|
|
49
|
+
"src/proto/payload.d.ts",
|
|
50
|
+
"test/fixtures/node-globals.js"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"bench": "node benchmarks/benchmark.js",
|
|
55
|
+
"clean": "aegir clean",
|
|
56
|
+
"dep-check": "aegir dep-check",
|
|
57
|
+
"build": "aegir build",
|
|
58
|
+
"lint": "aegir lint",
|
|
59
|
+
"lint:fix": "aegir lint --fix",
|
|
60
|
+
"test": "aegir test",
|
|
61
|
+
"test:node": "aegir test -t node",
|
|
62
|
+
"test:browser": "aegir test -t browser -t webworker",
|
|
63
|
+
"test:electron-main": "aegir test -t electron-main",
|
|
64
|
+
"docs": "aegir docs",
|
|
65
|
+
"proto:gen": "protons ./src/proto/payload.proto",
|
|
66
|
+
"prepublish": "npm run build"
|
|
67
|
+
},
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"@libp2p/crypto": "^1.0.11",
|
|
70
|
+
"@libp2p/interface": "~0.0.1",
|
|
71
|
+
"@libp2p/logger": "^2.1.1",
|
|
72
|
+
"@libp2p/peer-id": "^2.0.0",
|
|
73
|
+
"@stablelib/chacha20poly1305": "^1.0.1",
|
|
74
|
+
"@noble/hashes": "^1.3.0",
|
|
75
|
+
"@stablelib/x25519": "^1.0.3",
|
|
76
|
+
"it-length-prefixed": "^9.0.1",
|
|
77
|
+
"it-length-prefixed-stream": "^1.0.0",
|
|
78
|
+
"it-byte-stream": "^1.0.0",
|
|
79
|
+
"it-pair": "^2.0.2",
|
|
80
|
+
"it-pipe": "^3.0.1",
|
|
81
|
+
"it-stream-types": "^2.0.1",
|
|
82
|
+
"protons-runtime": "^5.0.0",
|
|
83
|
+
"uint8arraylist": "^2.3.2",
|
|
84
|
+
"uint8arrays": "^4.0.2"
|
|
85
|
+
},
|
|
86
|
+
"devDependencies": {
|
|
87
|
+
"@libp2p/interface-compliance-tests": "^3.0.0",
|
|
88
|
+
"@libp2p/peer-id-factory": "^2.0.0",
|
|
89
|
+
"@types/sinon": "^10.0.14",
|
|
90
|
+
"aegir": "^39.0.5",
|
|
91
|
+
"iso-random-stream": "^2.0.2",
|
|
92
|
+
"protons": "^7.0.0",
|
|
93
|
+
"sinon": "^15.0.0"
|
|
94
|
+
},
|
|
95
|
+
"browser": {
|
|
96
|
+
"./dist/src/alloc-unsafe.js": "./dist/src/alloc-unsafe-browser.js",
|
|
97
|
+
"util": false
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { bytes } from './basic.js'
|
|
2
|
+
import type { NoiseSession } from './handshake.js'
|
|
3
|
+
import type { NoiseExtensions } from '../proto/payload.js'
|
|
4
|
+
import type { PeerId } from '@libp2p/interface/peer-id'
|
|
5
|
+
|
|
6
|
+
export interface IHandshake {
|
|
7
|
+
session: NoiseSession
|
|
8
|
+
remotePeer: PeerId
|
|
9
|
+
remoteExtensions: NoiseExtensions
|
|
10
|
+
encrypt: (plaintext: bytes, session: NoiseSession) => bytes
|
|
11
|
+
decrypt: (ciphertext: bytes, session: NoiseSession, dst?: Uint8Array) => { plaintext: bytes, valid: boolean }
|
|
12
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { bytes, bytes32, uint64 } from './basic.js'
|
|
2
|
+
import type { KeyPair } from './libp2p.js'
|
|
3
|
+
import type { Nonce } from '../nonce.js'
|
|
4
|
+
|
|
5
|
+
export type Hkdf = [bytes, bytes, bytes]
|
|
6
|
+
|
|
7
|
+
export interface MessageBuffer {
|
|
8
|
+
ne: bytes32
|
|
9
|
+
ns: bytes
|
|
10
|
+
ciphertext: bytes
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface CipherState {
|
|
14
|
+
k: bytes32
|
|
15
|
+
// For performance reasons, the nonce is represented as a Nonce object
|
|
16
|
+
// The nonce is treated as a uint64, even though the underlying `number` only has 52 safely-available bits.
|
|
17
|
+
n: Nonce
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SymmetricState {
|
|
21
|
+
cs: CipherState
|
|
22
|
+
ck: bytes32 // chaining key
|
|
23
|
+
h: bytes32 // handshake hash
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface HandshakeState {
|
|
27
|
+
ss: SymmetricState
|
|
28
|
+
s: KeyPair
|
|
29
|
+
e?: KeyPair
|
|
30
|
+
rs: bytes32
|
|
31
|
+
re: bytes32
|
|
32
|
+
psk: bytes32
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface NoiseSession {
|
|
36
|
+
hs: HandshakeState
|
|
37
|
+
h?: bytes32
|
|
38
|
+
cs1?: CipherState
|
|
39
|
+
cs2?: CipherState
|
|
40
|
+
mc: uint64
|
|
41
|
+
i: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface INoisePayload {
|
|
45
|
+
identityKey: bytes
|
|
46
|
+
identitySig: bytes
|
|
47
|
+
data: bytes
|
|
48
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { bytes32 } from './basic.js'
|
|
2
|
+
import type { NoiseExtensions } from '../proto/payload.js'
|
|
3
|
+
import type { ConnectionEncrypter } from '@libp2p/interface/connection-encrypter'
|
|
4
|
+
|
|
5
|
+
export interface KeyPair {
|
|
6
|
+
publicKey: bytes32
|
|
7
|
+
privateKey: bytes32
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface INoiseConnection extends ConnectionEncrypter<NoiseExtensions> {}
|
package/src/constants.ts
ADDED