@onekeyfe/hd-transport 1.2.0-alpha.34 → 1.2.0-alpha.36
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/__tests__/messages.test.js +49 -29
- package/__tests__/protocol-v2.test.js +14 -14
- package/__tests__/transport-log.test.js +79 -0
- package/dist/index.d.ts +228 -242
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +159 -74
- package/dist/types/messages.d.ts +161 -177
- package/dist/types/messages.d.ts.map +1 -1
- package/dist/utils/transportLog.d.ts +9 -0
- package/dist/utils/transportLog.d.ts.map +1 -0
- package/messages-protocol-v2.json +408 -485
- package/package.json +2 -2
- package/scripts/protobuf-patches/index.js +1 -0
- package/src/index.ts +1 -0
- package/src/types/messages.ts +203 -225
- package/src/utils/transportLog.ts +102 -0
|
@@ -101,10 +101,10 @@ describe('messages', () => {
|
|
|
101
101
|
expect(v2Messages.nested.MessageType.values).toMatchObject({
|
|
102
102
|
MessageType_DeviceStatusGet: 60602,
|
|
103
103
|
MessageType_DeviceStatus: 60603,
|
|
104
|
-
MessageType_DeviceSessionGet:
|
|
105
|
-
MessageType_DeviceSession:
|
|
106
|
-
MessageType_DeviceSessionAskPin:
|
|
107
|
-
MessageType_DeviceSessionAskPassphrase:
|
|
104
|
+
MessageType_DeviceSessionGet: 61200,
|
|
105
|
+
MessageType_DeviceSession: 61201,
|
|
106
|
+
MessageType_DeviceSessionAskPin: 61202,
|
|
107
|
+
MessageType_DeviceSessionAskPassphrase: 61203,
|
|
108
108
|
});
|
|
109
109
|
expect(v2Messages.nested.DeviceStatusGet).toEqual({ fields: {} });
|
|
110
110
|
expect(v2Messages.nested.ProtocolInfoRequest.fields.eventless_wallet_session).toMatchObject({
|
|
@@ -112,10 +112,27 @@ describe('messages', () => {
|
|
|
112
112
|
type: 'bool',
|
|
113
113
|
options: { default: false },
|
|
114
114
|
});
|
|
115
|
+
expect(v2Messages.nested.ProtocolInfo.fields).toMatchObject({
|
|
116
|
+
version: { id: 1, type: 'uint32', rule: 'required' },
|
|
117
|
+
build_fingerprint: { id: 2, type: 'string', rule: 'required' },
|
|
118
|
+
supported_messages: { id: 3, type: 'uint32', rule: 'repeated' },
|
|
119
|
+
});
|
|
115
120
|
expect(v2Messages.nested.DeviceSessionGet.fields.session_id).toMatchObject({
|
|
116
121
|
id: 1,
|
|
117
122
|
type: 'bytes',
|
|
118
123
|
});
|
|
124
|
+
expect(v2Messages.nested.DeviceSessionGet.fields).toMatchObject({
|
|
125
|
+
btc_test_address: { id: 2, type: 'string' },
|
|
126
|
+
seed_domains: {
|
|
127
|
+
id: 3,
|
|
128
|
+
type: 'DeviceSessionSeedDomain',
|
|
129
|
+
rule: 'repeated',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
expect(v2Messages.nested.DeviceSessionSeedDomain.values).toEqual({
|
|
133
|
+
SeedDomain_Standard: 1,
|
|
134
|
+
SeedDomain_Cardano: 2,
|
|
135
|
+
});
|
|
119
136
|
expect(v2Messages.nested.DeviceSessionPinType.values).toEqual({
|
|
120
137
|
Any: 1,
|
|
121
138
|
Main: 2,
|
|
@@ -147,6 +164,7 @@ describe('messages', () => {
|
|
|
147
164
|
id: 1,
|
|
148
165
|
},
|
|
149
166
|
on_device: {
|
|
167
|
+
rule: 'required',
|
|
150
168
|
type: 'bool',
|
|
151
169
|
id: 2,
|
|
152
170
|
},
|
|
@@ -163,52 +181,54 @@ describe('messages', () => {
|
|
|
163
181
|
);
|
|
164
182
|
});
|
|
165
183
|
|
|
166
|
-
test('Protocol V2 passphrase selection
|
|
184
|
+
test('Protocol V2 passphrase selection explicitly selects host or device input on wire', () => {
|
|
167
185
|
const messages = parseConfigure(v2Messages);
|
|
168
186
|
const { Message } = createMessageFromName(messages, 'DeviceSessionAskPassphrase');
|
|
169
187
|
|
|
170
|
-
const onDevice = Message.encode(Message.create({ on_device: true })).finish();
|
|
171
188
|
const onHost = Message.encode(
|
|
172
|
-
Message.create({
|
|
173
|
-
passphrase: 'host hidden wallet',
|
|
174
|
-
on_device: false,
|
|
175
|
-
})
|
|
189
|
+
Message.create({ passphrase: 'host hidden wallet', on_device: false })
|
|
176
190
|
).finish();
|
|
191
|
+
const onDevice = Message.encode(Message.create({ on_device: true })).finish();
|
|
177
192
|
|
|
178
|
-
expect(Buffer.from(onDevice).toString('hex')).toBe('1001');
|
|
179
193
|
expect(Buffer.from(onHost).toString('hex')).toBe(
|
|
180
194
|
'0a12686f73742068696464656e2077616c6c65741000'
|
|
181
195
|
);
|
|
196
|
+
expect(Buffer.from(onDevice).toString('hex')).toBe('1001');
|
|
182
197
|
expect(Message.decode(onHost)).toMatchObject({
|
|
183
198
|
passphrase: 'host hidden wallet',
|
|
184
199
|
on_device: false,
|
|
185
200
|
});
|
|
201
|
+
expect(Message.decode(onDevice)).toMatchObject({ on_device: true });
|
|
186
202
|
});
|
|
187
203
|
|
|
188
204
|
test('Protocol V2 onboarding status matches the current firmware-pro2 schema', () => {
|
|
189
|
-
expect(v2Messages.nested.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
205
|
+
expect(v2Messages.nested.MessageType.values).toMatchObject({
|
|
206
|
+
MessageType_OnboardingStatusGet: 61600,
|
|
207
|
+
MessageType_OnboardingStatus: 61601,
|
|
208
|
+
});
|
|
209
|
+
expect(v2Messages.nested.OnboardingStep.values).toMatchObject({
|
|
210
|
+
ONBOARDING_STEP_UNKNOWN: 0,
|
|
211
|
+
ONBOARDING_STEP_CHECKING: 1,
|
|
212
|
+
ONBOARDING_STEP_PERSONALIZATION: 2,
|
|
213
|
+
ONBOARDING_STEP_PIN: 3,
|
|
214
|
+
ONBOARDING_STEP_SETUP: 4,
|
|
215
|
+
ONBOARDING_STEP_DONE: 5,
|
|
196
216
|
});
|
|
197
|
-
expect(v2Messages.nested.
|
|
198
|
-
expect(v2Messages.nested.
|
|
199
|
-
expect(v2Messages.nested.
|
|
200
|
-
expect(v2Messages.nested.
|
|
201
|
-
kind: { id: 1, type: '
|
|
202
|
-
method: { id: 2, type: '
|
|
217
|
+
expect(v2Messages.nested.OnboardingPhase.values).toBeDefined();
|
|
218
|
+
expect(v2Messages.nested.OnboardingSetupKind.values).toBeDefined();
|
|
219
|
+
expect(v2Messages.nested.OnboardingSetupMethod.values).toBeDefined();
|
|
220
|
+
expect(v2Messages.nested.OnboardingSetupStatus.fields).toMatchObject({
|
|
221
|
+
kind: { id: 1, type: 'OnboardingSetupKind' },
|
|
222
|
+
method: { id: 2, type: 'OnboardingSetupMethod' },
|
|
203
223
|
});
|
|
204
|
-
expect(v2Messages.nested.
|
|
205
|
-
step: { id: 1, type: '
|
|
206
|
-
phase: { id: 2, type: '
|
|
207
|
-
setup: { id: 3, type: '
|
|
224
|
+
expect(v2Messages.nested.OnboardingStatus.fields).toMatchObject({
|
|
225
|
+
step: { id: 1, type: 'OnboardingStep' },
|
|
226
|
+
phase: { id: 2, type: 'OnboardingPhase' },
|
|
227
|
+
setup: { id: 3, type: 'OnboardingSetupStatus' },
|
|
208
228
|
pin_set: { id: 4, type: 'bool' },
|
|
209
229
|
wallet_initialized: { id: 5, type: 'bool' },
|
|
210
230
|
});
|
|
211
|
-
expect(v2Messages.nested).not.toHaveProperty('
|
|
231
|
+
expect(v2Messages.nested).not.toHaveProperty('DevOnboardingStatus');
|
|
212
232
|
});
|
|
213
233
|
|
|
214
234
|
test('Protocol V2 does not restore retired unlock or passphrase ids', () => {
|
|
@@ -73,14 +73,14 @@ const protocolV2Messages = parseConfigure({
|
|
|
73
73
|
type: 'uint32',
|
|
74
74
|
id: 1,
|
|
75
75
|
},
|
|
76
|
-
|
|
77
|
-
type: '
|
|
76
|
+
build_fingerprint: {
|
|
77
|
+
type: 'string',
|
|
78
78
|
id: 2,
|
|
79
|
-
rule: 'repeated',
|
|
80
79
|
},
|
|
81
|
-
|
|
82
|
-
type: '
|
|
80
|
+
supported_messages: {
|
|
81
|
+
type: 'uint32',
|
|
83
82
|
id: 3,
|
|
83
|
+
rule: 'repeated',
|
|
84
84
|
},
|
|
85
85
|
},
|
|
86
86
|
},
|
|
@@ -211,7 +211,7 @@ const protocolV2Messages = parseConfigure({
|
|
|
211
211
|
MessageType_FileWrite: 60805,
|
|
212
212
|
MessageType_DeviceFirmwareUpdateRequest: 61000,
|
|
213
213
|
MessageType_DeviceFirmwareUpdateStatus: 61002,
|
|
214
|
-
MessageType_DeviceSession:
|
|
214
|
+
MessageType_DeviceSession: 61201,
|
|
215
215
|
MessageType_PartialNested: 62000,
|
|
216
216
|
},
|
|
217
217
|
},
|
|
@@ -235,8 +235,8 @@ describe('Protocol V2 framing and session', () => {
|
|
|
235
235
|
test('encodes and decodes Protocol V2 protobuf frames', () => {
|
|
236
236
|
const frame = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
237
237
|
version: 1,
|
|
238
|
+
build_fingerprint: 'application__1.0.0__abc__DEV__DEBUG',
|
|
238
239
|
supported_messages: [60200, 60201],
|
|
239
|
-
protobuf_definition: 'proto',
|
|
240
240
|
});
|
|
241
241
|
|
|
242
242
|
const parsed = protocolV2.decodeFrame(frame);
|
|
@@ -251,8 +251,8 @@ describe('Protocol V2 framing and session', () => {
|
|
|
251
251
|
seq: parsed.seq,
|
|
252
252
|
message: {
|
|
253
253
|
version: 1,
|
|
254
|
+
build_fingerprint: 'application__1.0.0__abc__DEV__DEBUG',
|
|
254
255
|
supported_messages: [60200, 60201],
|
|
255
|
-
protobuf_definition: 'proto',
|
|
256
256
|
},
|
|
257
257
|
});
|
|
258
258
|
});
|
|
@@ -297,10 +297,10 @@ describe('Protocol V2 framing and session', () => {
|
|
|
297
297
|
const malformedPayload = new Uint8Array(32);
|
|
298
298
|
malformedPayload[0] = 0x0a;
|
|
299
299
|
malformedPayload[1] = 101;
|
|
300
|
-
const frame = protocolV2.encodeProtobufFrame(
|
|
300
|
+
const frame = protocolV2.encodeProtobufFrame(61201, malformedPayload);
|
|
301
301
|
|
|
302
302
|
expect(() => ProtocolV2.decodeFrame(schemas, frame)).toThrow(
|
|
303
|
-
'Protocol V2 protobuf decode failed for "DeviceSession" (
|
|
303
|
+
'Protocol V2 protobuf decode failed for "DeviceSession" (61201, 32-byte payload); ' +
|
|
304
304
|
'the payload is malformed or incompatible with the active SDK schema.'
|
|
305
305
|
);
|
|
306
306
|
});
|
|
@@ -397,8 +397,8 @@ describe('Protocol V2 framing and session', () => {
|
|
|
397
397
|
type: 'ProtocolInfo',
|
|
398
398
|
message: {
|
|
399
399
|
version: 2,
|
|
400
|
+
build_fingerprint: null,
|
|
400
401
|
supported_messages: [60206],
|
|
401
|
-
protobuf_definition: null,
|
|
402
402
|
},
|
|
403
403
|
});
|
|
404
404
|
});
|
|
@@ -408,8 +408,8 @@ describe('Protocol V2 framing and session', () => {
|
|
|
408
408
|
const logger = { debug: jest.fn() };
|
|
409
409
|
const response = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
410
410
|
version: 2,
|
|
411
|
+
build_fingerprint: 'application__1.0.0__sensitive__DEV__DEBUG',
|
|
411
412
|
supported_messages: [60206],
|
|
412
|
-
protobuf_definition: 'sensitive-schema',
|
|
413
413
|
});
|
|
414
414
|
const session = new ProtocolV2Session({
|
|
415
415
|
schemas,
|
|
@@ -648,8 +648,8 @@ describe('Protocol V2 framing and session', () => {
|
|
|
648
648
|
type: 'ProtocolInfo',
|
|
649
649
|
message: {
|
|
650
650
|
version: 2,
|
|
651
|
+
build_fingerprint: null,
|
|
651
652
|
supported_messages: [],
|
|
652
|
-
protobuf_definition: null,
|
|
653
653
|
},
|
|
654
654
|
});
|
|
655
655
|
expect(logger.debug).not.toHaveBeenCalled();
|
|
@@ -770,8 +770,8 @@ describe('Protocol V2 framing and session', () => {
|
|
|
770
770
|
type: 'ProtocolInfo',
|
|
771
771
|
message: {
|
|
772
772
|
version: 2,
|
|
773
|
+
build_fingerprint: null,
|
|
773
774
|
supported_messages: [],
|
|
774
|
-
protobuf_definition: null,
|
|
775
775
|
},
|
|
776
776
|
});
|
|
777
777
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const { createTransportCallLog, getSafeTransportLogPayload } = require('../src/utils/transportLog');
|
|
2
|
+
|
|
3
|
+
describe('transport log sanitization', () => {
|
|
4
|
+
test('logs non-sensitive request fields and redacts passphrases recursively', () => {
|
|
5
|
+
expect(
|
|
6
|
+
createTransportCallLog('DeviceSessionAskPassphrase', 'V2', {
|
|
7
|
+
passphrase: 'hidden-wallet-secret',
|
|
8
|
+
on_device: false,
|
|
9
|
+
metadata: {
|
|
10
|
+
retry: 1,
|
|
11
|
+
session_id: 'wallet-session-secret',
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
).toEqual({
|
|
15
|
+
name: 'DeviceSessionAskPassphrase',
|
|
16
|
+
protocol: 'V2',
|
|
17
|
+
request: {
|
|
18
|
+
passphrase: '[REDACTED]',
|
|
19
|
+
on_device: false,
|
|
20
|
+
metadata: {
|
|
21
|
+
retry: 1,
|
|
22
|
+
session_id: '[REDACTED]',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('logs response fields while redacting device and wallet identifiers', () => {
|
|
29
|
+
expect(
|
|
30
|
+
getSafeTransportLogPayload({
|
|
31
|
+
message: 'Passphrase accepted',
|
|
32
|
+
device_id: 'device-secret',
|
|
33
|
+
nested: {
|
|
34
|
+
btc_test_address: 'wallet-address',
|
|
35
|
+
unlocked: true,
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
).toEqual({
|
|
39
|
+
message: 'Passphrase accepted',
|
|
40
|
+
device_id: '[REDACTED]',
|
|
41
|
+
nested: {
|
|
42
|
+
btc_test_address: '[REDACTED]',
|
|
43
|
+
unlocked: true,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('does not log raw signing request or response payloads', () => {
|
|
49
|
+
expect(
|
|
50
|
+
getSafeTransportLogPayload(
|
|
51
|
+
{
|
|
52
|
+
transaction: 'raw-transaction',
|
|
53
|
+
path: "m/44'/60'/0'/0/0",
|
|
54
|
+
},
|
|
55
|
+
'EthereumSignTx'
|
|
56
|
+
)
|
|
57
|
+
).toBe('[REDACTED]');
|
|
58
|
+
expect(
|
|
59
|
+
getSafeTransportLogPayload(
|
|
60
|
+
{
|
|
61
|
+
signature: 'raw-signature',
|
|
62
|
+
},
|
|
63
|
+
'EthereumSignedTx'
|
|
64
|
+
)
|
|
65
|
+
).toBe('[REDACTED]');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('replaces binary content with its byte length', () => {
|
|
69
|
+
expect(
|
|
70
|
+
getSafeTransportLogPayload({
|
|
71
|
+
file_name: 'resource.bin',
|
|
72
|
+
data: new Uint8Array(128),
|
|
73
|
+
})
|
|
74
|
+
).toEqual({
|
|
75
|
+
file_name: 'resource.bin',
|
|
76
|
+
data: '[BINARY:128]',
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|