@bsv/sdk 1.2.20 → 1.2.22
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/cjs/package.json +3 -3
- package/dist/cjs/src/auth/Peer.js +536 -0
- package/dist/cjs/src/auth/Peer.js.map +1 -0
- package/dist/cjs/src/auth/SessionManager.js +66 -0
- package/dist/cjs/src/auth/SessionManager.js.map +1 -0
- package/dist/cjs/src/auth/{Certificate.js → certificates/Certificate.js} +22 -26
- package/dist/cjs/src/auth/certificates/Certificate.js.map +1 -0
- package/dist/cjs/src/auth/certificates/MasterCertificate.js +79 -0
- package/dist/cjs/src/auth/certificates/MasterCertificate.js.map +1 -0
- package/dist/cjs/src/auth/certificates/VerifiableCertificate.js +49 -0
- package/dist/cjs/src/auth/certificates/VerifiableCertificate.js.map +1 -0
- package/dist/cjs/src/auth/certificates/index.js +25 -0
- package/dist/cjs/src/auth/certificates/index.js.map +1 -0
- package/dist/cjs/src/auth/clients/AuthFetch.js +411 -0
- package/dist/cjs/src/auth/clients/AuthFetch.js.map +1 -0
- package/dist/cjs/src/auth/clients/index.js +18 -0
- package/dist/cjs/src/auth/clients/index.js.map +1 -0
- package/dist/cjs/src/auth/index.js +20 -5
- package/dist/cjs/src/auth/index.js.map +1 -1
- package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js +259 -0
- package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js.map +1 -0
- package/dist/cjs/src/auth/transports/index.js +18 -0
- package/dist/cjs/src/auth/transports/index.js.map +1 -0
- package/dist/cjs/src/auth/types.js +3 -0
- package/dist/cjs/src/auth/types.js.map +1 -0
- package/dist/cjs/src/auth/utils/certificateHelpers.js +51 -0
- package/dist/cjs/src/auth/utils/certificateHelpers.js.map +1 -0
- package/dist/cjs/src/auth/utils/createNonce.js +19 -0
- package/dist/cjs/src/auth/utils/createNonce.js.map +1 -0
- package/dist/cjs/src/auth/utils/getVerifiableCertificates.js +31 -0
- package/dist/cjs/src/auth/utils/getVerifiableCertificates.js.map +1 -0
- package/dist/cjs/src/auth/utils/index.js +22 -0
- package/dist/cjs/src/auth/utils/index.js.map +1 -0
- package/dist/cjs/src/auth/utils/validateCertificates.js +42 -0
- package/dist/cjs/src/auth/utils/validateCertificates.js.map +1 -0
- package/dist/cjs/src/auth/utils/verifyNonce.js +27 -0
- package/dist/cjs/src/auth/utils/verifyNonce.js.map +1 -0
- package/dist/cjs/src/primitives/Point.js +1 -1
- package/dist/cjs/src/primitives/Point.js.map +1 -1
- package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js +1 -1
- package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js.map +1 -1
- package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js +148 -148
- package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/Peer.js +533 -0
- package/dist/esm/src/auth/Peer.js.map +1 -0
- package/dist/esm/src/auth/SessionManager.js +63 -0
- package/dist/esm/src/auth/SessionManager.js.map +1 -0
- package/dist/esm/src/auth/{Certificate.js → certificates/Certificate.js} +1 -2
- package/dist/esm/src/auth/certificates/Certificate.js.map +1 -0
- package/dist/esm/src/auth/certificates/MasterCertificate.js +73 -0
- package/dist/esm/src/auth/certificates/MasterCertificate.js.map +1 -0
- package/dist/esm/src/auth/certificates/VerifiableCertificate.js +44 -0
- package/dist/esm/src/auth/certificates/VerifiableCertificate.js.map +1 -0
- package/dist/esm/src/auth/certificates/index.js +4 -0
- package/dist/esm/src/auth/certificates/index.js.map +1 -0
- package/dist/esm/src/auth/clients/AuthFetch.js +409 -0
- package/dist/esm/src/auth/clients/AuthFetch.js.map +1 -0
- package/dist/esm/src/auth/clients/index.js +2 -0
- package/dist/esm/src/auth/clients/index.js.map +1 -0
- package/dist/esm/src/auth/index.js +7 -1
- package/dist/esm/src/auth/index.js.map +1 -1
- package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js +258 -0
- package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js.map +1 -0
- package/dist/esm/src/auth/transports/index.js +2 -0
- package/dist/esm/src/auth/transports/index.js.map +1 -0
- package/dist/esm/src/auth/types.js +2 -0
- package/dist/esm/src/auth/types.js.map +1 -0
- package/dist/esm/src/auth/utils/certificateHelpers.js +47 -0
- package/dist/esm/src/auth/utils/certificateHelpers.js.map +1 -0
- package/dist/esm/src/auth/utils/createNonce.js +16 -0
- package/dist/esm/src/auth/utils/createNonce.js.map +1 -0
- package/dist/esm/src/auth/utils/getVerifiableCertificates.js +27 -0
- package/dist/esm/src/auth/utils/getVerifiableCertificates.js.map +1 -0
- package/dist/esm/src/auth/utils/index.js +6 -0
- package/dist/esm/src/auth/utils/index.js.map +1 -0
- package/dist/esm/src/auth/utils/validateCertificates.js +38 -0
- package/dist/esm/src/auth/utils/validateCertificates.js.map +1 -0
- package/dist/esm/src/auth/utils/verifyNonce.js +24 -0
- package/dist/esm/src/auth/utils/verifyNonce.js.map +1 -0
- package/dist/esm/src/primitives/Point.js +1 -1
- package/dist/esm/src/primitives/Point.js.map +1 -1
- package/dist/esm/src/wallet/substrates/WalletWireProcessor.js +1 -1
- package/dist/esm/src/wallet/substrates/WalletWireProcessor.js.map +1 -1
- package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js +1 -1
- package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/Peer.d.ts +193 -0
- package/dist/types/src/auth/Peer.d.ts.map +1 -0
- package/dist/types/src/auth/SessionManager.d.ts +42 -0
- package/dist/types/src/auth/SessionManager.d.ts.map +1 -0
- package/dist/types/src/auth/{Certificate.d.ts → certificates/Certificate.d.ts} +1 -1
- package/dist/types/src/auth/certificates/Certificate.d.ts.map +1 -0
- package/dist/types/src/auth/certificates/MasterCertificate.d.ts +38 -0
- package/dist/types/src/auth/certificates/MasterCertificate.d.ts.map +1 -0
- package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts +26 -0
- package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts.map +1 -0
- package/dist/types/src/auth/certificates/index.d.ts +4 -0
- package/dist/types/src/auth/certificates/index.d.ts.map +1 -0
- package/dist/types/src/auth/clients/AuthFetch.d.ts +87 -0
- package/dist/types/src/auth/clients/AuthFetch.d.ts.map +1 -0
- package/dist/types/src/auth/clients/index.d.ts +2 -0
- package/dist/types/src/auth/clients/index.d.ts.map +1 -0
- package/dist/types/src/auth/index.d.ts +7 -1
- package/dist/types/src/auth/index.d.ts.map +1 -1
- package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts +51 -0
- package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts.map +1 -0
- package/dist/types/src/auth/transports/index.d.ts +2 -0
- package/dist/types/src/auth/transports/index.d.ts.map +1 -0
- package/dist/types/src/auth/types.d.ts +31 -0
- package/dist/types/src/auth/types.d.ts.map +1 -0
- package/dist/types/src/auth/utils/certificateHelpers.d.ts +26 -0
- package/dist/types/src/auth/utils/certificateHelpers.d.ts.map +1 -0
- package/dist/types/src/auth/utils/createNonce.d.ts +8 -0
- package/dist/types/src/auth/utils/createNonce.d.ts.map +1 -0
- package/dist/types/src/auth/utils/getVerifiableCertificates.d.ts +13 -0
- package/dist/types/src/auth/utils/getVerifiableCertificates.d.ts.map +1 -0
- package/dist/types/src/auth/utils/index.d.ts +6 -0
- package/dist/types/src/auth/utils/index.d.ts.map +1 -0
- package/dist/types/src/auth/utils/validateCertificates.d.ts +12 -0
- package/dist/types/src/auth/utils/validateCertificates.d.ts.map +1 -0
- package/dist/types/src/auth/utils/verifyNonce.d.ts +9 -0
- package/dist/types/src/auth/utils/verifyNonce.d.ts.map +1 -0
- package/dist/types/src/primitives/Point.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/README.md +1 -0
- package/docs/auth.md +1193 -0
- package/package.json +13 -3
- package/src/auth/Peer.ts +600 -0
- package/src/auth/SessionManager.ts +71 -0
- package/src/auth/__tests/Peer.test.ts +599 -0
- package/src/auth/__tests/SessionManager.test.ts +87 -0
- package/src/auth/{Certificate.ts → certificates/Certificate.ts} +15 -8
- package/src/auth/certificates/MasterCertificate.ts +106 -0
- package/src/auth/certificates/VerifiableCertificate.ts +73 -0
- package/src/auth/certificates/__tests/Certificate.test.ts +282 -0
- package/src/auth/certificates/index.ts +3 -0
- package/src/auth/clients/AuthFetch.ts +482 -0
- package/src/auth/clients/index.ts +1 -0
- package/src/auth/index.ts +7 -1
- package/src/auth/transports/SimplifiedFetchTransport.ts +288 -0
- package/src/auth/transports/index.ts +1 -0
- package/src/auth/types.ts +41 -0
- package/src/auth/utils/__tests/cryptononce.test.ts +84 -0
- package/src/auth/utils/__tests/getVerifiableCertificates.test.ts +126 -0
- package/src/auth/utils/__tests/validateCertificates.test.ts +142 -0
- package/src/auth/utils/certificateHelpers.ts +86 -0
- package/src/auth/utils/createNonce.ts +16 -0
- package/src/auth/utils/getVerifiableCertificates.ts +40 -0
- package/src/auth/utils/index.ts +5 -0
- package/src/auth/utils/validateCertificates.ts +54 -0
- package/src/auth/utils/verifyNonce.ts +27 -0
- package/src/primitives/Point.ts +59 -59
- package/src/wallet/substrates/WalletWireProcessor.ts +1 -1
- package/src/wallet/substrates/WalletWireTransceiver.ts +1 -1
- package/dist/cjs/src/auth/Certificate.js.map +0 -1
- package/dist/esm/src/auth/Certificate.js.map +0 -1
- package/dist/types/src/auth/Certificate.d.ts.map +0 -1
- package/src/auth/__tests/Certificate.test.ts +0 -282
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsv/sdk",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "BSV Blockchain Software Development Kit",
|
|
6
6
|
"main": "dist/cjs/mod.js",
|
|
@@ -164,6 +164,16 @@
|
|
|
164
164
|
"require": "./dist/cjs/src/auth/*.js",
|
|
165
165
|
"types": "./dist/types/src/auth/*.d.ts"
|
|
166
166
|
},
|
|
167
|
+
"./auth/certificate": {
|
|
168
|
+
"import": "./dist/esm/src/auth/certificate/index.js",
|
|
169
|
+
"require": "./dist/cjs/src/auth/certificate/index.js",
|
|
170
|
+
"types": "./dist/types/src/auth/certificate/index.d.ts"
|
|
171
|
+
},
|
|
172
|
+
"./auth/certificate/*": {
|
|
173
|
+
"import": "./dist/esm/src/auth/certificate/*.js",
|
|
174
|
+
"require": "./dist/cjs/src/auth/certificate/*.js",
|
|
175
|
+
"types": "./dist/types/src/auth/certificate/*.d.ts"
|
|
176
|
+
},
|
|
167
177
|
"./overlay-tools": {
|
|
168
178
|
"import": "./dist/esm/src/overlay-tools/index.js",
|
|
169
179
|
"require": "./dist/cjs/src/overlay-tools/index.js",
|
|
@@ -188,7 +198,7 @@
|
|
|
188
198
|
"build:umd": "webpack --config webpack.config.js",
|
|
189
199
|
"dev": "tsc -b -w",
|
|
190
200
|
"prepublish": "npm run build",
|
|
191
|
-
"doc": "ts2md
|
|
201
|
+
"doc": "ts2md"
|
|
192
202
|
},
|
|
193
203
|
"repository": {
|
|
194
204
|
"type": "git",
|
|
@@ -214,7 +224,7 @@
|
|
|
214
224
|
"ts-jest": "^29.1.1",
|
|
215
225
|
"ts-loader": "^9.5.1",
|
|
216
226
|
"ts-standard": "^12.0.2",
|
|
217
|
-
"ts2md": "^0.2.
|
|
227
|
+
"ts2md": "^0.2.5",
|
|
218
228
|
"tsconfig-to-dual-package": "^1.2.0",
|
|
219
229
|
"typescript": "^5.2.2",
|
|
220
230
|
"webpack": "^5.95.0",
|
package/src/auth/Peer.ts
ADDED
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
import { SessionManager } from './SessionManager.js'
|
|
2
|
+
import { createNonce, verifyNonce, getVerifiableCertificates, validateCertificates } from './utils/index.js'
|
|
3
|
+
import { AuthMessage, PeerSession, RequestedCertificateSet, Transport } from './types.js'
|
|
4
|
+
import { VerifiableCertificate } from './certificates/VerifiableCertificate.js'
|
|
5
|
+
import { Random, Utils, Wallet } from '../../mod.js'
|
|
6
|
+
|
|
7
|
+
const AUTH_VERSION = '0.1'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Represents a peer capable of performing mutual authentication.
|
|
11
|
+
* Manages sessions, handles authentication handshakes, certificate requests and responses,
|
|
12
|
+
* and sending and receiving general messages over a transport layer.
|
|
13
|
+
*/
|
|
14
|
+
export class Peer {
|
|
15
|
+
public sessionManager: SessionManager
|
|
16
|
+
private readonly transport: Transport
|
|
17
|
+
private readonly wallet: Wallet
|
|
18
|
+
certificatesToRequest: RequestedCertificateSet
|
|
19
|
+
private readonly onGeneralMessageReceivedCallbacks: Map<number, (senderPublicKey: string, payload: number[]) => void> = new Map()
|
|
20
|
+
private readonly onCertificatesReceivedCallbacks: Map<number, (senderPublicKey: string, certs: VerifiableCertificate[]) => void> = new Map()
|
|
21
|
+
private readonly onCertificateRequestReceivedCallbacks: Map<number, (senderPublicKey: string, requestedCertificates: RequestedCertificateSet) => void> = new Map()
|
|
22
|
+
private readonly onInitialResponseReceivedCallbacks: Map<number, ({ callback: (sessionNonce: string) => void, sessionNonce: string })> = new Map()
|
|
23
|
+
|
|
24
|
+
// Single shared counter for all callback types
|
|
25
|
+
private callbackIdCounter: number = 0
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new Peer instance
|
|
29
|
+
*
|
|
30
|
+
* @param {Wallet} wallet - The wallet instance used for cryptographic operations.
|
|
31
|
+
* @param {Transport} transport - The transport mechanism used for sending and receiving messages.
|
|
32
|
+
* @param {RequestedCertificateSet} [certificatesToRequest] - Optional set of certificates to request from a peer during the initial handshake.
|
|
33
|
+
* @param {SessionManager} [sessionManager] - Optional SessionManager to be used for managing peer sessions.
|
|
34
|
+
*/
|
|
35
|
+
constructor (
|
|
36
|
+
wallet: Wallet,
|
|
37
|
+
transport: Transport,
|
|
38
|
+
certificatesToRequest?: RequestedCertificateSet,
|
|
39
|
+
sessionManager?: SessionManager
|
|
40
|
+
) {
|
|
41
|
+
this.wallet = wallet
|
|
42
|
+
this.transport = transport
|
|
43
|
+
this.certificatesToRequest = certificatesToRequest ?? { certifiers: [], types: {} }
|
|
44
|
+
this.transport.onData(this.handleIncomingMessage.bind(this))
|
|
45
|
+
this.sessionManager = sessionManager || new SessionManager()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Sends a general message to a peer, and initiates a handshake if necessary.
|
|
50
|
+
*
|
|
51
|
+
* @param {number[]} message - The message payload to send.
|
|
52
|
+
* @param {string} [identityKey] - The identity public key of the peer. If not provided, a handshake will be initiated.
|
|
53
|
+
* @returns {Promise<void>}
|
|
54
|
+
* @throws Will throw an error if the message fails to send.
|
|
55
|
+
*/
|
|
56
|
+
async toPeer (message: number[], identityKey?: string, maxWaitTime?: number): Promise<void> {
|
|
57
|
+
const peerSession = await this.getAuthenticatedSession(identityKey, maxWaitTime)
|
|
58
|
+
|
|
59
|
+
// Prepare the general message
|
|
60
|
+
const requestNonce = Utils.toBase64(Random(32))
|
|
61
|
+
const { signature } = await this.wallet.createSignature({
|
|
62
|
+
data: message,
|
|
63
|
+
protocolID: [2, 'auth message signature'],
|
|
64
|
+
keyID: `${requestNonce} ${peerSession.peerNonce}`,
|
|
65
|
+
counterparty: peerSession.peerIdentityKey
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const generalMessage: AuthMessage = {
|
|
69
|
+
version: AUTH_VERSION,
|
|
70
|
+
messageType: 'general',
|
|
71
|
+
identityKey: (await this.wallet.getPublicKey({ identityKey: true })).publicKey,
|
|
72
|
+
nonce: requestNonce,
|
|
73
|
+
yourNonce: peerSession.peerNonce,
|
|
74
|
+
payload: message,
|
|
75
|
+
signature
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
await this.transport.send(generalMessage)
|
|
80
|
+
} catch (error) {
|
|
81
|
+
const e = new Error(`Failed to send message to peer ${peerSession.peerIdentityKey}: ${error.message}`)
|
|
82
|
+
e.stack = error.stack
|
|
83
|
+
throw e
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Sends a request for certificates to a peer.
|
|
89
|
+
* This method allows a peer to dynamically request specific certificates after
|
|
90
|
+
* an initial handshake or message has been exchanged.
|
|
91
|
+
*
|
|
92
|
+
* @param {RequestedCertificateSet} certificatesToRequest - Specifies the certifiers and types of certificates required from the peer.
|
|
93
|
+
* @param {string} [identityKey] - The identity public key of the peer. If not provided, the current session identity is used.
|
|
94
|
+
* @param {number} [maxWaitTime=10000] - Maximum time in milliseconds to wait for the peer session to be authenticated.
|
|
95
|
+
* @returns {Promise<void>} Resolves if the certificate request message is successfully sent.
|
|
96
|
+
* @throws Will throw an error if the peer session is not authenticated or if sending the request fails.
|
|
97
|
+
*/
|
|
98
|
+
async requestCertificates (certificatesToRequest: RequestedCertificateSet, identityKey?: string, maxWaitTime = 10000): Promise<void> {
|
|
99
|
+
const peerSession = await this.getAuthenticatedSession(identityKey, maxWaitTime)
|
|
100
|
+
|
|
101
|
+
// Prepare the general message
|
|
102
|
+
const requestNonce = Utils.toBase64(Random(32))
|
|
103
|
+
const { signature } = await this.wallet.createSignature({
|
|
104
|
+
data: Utils.toArray(JSON.stringify(certificatesToRequest), 'utf8'),
|
|
105
|
+
protocolID: [2, 'auth message signature'],
|
|
106
|
+
keyID: `${requestNonce} ${peerSession.peerNonce}`,
|
|
107
|
+
counterparty: peerSession.peerIdentityKey
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const certRequestMessage: AuthMessage = {
|
|
111
|
+
version: AUTH_VERSION,
|
|
112
|
+
messageType: 'certificateRequest',
|
|
113
|
+
identityKey: (await this.wallet.getPublicKey({ identityKey: true })).publicKey,
|
|
114
|
+
nonce: requestNonce,
|
|
115
|
+
initialNonce: peerSession.sessionNonce,
|
|
116
|
+
yourNonce: peerSession.peerNonce,
|
|
117
|
+
requestedCertificates: certificatesToRequest,
|
|
118
|
+
signature
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
await this.transport.send(certRequestMessage)
|
|
123
|
+
} catch (error) {
|
|
124
|
+
throw new Error(`Failed to send certificate request message to peer ${peerSession.peerIdentityKey}: ${error.message}`)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Retrieves an authenticated session for a given peer identity. If no session exists
|
|
130
|
+
* or the session is not authenticated, initiates a handshake to create or authenticate the session.
|
|
131
|
+
*
|
|
132
|
+
* @param {string} [identityKey] - The identity public key of the peer. If provided, it attempts
|
|
133
|
+
* to retrieve an existing session associated with this identity.
|
|
134
|
+
* @param {number} [maxWaitTime] - The maximum time in milliseconds to wait for the handshake
|
|
135
|
+
* to complete if a new session is required. Defaults to a pre-defined timeout if not specified.
|
|
136
|
+
* @returns {Promise<PeerSession>} - A promise that resolves with an authenticated `PeerSession`.
|
|
137
|
+
* @throws {Error} - Throws an error if the transport is not connected or if the handshake fails.
|
|
138
|
+
*/
|
|
139
|
+
async getAuthenticatedSession (identityKey?: string, maxWaitTime?: number): Promise<PeerSession> {
|
|
140
|
+
if (!this.transport) {
|
|
141
|
+
throw new Error('Peer transport is not connected!')
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let peerSession = identityKey ? this.sessionManager.getSession(identityKey) : undefined
|
|
145
|
+
if (!peerSession || !peerSession.isAuthenticated) {
|
|
146
|
+
const sessionNonce = await this.initiateHandshake(identityKey, maxWaitTime)
|
|
147
|
+
peerSession = this.sessionManager.getSession(identityKey || sessionNonce)
|
|
148
|
+
if (!peerSession.isAuthenticated) {
|
|
149
|
+
throw new Error('Unable to establish mutual authentication with peer!')
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return peerSession
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Registers a callback to listen for general messages from peers.
|
|
158
|
+
*
|
|
159
|
+
* @param {(senderPublicKey: string, payload: number[]) => void} callback - The function to call when a general message is received.
|
|
160
|
+
* @returns {number} The ID of the callback listener.
|
|
161
|
+
*/
|
|
162
|
+
listenForGeneralMessages (callback: (senderPublicKey: string, payload: number[]) => void): number {
|
|
163
|
+
const callbackID = this.callbackIdCounter++
|
|
164
|
+
this.onGeneralMessageReceivedCallbacks.set(callbackID, callback)
|
|
165
|
+
return callbackID
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Removes a general message listener.
|
|
170
|
+
*
|
|
171
|
+
* @param {number} callbackID - The ID of the callback to remove.
|
|
172
|
+
*/
|
|
173
|
+
stopListeningForGeneralMessages (callbackID: number): void {
|
|
174
|
+
this.onGeneralMessageReceivedCallbacks.delete(callbackID)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Registers a callback to listen for certificates received from peers.
|
|
179
|
+
*
|
|
180
|
+
* @param {(certs: VerifiableCertificate[]) => void} callback - The function to call when certificates are received.
|
|
181
|
+
* @returns {number} The ID of the callback listener.
|
|
182
|
+
*/
|
|
183
|
+
listenForCertificatesReceived (callback: (senderPublicKey: string, certs: VerifiableCertificate[]) => void): number {
|
|
184
|
+
const callbackID = this.callbackIdCounter++
|
|
185
|
+
this.onCertificatesReceivedCallbacks.set(callbackID, callback)
|
|
186
|
+
return callbackID
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Cancels and unsubscribes a certificatesReceived listener.
|
|
191
|
+
*
|
|
192
|
+
* @param {number} callbackID - The ID of the certificates received callback to cancel.
|
|
193
|
+
*/
|
|
194
|
+
stopListeningForCertificatesReceived (callbackID: number): void {
|
|
195
|
+
this.onCertificatesReceivedCallbacks.delete(callbackID)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Registers a callback to listen for certificates requested from peers.
|
|
200
|
+
*
|
|
201
|
+
* @param {(requestedCertificates: RequestedCertificateSet) => void} callback - The function to call when a certificate request is received
|
|
202
|
+
* @returns {number} The ID of the callback listener.
|
|
203
|
+
*/
|
|
204
|
+
listenForCertificatesRequested (callback: (senderPublicKey: string, requestedCertificates: RequestedCertificateSet) => void): number {
|
|
205
|
+
const callbackID = this.callbackIdCounter++
|
|
206
|
+
this.onCertificateRequestReceivedCallbacks.set(callbackID, callback)
|
|
207
|
+
return callbackID
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Cancels and unsubscribes a certificatesRequested listener.
|
|
212
|
+
*
|
|
213
|
+
* @param {number} callbackID - The ID of the requested certificates callback to cancel.
|
|
214
|
+
*/
|
|
215
|
+
stopListeningForCertificatesRequested (callbackID: number): void {
|
|
216
|
+
this.onCertificateRequestReceivedCallbacks.delete(callbackID)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Initiates the mutual authentication handshake with a peer.
|
|
221
|
+
*
|
|
222
|
+
* @private
|
|
223
|
+
* @param {string} [identityKey] - The identity public key of the peer.
|
|
224
|
+
* @returns {Promise<string>} A promise that resolves to the session nonce.
|
|
225
|
+
*/
|
|
226
|
+
private async initiateHandshake (identityKey?: string, maxWaitTime = 10000): Promise<string> {
|
|
227
|
+
const sessionNonce = await createNonce(this.wallet) // Initial request nonce
|
|
228
|
+
this.sessionManager.addSession({
|
|
229
|
+
isAuthenticated: false,
|
|
230
|
+
sessionNonce,
|
|
231
|
+
peerIdentityKey: identityKey
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
const initialRequest: AuthMessage = {
|
|
235
|
+
version: AUTH_VERSION,
|
|
236
|
+
messageType: 'initialRequest',
|
|
237
|
+
identityKey: (await this.wallet.getPublicKey({ identityKey: true })).publicKey,
|
|
238
|
+
initialNonce: sessionNonce,
|
|
239
|
+
requestedCertificates: this.certificatesToRequest
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
await this.transport.send(initialRequest)
|
|
243
|
+
return await this.waitForInitialResponse(sessionNonce, maxWaitTime)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Waits for the initial response from the peer after sending an initial handshake request message.
|
|
248
|
+
*
|
|
249
|
+
* @param {string} sessionNonce - The session nonce created in the initial request.
|
|
250
|
+
* @returns {Promise<string>} A promise that resolves with the session nonce when the initial response is received.
|
|
251
|
+
*/
|
|
252
|
+
private async waitForInitialResponse (sessionNonce: string, maxWaitTime = 10000): Promise<string> {
|
|
253
|
+
return await new Promise((resolve, reject) => {
|
|
254
|
+
const callbackID = this.listenForInitialResponse(sessionNonce, (sessionNonce) => {
|
|
255
|
+
clearTimeout(timeoutHandle)
|
|
256
|
+
this.stopListeningForInitialResponses(callbackID)
|
|
257
|
+
resolve(sessionNonce)
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
const timeoutHandle = setTimeout(() => {
|
|
261
|
+
this.stopListeningForInitialResponses(callbackID)
|
|
262
|
+
reject(new Error('Initial response timed out.'))
|
|
263
|
+
}, maxWaitTime)
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Adds a listener for an initial response message matching a specific initial nonce.
|
|
269
|
+
*
|
|
270
|
+
* @private
|
|
271
|
+
* @param {string} sessionNonce - The session nonce to match.
|
|
272
|
+
* @param {(sessionNonce: string) => void} callback - The callback to invoke when the initial response is received.
|
|
273
|
+
* @returns {number} The ID of the callback listener.
|
|
274
|
+
*/
|
|
275
|
+
private listenForInitialResponse (sessionNonce: string, callback: (sessionNonce: string) => void) {
|
|
276
|
+
const callbackID = this.callbackIdCounter++
|
|
277
|
+
this.onInitialResponseReceivedCallbacks.set(callbackID, { callback, sessionNonce })
|
|
278
|
+
return callbackID
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Removes a listener for initial responses.
|
|
283
|
+
*
|
|
284
|
+
* @private
|
|
285
|
+
* @param {number} callbackID - The ID of the callback to remove.
|
|
286
|
+
*/
|
|
287
|
+
private stopListeningForInitialResponses (callbackID: number) {
|
|
288
|
+
this.onInitialResponseReceivedCallbacks.delete(callbackID)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Handles incoming messages from the transport.
|
|
293
|
+
*
|
|
294
|
+
* @param {AuthMessage} message - The incoming message to process.
|
|
295
|
+
* @returns {Promise<void>}
|
|
296
|
+
*/
|
|
297
|
+
private async handleIncomingMessage (message: AuthMessage): Promise<void> {
|
|
298
|
+
if (!message.version || message.version !== AUTH_VERSION) {
|
|
299
|
+
console.error(`Invalid message auth version! Received: ${message.version}, expected: ${AUTH_VERSION}`)
|
|
300
|
+
return
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
switch (message.messageType) {
|
|
304
|
+
case 'initialRequest':
|
|
305
|
+
await this.processInitialRequest(message)
|
|
306
|
+
break
|
|
307
|
+
case 'initialResponse':
|
|
308
|
+
await this.processInitialResponse(message)
|
|
309
|
+
break
|
|
310
|
+
case 'certificateRequest':
|
|
311
|
+
await this.processCertificateRequest(message)
|
|
312
|
+
break
|
|
313
|
+
case 'certificateResponse':
|
|
314
|
+
await this.processCertificateResponse(message)
|
|
315
|
+
break
|
|
316
|
+
case 'general':
|
|
317
|
+
await this.processGeneralMessage(message)
|
|
318
|
+
break
|
|
319
|
+
default:
|
|
320
|
+
console.error(`Unknown message type of ${message.messageType} from ${message.identityKey}`)
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Processes an initial request message from a peer.
|
|
326
|
+
*
|
|
327
|
+
* @param {AuthMessage} message - The incoming initial request message.
|
|
328
|
+
* @returns {Promise<void>}
|
|
329
|
+
*/
|
|
330
|
+
async processInitialRequest (message: AuthMessage) {
|
|
331
|
+
if (!message.identityKey || !message.initialNonce) {
|
|
332
|
+
throw new Error('Missing required fields in initialResponse message.')
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Create an initial session nonce
|
|
336
|
+
const sessionNonce = await createNonce(this.wallet)
|
|
337
|
+
this.sessionManager.addSession({
|
|
338
|
+
isAuthenticated: true,
|
|
339
|
+
sessionNonce,
|
|
340
|
+
peerNonce: message.initialNonce,
|
|
341
|
+
peerIdentityKey: message.identityKey
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
// Handle initial certificate requests
|
|
345
|
+
let certificatesToInclude
|
|
346
|
+
if (message.requestedCertificates?.certifiers?.length > 0) {
|
|
347
|
+
if (this.onCertificateRequestReceivedCallbacks.size > 0) {
|
|
348
|
+
// The application wants to handle certificate requests
|
|
349
|
+
this.onCertificateRequestReceivedCallbacks.forEach(callback => {
|
|
350
|
+
callback(message.identityKey, message.requestedCertificates)
|
|
351
|
+
})
|
|
352
|
+
} else {
|
|
353
|
+
// Attempt to find exact matching certificates to return automatically to save round trips
|
|
354
|
+
certificatesToInclude = await getVerifiableCertificates(this.wallet, message.requestedCertificates, message.identityKey)
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Create the signature for the message
|
|
359
|
+
const { signature } = await this.wallet.createSignature({
|
|
360
|
+
data: Utils.toArray(message.initialNonce + sessionNonce, 'base64'),
|
|
361
|
+
protocolID: [2, 'auth message signature'],
|
|
362
|
+
keyID: `${message.initialNonce} ${sessionNonce}`,
|
|
363
|
+
counterparty: message.identityKey
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
const initialResponseMessage: AuthMessage = {
|
|
367
|
+
version: AUTH_VERSION,
|
|
368
|
+
messageType: 'initialResponse',
|
|
369
|
+
identityKey: (await this.wallet.getPublicKey({ identityKey: true })).publicKey,
|
|
370
|
+
initialNonce: sessionNonce,
|
|
371
|
+
yourNonce: message.initialNonce,
|
|
372
|
+
certificates: certificatesToInclude,
|
|
373
|
+
requestedCertificates: this.certificatesToRequest,
|
|
374
|
+
signature
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
await this.transport.send(initialResponseMessage)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Processes an initial response message from a peer.
|
|
382
|
+
*
|
|
383
|
+
* @private
|
|
384
|
+
* @param {AuthMessage} message - The incoming initial response message.
|
|
385
|
+
* @returns {Promise<void>}
|
|
386
|
+
* @throws Will throw an error if nonce verification or signature verification fails.
|
|
387
|
+
*/
|
|
388
|
+
private async processInitialResponse (message: AuthMessage) {
|
|
389
|
+
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
390
|
+
if (!validNonce) {
|
|
391
|
+
throw new Error(`Initial response nonce verification failed from peer: ${message.identityKey}`)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const peerSession = this.sessionManager.getSession(message.yourNonce)
|
|
395
|
+
if (!peerSession) {
|
|
396
|
+
throw new Error(`Peer session not found for peer: ${message.identityKey}`)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Validate message signature
|
|
400
|
+
const { valid } = await this.wallet.verifySignature({
|
|
401
|
+
data: Utils.toArray(peerSession.sessionNonce + message.initialNonce, 'base64'),
|
|
402
|
+
signature: message.signature,
|
|
403
|
+
protocolID: [2, 'auth message signature'],
|
|
404
|
+
keyID: `${peerSession.sessionNonce} ${message.initialNonce}`,
|
|
405
|
+
counterparty: message.identityKey
|
|
406
|
+
})
|
|
407
|
+
if (!valid) {
|
|
408
|
+
throw new Error(`Unable to verify initial response signature for peer: ${message.identityKey}`)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// After signature and nonce verification is complete, the peer is considered authenticated
|
|
412
|
+
// Save the peer's identity key and initial nonce
|
|
413
|
+
// This allows future requests to be linked to the same session
|
|
414
|
+
peerSession.peerNonce = message.initialNonce
|
|
415
|
+
peerSession.peerIdentityKey = message.identityKey
|
|
416
|
+
peerSession.isAuthenticated = true
|
|
417
|
+
// Run update to ensure lookup is available by both peerIdentityKey and sessionNonce
|
|
418
|
+
this.sessionManager.updateSession(peerSession)
|
|
419
|
+
|
|
420
|
+
// Process certificates received
|
|
421
|
+
if (this.certificatesToRequest?.certifiers?.length && message.certificates?.length) {
|
|
422
|
+
await validateCertificates(this.wallet, message, this.certificatesToRequest)
|
|
423
|
+
|
|
424
|
+
this.onCertificatesReceivedCallbacks.forEach(callback =>
|
|
425
|
+
callback(message.identityKey, message.certificates)
|
|
426
|
+
)
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
this.onInitialResponseReceivedCallbacks.forEach((entry) => {
|
|
430
|
+
if (entry && entry.sessionNonce === peerSession.sessionNonce) {
|
|
431
|
+
entry.callback(peerSession.sessionNonce)
|
|
432
|
+
}
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
// Check if the peer requested certificates from us
|
|
436
|
+
if (message.requestedCertificates?.certifiers?.length > 0) {
|
|
437
|
+
if (this.onCertificateRequestReceivedCallbacks.size > 0) {
|
|
438
|
+
// Application wants to handle certificate requests
|
|
439
|
+
this.onCertificateRequestReceivedCallbacks.forEach(callback => {
|
|
440
|
+
callback(message.identityKey, message.requestedCertificates)
|
|
441
|
+
})
|
|
442
|
+
} else {
|
|
443
|
+
// Attempt to find exact matching certificates to respond automatically and save round trips
|
|
444
|
+
const verifiableCertificates = await getVerifiableCertificates(this.wallet, message.requestedCertificates, message.identityKey)
|
|
445
|
+
await this.sendCertificateResponse(message.identityKey, verifiableCertificates)
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Processes an incoming certificate request message from a peer.
|
|
452
|
+
* Verifies the nonce and signature to ensure the authenticity of the request,
|
|
453
|
+
* then initiates a response with any requested certificates that are available.
|
|
454
|
+
*
|
|
455
|
+
* @param {AuthMessage} message - The certificate request message received from the peer.
|
|
456
|
+
* @throws {Error} Throws an error if nonce verification fails, or the message signature is invalid.
|
|
457
|
+
*/
|
|
458
|
+
private async processCertificateRequest (message: AuthMessage) {
|
|
459
|
+
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
460
|
+
if (!validNonce) {
|
|
461
|
+
throw new Error(`Unable to verify nonce for certificate request message from: ${message.identityKey}`)
|
|
462
|
+
}
|
|
463
|
+
const peerSession = this.sessionManager.getSession(message.yourNonce)
|
|
464
|
+
|
|
465
|
+
const { valid } = await this.wallet.verifySignature({
|
|
466
|
+
data: Utils.toArray(JSON.stringify(message.requestedCertificates), 'utf8'),
|
|
467
|
+
signature: message.signature,
|
|
468
|
+
protocolID: [2, 'auth message signature'],
|
|
469
|
+
keyID: `${message.nonce} ${peerSession.sessionNonce}`,
|
|
470
|
+
counterparty: peerSession.peerIdentityKey
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
if (!valid) {
|
|
474
|
+
throw new Error(`Invalid signature in certificate request message from ${peerSession.peerIdentityKey}`)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (message.requestedCertificates?.certifiers?.length > 0) {
|
|
478
|
+
if (this.onCertificateRequestReceivedCallbacks.size > 0) {
|
|
479
|
+
// Application wants to handle certificate requests
|
|
480
|
+
this.onCertificateRequestReceivedCallbacks.forEach(callback => {
|
|
481
|
+
callback(message.identityKey, message.requestedCertificates)
|
|
482
|
+
})
|
|
483
|
+
} else {
|
|
484
|
+
// Attempt to find exact matching certificates to respond automatically and save round trips
|
|
485
|
+
const verifiableCertificates = await getVerifiableCertificates(this.wallet, message.requestedCertificates, message.identityKey)
|
|
486
|
+
await this.sendCertificateResponse(message.identityKey, verifiableCertificates)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Sends a certificate response message containing the specified certificates to a peer.
|
|
493
|
+
*
|
|
494
|
+
* @param {string} verifierIdentityKey - The identity key of the peer requesting the certificates.
|
|
495
|
+
* @param {VerifiableCertificate[]} certificates - The list of certificates to be included in the response.
|
|
496
|
+
* @returns {Promise<void>} - A promise that resolves once the certificate response has been sent successfully.
|
|
497
|
+
*
|
|
498
|
+
* @throws {Error} Throws an error if the peer session could not be authenticated or if message signing fails.
|
|
499
|
+
*/
|
|
500
|
+
async sendCertificateResponse (
|
|
501
|
+
verifierIdentityKey: string,
|
|
502
|
+
certificates: VerifiableCertificate[]
|
|
503
|
+
) {
|
|
504
|
+
const peerSession = await this.getAuthenticatedSession(verifierIdentityKey)
|
|
505
|
+
const requestNonce = Utils.toBase64(Random(32))
|
|
506
|
+
const { signature } = await this.wallet.createSignature({
|
|
507
|
+
data: Utils.toArray(JSON.stringify(certificates), 'utf8'),
|
|
508
|
+
protocolID: [2, 'auth message signature'],
|
|
509
|
+
keyID: `${requestNonce} ${peerSession.peerNonce}`,
|
|
510
|
+
counterparty: peerSession.peerIdentityKey
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
const certificateResponse: AuthMessage = {
|
|
514
|
+
version: AUTH_VERSION,
|
|
515
|
+
messageType: 'certificateResponse',
|
|
516
|
+
identityKey: (await this.wallet.getPublicKey({ identityKey: true })).publicKey,
|
|
517
|
+
nonce: requestNonce,
|
|
518
|
+
initialNonce: peerSession.sessionNonce,
|
|
519
|
+
yourNonce: peerSession.peerNonce,
|
|
520
|
+
certificates,
|
|
521
|
+
signature
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
try {
|
|
525
|
+
await this.transport.send(certificateResponse)
|
|
526
|
+
} catch (error) {
|
|
527
|
+
throw new Error(`Failed to send certificate response message to peer ${peerSession.peerIdentityKey}: ${error.message}`)
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Processes a certificate response message from a peer.
|
|
533
|
+
*
|
|
534
|
+
* @private
|
|
535
|
+
* @param {AuthMessage} message - The incoming certificate response message.
|
|
536
|
+
* @returns {Promise<void>}
|
|
537
|
+
* @throws Will throw an error if nonce verification or signature verification fails.
|
|
538
|
+
*/
|
|
539
|
+
private async processCertificateResponse (
|
|
540
|
+
message: AuthMessage
|
|
541
|
+
) {
|
|
542
|
+
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
543
|
+
if (!validNonce) {
|
|
544
|
+
throw new Error(`Unable to verify nonce for certificate response from: ${message.identityKey}!`)
|
|
545
|
+
}
|
|
546
|
+
const peerSession = this.sessionManager.getSession(message.yourNonce)
|
|
547
|
+
|
|
548
|
+
// Validate message signature
|
|
549
|
+
const { valid } = await this.wallet.verifySignature({
|
|
550
|
+
data: Utils.toArray(JSON.stringify(message.certificates), 'utf8'),
|
|
551
|
+
signature: message.signature,
|
|
552
|
+
protocolID: [2, 'auth message signature'],
|
|
553
|
+
keyID: `${message.nonce} ${peerSession.sessionNonce}`,
|
|
554
|
+
counterparty: message.identityKey
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
if (!valid) {
|
|
558
|
+
throw new Error(`Unable to verify certificate response signature for peer: ${message.identityKey}`)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Process and verify any certificates received
|
|
562
|
+
await validateCertificates(this.wallet, message, message.requestedCertificates)
|
|
563
|
+
|
|
564
|
+
this.onCertificatesReceivedCallbacks.forEach(callback => {
|
|
565
|
+
callback(message.identityKey, message.certificates)
|
|
566
|
+
})
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Processes a general message from a peer.
|
|
571
|
+
*
|
|
572
|
+
* @private
|
|
573
|
+
* @param {AuthMessage} message - The incoming general message.
|
|
574
|
+
* @returns {Promise<void>}
|
|
575
|
+
* @throws Will throw an error if nonce verification or signature verification fails.
|
|
576
|
+
*/
|
|
577
|
+
private async processGeneralMessage (message: AuthMessage) {
|
|
578
|
+
const validNonce = await verifyNonce(message.yourNonce, this.wallet)
|
|
579
|
+
if (!validNonce) {
|
|
580
|
+
throw new Error(`Unable to verify nonce for general message from: ${message.identityKey}`)
|
|
581
|
+
}
|
|
582
|
+
const peerSession = this.sessionManager.getSession(message.yourNonce)
|
|
583
|
+
|
|
584
|
+
const { valid } = await this.wallet.verifySignature({
|
|
585
|
+
data: message.payload,
|
|
586
|
+
signature: message.signature,
|
|
587
|
+
protocolID: [2, 'auth message signature'],
|
|
588
|
+
keyID: `${message.nonce} ${peerSession.sessionNonce}`,
|
|
589
|
+
counterparty: peerSession.peerIdentityKey
|
|
590
|
+
})
|
|
591
|
+
|
|
592
|
+
if (!valid) {
|
|
593
|
+
throw new Error(`Invalid signature in generalMessage from ${peerSession.peerIdentityKey}`)
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
this.onGeneralMessageReceivedCallbacks.forEach(callback => {
|
|
597
|
+
callback(message.identityKey, message.payload)
|
|
598
|
+
})
|
|
599
|
+
}
|
|
600
|
+
}
|