walletpair-sdk 1.0.2 → 1.0.5
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 +13 -0
- package/dist/ble/framing.d.ts.map +1 -1
- package/dist/ble/framing.js +2 -2
- package/dist/ble/framing.js.map +1 -1
- package/dist/ble/index.d.ts +2 -2
- package/dist/ble/index.d.ts.map +1 -1
- package/dist/ble/index.js +2 -2
- package/dist/ble/index.js.map +1 -1
- package/dist/ble/web-ble-transport.d.ts +1 -1
- package/dist/ble/web-ble-transport.d.ts.map +1 -1
- package/dist/ble/web-ble-transport.js +23 -12
- package/dist/ble/web-ble-transport.js.map +1 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +29 -12
- package/dist/crypto.js.map +1 -1
- package/dist/dapp-session.d.ts.map +1 -1
- package/dist/dapp-session.js +15 -5
- package/dist/dapp-session.js.map +1 -1
- package/dist/emitter.d.ts +1 -3
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +4 -2
- package/dist/emitter.js.map +1 -1
- package/dist/evm/eip1193.d.ts +2 -2
- package/dist/evm/eip1193.d.ts.map +1 -1
- package/dist/evm/eip1193.js +32 -18
- package/dist/evm/eip1193.js.map +1 -1
- package/dist/evm/index.d.ts +2 -2
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js.map +1 -1
- package/dist/wallet-session.d.ts.map +1 -1
- package/dist/wallet-session.js +4 -3
- package/dist/wallet-session.js.map +1 -1
- package/dist/ws-transport.d.ts +3 -2
- package/dist/ws-transport.d.ts.map +1 -1
- package/dist/ws-transport.js +13 -4
- package/dist/ws-transport.js.map +1 -1
- package/package.json +20 -1
- package/src/__tests__/adversarial/crypto-attacks.test.ts +240 -233
- package/src/__tests__/adversarial/malicious-dapp.test.ts +228 -194
- package/src/__tests__/adversarial/malicious-relay.test.ts +292 -220
- package/src/__tests__/adversarial/malicious-wallet.test.ts +246 -180
- package/src/__tests__/spec-compliance/canonical-json.test.ts +105 -105
- package/src/__tests__/spec-compliance/crypto-vectors.test.ts +149 -154
- package/src/__tests__/spec-compliance/message-format.test.ts +180 -151
- package/src/__tests__/spec-compliance/sequence-numbers.test.ts +142 -149
- package/src/__tests__/spec-compliance/state-machine.test.ts +203 -180
- package/src/ble/framing.test.ts +122 -114
- package/src/ble/framing.ts +48 -51
- package/src/ble/index.ts +7 -7
- package/src/ble/web-ble-transport.test.ts +93 -84
- package/src/ble/web-ble-transport.ts +70 -57
- package/src/ble/web-bluetooth.d.ts +19 -19
- package/src/canonical-json.test.ts +301 -285
- package/src/crypto-directional.test.ts +155 -129
- package/src/crypto-hardening.test.ts +292 -283
- package/src/crypto.test.ts +364 -346
- package/src/crypto.ts +185 -175
- package/src/dapp-session.test.ts +522 -385
- package/src/dapp-session.ts +17 -11
- package/src/emitter.test.ts +122 -122
- package/src/emitter.ts +20 -18
- package/src/evm/eip1193.test.ts +283 -205
- package/src/evm/eip1193.ts +162 -138
- package/src/evm/index.ts +5 -5
- package/src/evm/wagmi.test.ts +1 -1
- package/src/integration.test.ts +329 -201
- package/src/security.test.ts +331 -238
- package/src/sequence-validation.test.ts +6 -9
- package/src/test-helpers.ts +102 -78
- package/src/types.test.ts +45 -50
- package/src/wallet-session.test.ts +611 -383
- package/src/wallet-session.ts +7 -9
- package/src/ws-transport.test.ts +141 -139
- package/src/ws-transport.ts +52 -41
|
@@ -6,22 +6,19 @@
|
|
|
6
6
|
* and cross-key decryption failures.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { describe,
|
|
9
|
+
import { describe, expect, it } from 'vitest'
|
|
10
|
+
import type { SessionCryptoContext } from './crypto.js'
|
|
10
11
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
bytesToHex,
|
|
13
|
+
computeHandshakeTranscriptHash,
|
|
13
14
|
computeSharedSecret,
|
|
15
|
+
deriveDirectionalSessionKeys,
|
|
14
16
|
deriveSessionKey,
|
|
17
|
+
generateChannelId,
|
|
18
|
+
generateX25519KeyPair,
|
|
15
19
|
sealPayload,
|
|
16
20
|
unsealPayload,
|
|
17
|
-
|
|
18
|
-
b64urlEncode,
|
|
19
|
-
} from './crypto.js';
|
|
20
|
-
import {
|
|
21
|
-
deriveDirectionalSessionKeys,
|
|
22
|
-
computeHandshakeTranscriptHash,
|
|
23
|
-
} from './crypto.js';
|
|
24
|
-
import type { SessionCryptoContext } from './crypto.js';
|
|
21
|
+
} from './crypto.js'
|
|
25
22
|
|
|
26
23
|
// ---------------------------------------------------------------------------
|
|
27
24
|
// Helpers
|
|
@@ -31,16 +28,20 @@ function makeContext(overrides?: Partial<SessionCryptoContext>): SessionCryptoCo
|
|
|
31
28
|
return {
|
|
32
29
|
dappPubKeyB64: overrides?.dappPubKeyB64 ?? 'dappPubKey123',
|
|
33
30
|
walletPubKeyB64: overrides?.walletPubKeyB64 ?? 'walletPubKey456',
|
|
34
|
-
capabilities: overrides?.capabilities ?? {
|
|
31
|
+
capabilities: overrides?.capabilities ?? {
|
|
32
|
+
methods: ['wallet_getAccounts'],
|
|
33
|
+
events: [],
|
|
34
|
+
chains: ['eip155:1'],
|
|
35
|
+
},
|
|
35
36
|
walletMeta: overrides?.walletMeta ?? { name: 'TestWallet' },
|
|
36
37
|
dappName: overrides?.dappName ?? 'TestDApp',
|
|
37
|
-
}
|
|
38
|
+
}
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
function makeRootKey(): Uint8Array {
|
|
41
|
-
const key = new Uint8Array(32)
|
|
42
|
-
crypto.getRandomValues(key)
|
|
43
|
-
return key
|
|
42
|
+
const key = new Uint8Array(32)
|
|
43
|
+
crypto.getRandomValues(key)
|
|
44
|
+
return key
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
// ---------------------------------------------------------------------------
|
|
@@ -48,113 +49,119 @@ function makeRootKey(): Uint8Array {
|
|
|
48
49
|
// ---------------------------------------------------------------------------
|
|
49
50
|
|
|
50
51
|
describe('Directional session keys', () => {
|
|
51
|
-
|
|
52
52
|
it('deriveDirectionalSessionKeys produces different keys for each direction', () => {
|
|
53
|
-
const rootKey = makeRootKey()
|
|
54
|
-
const channelId = generateChannelId()
|
|
55
|
-
const context = makeContext()
|
|
53
|
+
const rootKey = makeRootKey()
|
|
54
|
+
const channelId = generateChannelId()
|
|
55
|
+
const context = makeContext()
|
|
56
56
|
|
|
57
|
-
const keys = deriveDirectionalSessionKeys(rootKey, channelId, context)
|
|
57
|
+
const keys = deriveDirectionalSessionKeys(rootKey, channelId, context)
|
|
58
58
|
|
|
59
|
-
expect(keys.dappToWalletKey).toHaveLength(32)
|
|
60
|
-
expect(keys.walletToDappKey).toHaveLength(32)
|
|
61
|
-
expect(bytesToHex(keys.dappToWalletKey)).not.toBe(bytesToHex(keys.walletToDappKey))
|
|
62
|
-
})
|
|
59
|
+
expect(keys.dappToWalletKey).toHaveLength(32)
|
|
60
|
+
expect(keys.walletToDappKey).toHaveLength(32)
|
|
61
|
+
expect(bytesToHex(keys.dappToWalletKey)).not.toBe(bytesToHex(keys.walletToDappKey))
|
|
62
|
+
})
|
|
63
63
|
|
|
64
64
|
it('dappToWalletKey != walletToDappKey (even with identical root key and context)', () => {
|
|
65
|
-
const rootKey = new Uint8Array(32).fill(0x42)
|
|
66
|
-
const channelId = '00'.repeat(32)
|
|
67
|
-
const context = makeContext()
|
|
65
|
+
const rootKey = new Uint8Array(32).fill(0x42)
|
|
66
|
+
const channelId = '00'.repeat(32)
|
|
67
|
+
const context = makeContext()
|
|
68
68
|
|
|
69
|
-
const keys = deriveDirectionalSessionKeys(rootKey, channelId, context)
|
|
69
|
+
const keys = deriveDirectionalSessionKeys(rootKey, channelId, context)
|
|
70
70
|
|
|
71
71
|
// They must differ because different HKDF info strings are used
|
|
72
|
-
expect(bytesToHex(keys.dappToWalletKey)).not.toBe(bytesToHex(keys.walletToDappKey))
|
|
73
|
-
})
|
|
72
|
+
expect(bytesToHex(keys.dappToWalletKey)).not.toBe(bytesToHex(keys.walletToDappKey))
|
|
73
|
+
})
|
|
74
74
|
|
|
75
75
|
it('same keys derived from both sides (dApp and wallet perspectives)', () => {
|
|
76
76
|
// Simulate full key exchange: both sides derive the same shared secret,
|
|
77
77
|
// then the same directional keys.
|
|
78
|
-
const dappKp = generateX25519KeyPair()
|
|
79
|
-
const walletKp = generateX25519KeyPair()
|
|
80
|
-
const channelId = generateChannelId()
|
|
81
|
-
|
|
82
|
-
const capabilities = {
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
const dappKp = generateX25519KeyPair()
|
|
79
|
+
const walletKp = generateX25519KeyPair()
|
|
80
|
+
const channelId = generateChannelId()
|
|
81
|
+
|
|
82
|
+
const capabilities = {
|
|
83
|
+
methods: ['wallet_getAccounts'],
|
|
84
|
+
events: ['accountsChanged'],
|
|
85
|
+
chains: ['eip155:1'],
|
|
86
|
+
}
|
|
87
|
+
const walletMeta = { name: 'My Wallet' }
|
|
88
|
+
const dappName = 'My dApp'
|
|
85
89
|
|
|
86
90
|
// DApp side
|
|
87
|
-
const sharedDapp = computeSharedSecret(dappKp.privateKey, walletKp.publicKey)
|
|
88
|
-
const rootKeyDapp = deriveSessionKey(sharedDapp, channelId)
|
|
91
|
+
const sharedDapp = computeSharedSecret(dappKp.privateKey, walletKp.publicKey)
|
|
92
|
+
const rootKeyDapp = deriveSessionKey(sharedDapp, channelId)
|
|
89
93
|
const contextDapp: SessionCryptoContext = {
|
|
90
94
|
dappPubKeyB64: dappKp.publicKeyB64,
|
|
91
95
|
walletPubKeyB64: walletKp.publicKeyB64,
|
|
92
96
|
capabilities,
|
|
93
97
|
walletMeta,
|
|
94
98
|
dappName,
|
|
95
|
-
}
|
|
96
|
-
const keysDapp = deriveDirectionalSessionKeys(rootKeyDapp, channelId, contextDapp)
|
|
99
|
+
}
|
|
100
|
+
const keysDapp = deriveDirectionalSessionKeys(rootKeyDapp, channelId, contextDapp)
|
|
97
101
|
|
|
98
102
|
// Wallet side (same context fields, same shared secret via DH symmetry)
|
|
99
|
-
const sharedWallet = computeSharedSecret(walletKp.privateKey, dappKp.publicKey)
|
|
100
|
-
const rootKeyWallet = deriveSessionKey(sharedWallet, channelId)
|
|
103
|
+
const sharedWallet = computeSharedSecret(walletKp.privateKey, dappKp.publicKey)
|
|
104
|
+
const rootKeyWallet = deriveSessionKey(sharedWallet, channelId)
|
|
101
105
|
const contextWallet: SessionCryptoContext = {
|
|
102
106
|
dappPubKeyB64: dappKp.publicKeyB64,
|
|
103
107
|
walletPubKeyB64: walletKp.publicKeyB64,
|
|
104
108
|
capabilities,
|
|
105
109
|
walletMeta,
|
|
106
110
|
dappName,
|
|
107
|
-
}
|
|
108
|
-
const keysWallet = deriveDirectionalSessionKeys(rootKeyWallet, channelId, contextWallet)
|
|
111
|
+
}
|
|
112
|
+
const keysWallet = deriveDirectionalSessionKeys(rootKeyWallet, channelId, contextWallet)
|
|
109
113
|
|
|
110
114
|
// Both sides must agree on all keys
|
|
111
|
-
expect(bytesToHex(keysDapp.dappToWalletKey)).toBe(bytesToHex(keysWallet.dappToWalletKey))
|
|
112
|
-
expect(bytesToHex(keysDapp.walletToDappKey)).toBe(bytesToHex(keysWallet.walletToDappKey))
|
|
113
|
-
expect(bytesToHex(keysDapp.transcriptHash)).toBe(bytesToHex(keysWallet.transcriptHash))
|
|
114
|
-
})
|
|
115
|
+
expect(bytesToHex(keysDapp.dappToWalletKey)).toBe(bytesToHex(keysWallet.dappToWalletKey))
|
|
116
|
+
expect(bytesToHex(keysDapp.walletToDappKey)).toBe(bytesToHex(keysWallet.walletToDappKey))
|
|
117
|
+
expect(bytesToHex(keysDapp.transcriptHash)).toBe(bytesToHex(keysWallet.transcriptHash))
|
|
118
|
+
})
|
|
115
119
|
|
|
116
120
|
it('different capabilities produce different directional keys', () => {
|
|
117
|
-
const rootKey = makeRootKey()
|
|
118
|
-
const channelId = generateChannelId()
|
|
121
|
+
const rootKey = makeRootKey()
|
|
122
|
+
const channelId = generateChannelId()
|
|
119
123
|
|
|
120
|
-
const context1 = makeContext({
|
|
121
|
-
|
|
124
|
+
const context1 = makeContext({
|
|
125
|
+
capabilities: { methods: ['wallet_getAccounts'], events: [], chains: ['eip155:1'] },
|
|
126
|
+
})
|
|
127
|
+
const context2 = makeContext({
|
|
128
|
+
capabilities: { methods: ['wallet_signMessage'], events: [], chains: ['eip155:1'] },
|
|
129
|
+
})
|
|
122
130
|
|
|
123
|
-
const keys1 = deriveDirectionalSessionKeys(rootKey, channelId, context1)
|
|
124
|
-
const keys2 = deriveDirectionalSessionKeys(rootKey, channelId, context2)
|
|
131
|
+
const keys1 = deriveDirectionalSessionKeys(rootKey, channelId, context1)
|
|
132
|
+
const keys2 = deriveDirectionalSessionKeys(rootKey, channelId, context2)
|
|
125
133
|
|
|
126
|
-
expect(bytesToHex(keys1.dappToWalletKey)).not.toBe(bytesToHex(keys2.dappToWalletKey))
|
|
127
|
-
expect(bytesToHex(keys1.walletToDappKey)).not.toBe(bytesToHex(keys2.walletToDappKey))
|
|
128
|
-
})
|
|
134
|
+
expect(bytesToHex(keys1.dappToWalletKey)).not.toBe(bytesToHex(keys2.dappToWalletKey))
|
|
135
|
+
expect(bytesToHex(keys1.walletToDappKey)).not.toBe(bytesToHex(keys2.walletToDappKey))
|
|
136
|
+
})
|
|
129
137
|
|
|
130
138
|
it('different walletMeta produce different directional keys', () => {
|
|
131
|
-
const rootKey = makeRootKey()
|
|
132
|
-
const channelId = generateChannelId()
|
|
139
|
+
const rootKey = makeRootKey()
|
|
140
|
+
const channelId = generateChannelId()
|
|
133
141
|
|
|
134
|
-
const context1 = makeContext({ walletMeta: { name: 'Wallet A' } })
|
|
135
|
-
const context2 = makeContext({ walletMeta: { name: 'Wallet B' } })
|
|
142
|
+
const context1 = makeContext({ walletMeta: { name: 'Wallet A' } })
|
|
143
|
+
const context2 = makeContext({ walletMeta: { name: 'Wallet B' } })
|
|
136
144
|
|
|
137
|
-
const keys1 = deriveDirectionalSessionKeys(rootKey, channelId, context1)
|
|
138
|
-
const keys2 = deriveDirectionalSessionKeys(rootKey, channelId, context2)
|
|
145
|
+
const keys1 = deriveDirectionalSessionKeys(rootKey, channelId, context1)
|
|
146
|
+
const keys2 = deriveDirectionalSessionKeys(rootKey, channelId, context2)
|
|
139
147
|
|
|
140
|
-
expect(bytesToHex(keys1.dappToWalletKey)).not.toBe(bytesToHex(keys2.dappToWalletKey))
|
|
141
|
-
})
|
|
142
|
-
})
|
|
148
|
+
expect(bytesToHex(keys1.dappToWalletKey)).not.toBe(bytesToHex(keys2.dappToWalletKey))
|
|
149
|
+
})
|
|
150
|
+
})
|
|
143
151
|
|
|
144
152
|
describe('computeHandshakeTranscriptHash', () => {
|
|
145
|
-
|
|
146
153
|
it('is deterministic for the same inputs', () => {
|
|
147
|
-
const channelId = generateChannelId()
|
|
148
|
-
const context = makeContext()
|
|
154
|
+
const channelId = generateChannelId()
|
|
155
|
+
const context = makeContext()
|
|
149
156
|
|
|
150
|
-
const hash1 = computeHandshakeTranscriptHash(channelId, context)
|
|
151
|
-
const hash2 = computeHandshakeTranscriptHash(channelId, context)
|
|
157
|
+
const hash1 = computeHandshakeTranscriptHash(channelId, context)
|
|
158
|
+
const hash2 = computeHandshakeTranscriptHash(channelId, context)
|
|
152
159
|
|
|
153
|
-
expect(bytesToHex(hash1)).toBe(bytesToHex(hash2))
|
|
154
|
-
})
|
|
160
|
+
expect(bytesToHex(hash1)).toBe(bytesToHex(hash2))
|
|
161
|
+
})
|
|
155
162
|
|
|
156
163
|
it('canonicalJson ordering is consistent regardless of object key insertion order', () => {
|
|
157
|
-
const channelId = generateChannelId()
|
|
164
|
+
const channelId = generateChannelId()
|
|
158
165
|
|
|
159
166
|
// Two contexts with same data but different key insertion order
|
|
160
167
|
const context1: SessionCryptoContext = {
|
|
@@ -163,7 +170,7 @@ describe('computeHandshakeTranscriptHash', () => {
|
|
|
163
170
|
capabilities: { methods: ['a'], events: ['b'], chains: ['c'] },
|
|
164
171
|
walletMeta: { name: 'W', address: '0x1' },
|
|
165
172
|
dappName: 'D',
|
|
166
|
-
}
|
|
173
|
+
}
|
|
167
174
|
|
|
168
175
|
const context2: SessionCryptoContext = {
|
|
169
176
|
walletPubKeyB64: 'def',
|
|
@@ -171,93 +178,112 @@ describe('computeHandshakeTranscriptHash', () => {
|
|
|
171
178
|
dappPubKeyB64: 'abc',
|
|
172
179
|
walletMeta: { address: '0x1', name: 'W' },
|
|
173
180
|
capabilities: { chains: ['c'], events: ['b'], methods: ['a'] },
|
|
174
|
-
}
|
|
181
|
+
}
|
|
175
182
|
|
|
176
|
-
const hash1 = computeHandshakeTranscriptHash(channelId, context1)
|
|
177
|
-
const hash2 = computeHandshakeTranscriptHash(channelId, context2)
|
|
183
|
+
const hash1 = computeHandshakeTranscriptHash(channelId, context1)
|
|
184
|
+
const hash2 = computeHandshakeTranscriptHash(channelId, context2)
|
|
178
185
|
|
|
179
|
-
expect(bytesToHex(hash1)).toBe(bytesToHex(hash2))
|
|
180
|
-
})
|
|
186
|
+
expect(bytesToHex(hash1)).toBe(bytesToHex(hash2))
|
|
187
|
+
})
|
|
181
188
|
|
|
182
189
|
it('changing any context field changes the transcript hash', () => {
|
|
183
|
-
const channelId = generateChannelId()
|
|
184
|
-
const baseContext = makeContext()
|
|
185
|
-
const baseHash = bytesToHex(computeHandshakeTranscriptHash(channelId, baseContext))
|
|
190
|
+
const channelId = generateChannelId()
|
|
191
|
+
const baseContext = makeContext()
|
|
192
|
+
const baseHash = bytesToHex(computeHandshakeTranscriptHash(channelId, baseContext))
|
|
186
193
|
|
|
187
194
|
// Change dappPubKeyB64
|
|
188
|
-
const h1 = bytesToHex(
|
|
189
|
-
|
|
195
|
+
const h1 = bytesToHex(
|
|
196
|
+
computeHandshakeTranscriptHash(channelId, makeContext({ dappPubKeyB64: 'differentDappKey' })),
|
|
197
|
+
)
|
|
198
|
+
expect(h1).not.toBe(baseHash)
|
|
190
199
|
|
|
191
200
|
// Change walletPubKeyB64
|
|
192
|
-
const h2 = bytesToHex(
|
|
193
|
-
|
|
201
|
+
const h2 = bytesToHex(
|
|
202
|
+
computeHandshakeTranscriptHash(
|
|
203
|
+
channelId,
|
|
204
|
+
makeContext({ walletPubKeyB64: 'differentWalletKey' }),
|
|
205
|
+
),
|
|
206
|
+
)
|
|
207
|
+
expect(h2).not.toBe(baseHash)
|
|
194
208
|
|
|
195
209
|
// Change capabilities
|
|
196
|
-
const h3 = bytesToHex(
|
|
197
|
-
|
|
210
|
+
const h3 = bytesToHex(
|
|
211
|
+
computeHandshakeTranscriptHash(
|
|
212
|
+
channelId,
|
|
213
|
+
makeContext({ capabilities: { methods: ['other_method'], events: [], chains: [] } }),
|
|
214
|
+
),
|
|
215
|
+
)
|
|
216
|
+
expect(h3).not.toBe(baseHash)
|
|
198
217
|
|
|
199
218
|
// Change walletMeta
|
|
200
|
-
const h4 = bytesToHex(
|
|
201
|
-
|
|
219
|
+
const h4 = bytesToHex(
|
|
220
|
+
computeHandshakeTranscriptHash(
|
|
221
|
+
channelId,
|
|
222
|
+
makeContext({ walletMeta: { name: 'DifferentWallet' } }),
|
|
223
|
+
),
|
|
224
|
+
)
|
|
225
|
+
expect(h4).not.toBe(baseHash)
|
|
202
226
|
|
|
203
227
|
// Change dappName
|
|
204
|
-
const h5 = bytesToHex(
|
|
205
|
-
|
|
228
|
+
const h5 = bytesToHex(
|
|
229
|
+
computeHandshakeTranscriptHash(channelId, makeContext({ dappName: 'DifferentDApp' })),
|
|
230
|
+
)
|
|
231
|
+
expect(h5).not.toBe(baseHash)
|
|
206
232
|
|
|
207
233
|
// Change channelId
|
|
208
|
-
const h6 = bytesToHex(computeHandshakeTranscriptHash(generateChannelId(), baseContext))
|
|
209
|
-
expect(h6).not.toBe(baseHash)
|
|
234
|
+
const h6 = bytesToHex(computeHandshakeTranscriptHash(generateChannelId(), baseContext))
|
|
235
|
+
expect(h6).not.toBe(baseHash)
|
|
210
236
|
|
|
211
237
|
// All hashes must be unique
|
|
212
|
-
const allHashes = [baseHash, h1, h2, h3, h4, h5, h6]
|
|
213
|
-
expect(new Set(allHashes).size).toBe(allHashes.length)
|
|
214
|
-
})
|
|
215
|
-
})
|
|
238
|
+
const allHashes = [baseHash, h1, h2, h3, h4, h5, h6]
|
|
239
|
+
expect(new Set(allHashes).size).toBe(allHashes.length)
|
|
240
|
+
})
|
|
241
|
+
})
|
|
216
242
|
|
|
217
243
|
describe('Cross-key decryption', () => {
|
|
218
|
-
const channelId = generateChannelId()
|
|
219
|
-
const rootKey = makeRootKey()
|
|
220
|
-
const context = makeContext()
|
|
221
|
-
const keys = deriveDirectionalSessionKeys(rootKey, channelId, context)
|
|
244
|
+
const channelId = generateChannelId()
|
|
245
|
+
const rootKey = makeRootKey()
|
|
246
|
+
const context = makeContext()
|
|
247
|
+
const keys = deriveDirectionalSessionKeys(rootKey, channelId, context)
|
|
222
248
|
|
|
223
249
|
it('sealPayload with dappToWalletKey can be unsealed with dappToWalletKey', () => {
|
|
224
|
-
const data = { action: 'test' }
|
|
225
|
-
const sealed = sealPayload(keys.dappToWalletKey, channelId, 0, data)
|
|
226
|
-
const { data: decrypted } = unsealPayload(keys.dappToWalletKey, channelId, sealed)
|
|
227
|
-
expect(decrypted).toEqual(data)
|
|
228
|
-
})
|
|
250
|
+
const data = { action: 'test' }
|
|
251
|
+
const sealed = sealPayload(keys.dappToWalletKey, channelId, 0, data)
|
|
252
|
+
const { data: decrypted } = unsealPayload(keys.dappToWalletKey, channelId, sealed)
|
|
253
|
+
expect(decrypted).toEqual(data)
|
|
254
|
+
})
|
|
229
255
|
|
|
230
256
|
it('sealPayload with dappToWalletKey cannot be unsealed with walletToDappKey', () => {
|
|
231
|
-
const data = { secret: 'from-dapp' }
|
|
232
|
-
const sealed = sealPayload(keys.dappToWalletKey, channelId, 0, data)
|
|
257
|
+
const data = { secret: 'from-dapp' }
|
|
258
|
+
const sealed = sealPayload(keys.dappToWalletKey, channelId, 0, data)
|
|
233
259
|
|
|
234
260
|
// Attempting to decrypt with the wrong directional key must fail
|
|
235
|
-
expect(() => unsealPayload(keys.walletToDappKey, channelId, sealed)).toThrow()
|
|
236
|
-
})
|
|
261
|
+
expect(() => unsealPayload(keys.walletToDappKey, channelId, sealed)).toThrow()
|
|
262
|
+
})
|
|
237
263
|
|
|
238
264
|
it('cross-key decryption fails: wallet key cannot decrypt dapp-encrypted message', () => {
|
|
239
|
-
const data = { request: 'wallet_getAccounts', params: {} }
|
|
240
|
-
const hdr = { type: 'req' as const, from: 'dapp', id: 'req-1', method: 'wallet_getAccounts' }
|
|
265
|
+
const data = { request: 'wallet_getAccounts', params: {} }
|
|
266
|
+
const hdr = { type: 'req' as const, from: 'dapp', id: 'req-1', method: 'wallet_getAccounts' }
|
|
241
267
|
|
|
242
|
-
const sealed = sealPayload(keys.dappToWalletKey, channelId, 0, data, hdr)
|
|
268
|
+
const sealed = sealPayload(keys.dappToWalletKey, channelId, 0, data, hdr)
|
|
243
269
|
|
|
244
270
|
// walletToDappKey must not be able to open it
|
|
245
|
-
expect(() => unsealPayload(keys.walletToDappKey, channelId, sealed, hdr)).toThrow()
|
|
271
|
+
expect(() => unsealPayload(keys.walletToDappKey, channelId, sealed, hdr)).toThrow()
|
|
246
272
|
|
|
247
273
|
// But dappToWalletKey can
|
|
248
|
-
const { data: decrypted } = unsealPayload(keys.dappToWalletKey, channelId, sealed, hdr)
|
|
249
|
-
expect(decrypted).toEqual(data)
|
|
250
|
-
})
|
|
274
|
+
const { data: decrypted } = unsealPayload(keys.dappToWalletKey, channelId, sealed, hdr)
|
|
275
|
+
expect(decrypted).toEqual(data)
|
|
276
|
+
})
|
|
251
277
|
|
|
252
278
|
it('walletToDappKey sealed message cannot be opened with dappToWalletKey', () => {
|
|
253
|
-
const data = { result: ['0xabc'] }
|
|
254
|
-
const hdr = { type: 'res' as const, from: 'wallet', id: 'req-1' }
|
|
279
|
+
const data = { result: ['0xabc'] }
|
|
280
|
+
const hdr = { type: 'res' as const, from: 'wallet', id: 'req-1' }
|
|
255
281
|
|
|
256
|
-
const sealed = sealPayload(keys.walletToDappKey, channelId, 0, data, hdr)
|
|
282
|
+
const sealed = sealPayload(keys.walletToDappKey, channelId, 0, data, hdr)
|
|
257
283
|
|
|
258
|
-
expect(() => unsealPayload(keys.dappToWalletKey, channelId, sealed, hdr)).toThrow()
|
|
284
|
+
expect(() => unsealPayload(keys.dappToWalletKey, channelId, sealed, hdr)).toThrow()
|
|
259
285
|
|
|
260
|
-
const { data: decrypted } = unsealPayload(keys.walletToDappKey, channelId, sealed, hdr)
|
|
261
|
-
expect(decrypted).toEqual(data)
|
|
262
|
-
})
|
|
263
|
-
})
|
|
286
|
+
const { data: decrypted } = unsealPayload(keys.walletToDappKey, channelId, sealed, hdr)
|
|
287
|
+
expect(decrypted).toEqual(data)
|
|
288
|
+
})
|
|
289
|
+
})
|