@yume-chan/adb 0.0.12 → 0.0.15
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/CHANGELOG.json +54 -0
- package/CHANGELOG.md +28 -1
- package/README.md +24 -17
- package/esm/adb.d.ts +10 -9
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +88 -67
- package/esm/adb.js.map +1 -1
- package/esm/auth.d.ts +6 -6
- package/esm/auth.d.ts.map +1 -1
- package/esm/auth.js +8 -6
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +2 -2
- package/esm/commands/install.d.ts.map +1 -1
- package/esm/commands/install.js +5 -7
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/reverse.d.ts +9 -12
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +44 -36
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/index.d.ts +19 -20
- package/esm/commands/subprocess/index.d.ts.map +1 -1
- package/esm/commands/subprocess/index.js +36 -31
- package/esm/commands/subprocess/index.js.map +1 -1
- package/esm/commands/subprocess/legacy.d.ts +14 -7
- package/esm/commands/subprocess/legacy.d.ts.map +1 -1
- package/esm/commands/subprocess/legacy.js +14 -5
- package/esm/commands/subprocess/legacy.js.map +1 -1
- package/esm/commands/subprocess/protocol.d.ts +3 -2
- package/esm/commands/subprocess/protocol.d.ts.map +1 -1
- package/esm/commands/subprocess/protocol.js +6 -4
- package/esm/commands/subprocess/protocol.js.map +1 -1
- package/esm/commands/subprocess/protocols/index.d.ts +4 -0
- package/esm/commands/subprocess/protocols/index.d.ts.map +1 -0
- package/esm/commands/subprocess/protocols/index.js +4 -0
- package/esm/commands/subprocess/protocols/index.js.map +1 -0
- package/esm/commands/subprocess/protocols/none.d.ts +35 -0
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -0
- package/esm/commands/subprocess/protocols/none.js +53 -0
- package/esm/commands/subprocess/protocols/none.js.map +1 -0
- package/esm/commands/subprocess/protocols/shell.d.ts +39 -0
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -0
- package/esm/commands/subprocess/protocols/shell.js +155 -0
- package/esm/commands/subprocess/protocols/shell.js.map +1 -0
- package/esm/commands/subprocess/protocols/types.d.ts +50 -0
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -0
- package/esm/commands/subprocess/protocols/types.js +2 -0
- package/esm/commands/subprocess/protocols/types.js.map +1 -0
- package/esm/commands/subprocess/types.d.ts +9 -6
- package/esm/commands/subprocess/types.d.ts.map +1 -1
- package/esm/commands/sync/list.d.ts +25 -1
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +40 -5
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +6 -3
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/request.d.ts +1 -0
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +1 -0
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +2 -1
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +2 -1
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/stat.d.ts +13 -1
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +22 -9
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +13 -35
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +40 -10
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/crypto.d.ts +23 -10
- package/esm/crypto.d.ts.map +1 -1
- package/esm/crypto.js +64 -46
- package/esm/crypto.js.map +1 -1
- package/esm/features.d.ts +4 -2
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +6 -2
- package/esm/features.js.map +1 -1
- package/esm/packet.d.ts +21 -2
- package/esm/packet.d.ts.map +1 -1
- package/esm/packet.js +2 -2
- package/esm/packet.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +35 -23
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +97 -72
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/socket.d.ts +29 -8
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +43 -29
- package/esm/socket/socket.js.map +1 -1
- package/esm/stream/buffered.d.ts +1 -1
- package/esm/stream/buffered.d.ts.map +1 -1
- package/esm/stream/buffered.js +2 -2
- package/esm/stream/buffered.js.map +1 -1
- package/esm/stream/detect.d.ts +1 -17
- package/esm/stream/detect.d.ts.map +1 -1
- package/esm/stream/detect.js +4 -5
- package/esm/stream/detect.js.map +1 -1
- package/esm/stream/detect.polyfill.d.ts +1 -1
- package/esm/stream/detect.polyfill.d.ts.map +1 -1
- package/esm/stream/detect.polyfill.js +4 -1
- package/esm/stream/detect.polyfill.js.map +1 -1
- package/esm/stream/transform.d.ts +39 -33
- package/esm/stream/transform.d.ts.map +1 -1
- package/esm/stream/transform.js +121 -100
- package/esm/stream/transform.js.map +1 -1
- package/esm/utils/base64.js +5 -5
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/encoding.d.ts.map +1 -1
- package/esm/utils/encoding.js.map +1 -1
- package/esm/utils/index.d.ts +1 -1
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.js +1 -1
- package/esm/utils/index.js.map +1 -1
- package/package.json +7 -7
- package/src/adb.ts +112 -86
- package/src/auth.ts +21 -18
- package/src/backend.ts +2 -2
- package/src/commands/install.ts +7 -9
- package/src/commands/reverse.ts +48 -44
- package/src/commands/subprocess/index.ts +57 -42
- package/src/commands/subprocess/protocols/index.ts +3 -0
- package/src/commands/subprocess/{legacy.ts → protocols/none.ts} +20 -10
- package/src/commands/subprocess/{protocol.ts → protocols/shell.ts} +22 -17
- package/src/commands/subprocess/{types.ts → protocols/types.ts} +13 -9
- package/src/commands/sync/list.ts +51 -5
- package/src/commands/sync/pull.ts +6 -3
- package/src/commands/sync/request.ts +1 -0
- package/src/commands/sync/response.ts +8 -2
- package/src/commands/sync/stat.ts +36 -9
- package/src/commands/sync/sync.ts +56 -20
- package/src/crypto.ts +72 -56
- package/src/features.ts +6 -2
- package/src/packet.ts +17 -6
- package/src/socket/dispatcher.ts +139 -91
- package/src/socket/socket.ts +76 -61
- package/src/stream/buffered.ts +2 -2
- package/src/stream/detect.polyfill.ts +5 -2
- package/src/stream/detect.ts +4 -24
- package/src/stream/transform.ts +144 -124
- package/src/utils/index.ts +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/src/utils/encoding.ts +0 -13
|
@@ -4,11 +4,28 @@ import { AdbFeatures } from '../../features.js';
|
|
|
4
4
|
import type { AdbSocket } from '../../socket/index.js';
|
|
5
5
|
import { AdbBufferedStream, ReadableStream, WrapReadableStream, WrapWritableStream, WritableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
6
6
|
import { AutoResetEvent } from '../../utils/index.js';
|
|
7
|
-
import {
|
|
7
|
+
import { escapeArg } from "../index.js";
|
|
8
|
+
import { adbSyncOpenDir, type AdbSyncEntry } from './list.js';
|
|
8
9
|
import { adbSyncPull } from './pull.js';
|
|
9
10
|
import { adbSyncPush } from './push.js';
|
|
10
11
|
import { adbSyncLstat, adbSyncStat } from './stat.js';
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* A simplified `dirname` function that only handles absolute unix paths.
|
|
15
|
+
* @param path an absolute unix path
|
|
16
|
+
* @returns the directory name of the input path
|
|
17
|
+
*/
|
|
18
|
+
export function dirname(path: string): string {
|
|
19
|
+
const end = path.lastIndexOf('/');
|
|
20
|
+
if (end === -1) {
|
|
21
|
+
throw new Error(`Invalid path`);
|
|
22
|
+
}
|
|
23
|
+
if (end === 0) {
|
|
24
|
+
return '/';
|
|
25
|
+
}
|
|
26
|
+
return path.substring(0, end);
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
export class AdbSync extends AutoDisposable {
|
|
13
30
|
protected adb: Adb;
|
|
14
31
|
|
|
@@ -22,6 +39,19 @@ export class AdbSync extends AutoDisposable {
|
|
|
22
39
|
return this.adb.features!.includes(AdbFeatures.StatV2);
|
|
23
40
|
}
|
|
24
41
|
|
|
42
|
+
public get supportsList2(): boolean {
|
|
43
|
+
return this.adb.features!.includes(AdbFeatures.ListV2);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public get fixedPushMkdir(): boolean {
|
|
47
|
+
return this.adb.features!.includes(AdbFeatures.FixedPushMkdir);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public get needPushMkdirWorkaround(): boolean {
|
|
51
|
+
// https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
|
|
52
|
+
return this.adb.features!.includes(AdbFeatures.ShellV2) && !this.fixedPushMkdir;
|
|
53
|
+
}
|
|
54
|
+
|
|
25
55
|
public constructor(adb: Adb, socket: AdbSocket) {
|
|
26
56
|
super();
|
|
27
57
|
|
|
@@ -65,18 +95,18 @@ export class AdbSync extends AutoDisposable {
|
|
|
65
95
|
|
|
66
96
|
public async *opendir(
|
|
67
97
|
path: string
|
|
68
|
-
): AsyncGenerator<
|
|
98
|
+
): AsyncGenerator<AdbSyncEntry, void, void> {
|
|
69
99
|
await this.sendLock.wait();
|
|
70
100
|
|
|
71
101
|
try {
|
|
72
|
-
yield* adbSyncOpenDir(this.stream, this.writer, path);
|
|
102
|
+
yield* adbSyncOpenDir(this.stream, this.writer, path, this.supportsList2);
|
|
73
103
|
} finally {
|
|
74
104
|
this.sendLock.notify();
|
|
75
105
|
}
|
|
76
106
|
}
|
|
77
107
|
|
|
78
108
|
public async readdir(path: string) {
|
|
79
|
-
const results:
|
|
109
|
+
const results: AdbSyncEntry[] = [];
|
|
80
110
|
for await (const entry of this.opendir(path)) {
|
|
81
111
|
results.push(entry);
|
|
82
112
|
}
|
|
@@ -90,13 +120,10 @@ export class AdbSync extends AutoDisposable {
|
|
|
90
120
|
* @returns A `ReadableStream` that reads from the file.
|
|
91
121
|
*/
|
|
92
122
|
public read(filename: string): ReadableStream<Uint8Array> {
|
|
93
|
-
return new WrapReadableStream
|
|
123
|
+
return new WrapReadableStream({
|
|
94
124
|
start: async () => {
|
|
95
125
|
await this.sendLock.wait();
|
|
96
|
-
return
|
|
97
|
-
readable: adbSyncPull(this.stream, this.writer, filename),
|
|
98
|
-
state: undefined,
|
|
99
|
-
};
|
|
126
|
+
return adbSyncPull(this.stream, this.writer, filename);
|
|
100
127
|
},
|
|
101
128
|
close: async () => {
|
|
102
129
|
this.sendLock.notify();
|
|
@@ -120,16 +147,25 @@ export class AdbSync extends AutoDisposable {
|
|
|
120
147
|
return new WrapWritableStream({
|
|
121
148
|
start: async () => {
|
|
122
149
|
await this.sendLock.wait();
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
150
|
+
|
|
151
|
+
if (this.needPushMkdirWorkaround) {
|
|
152
|
+
// It may fail if the path is already existed.
|
|
153
|
+
// Ignore the result.
|
|
154
|
+
// TODO: sync: test this
|
|
155
|
+
await this.adb.subprocess.spawnAndWait([
|
|
156
|
+
'mkdir',
|
|
157
|
+
'-p',
|
|
158
|
+
escapeArg(dirname(filename)),
|
|
159
|
+
]);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return adbSyncPush(
|
|
163
|
+
this.stream,
|
|
164
|
+
this.writer,
|
|
165
|
+
filename,
|
|
166
|
+
mode,
|
|
167
|
+
mtime,
|
|
168
|
+
);
|
|
133
169
|
},
|
|
134
170
|
close: async () => {
|
|
135
171
|
this.sendLock.notify();
|
|
@@ -139,7 +175,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
139
175
|
|
|
140
176
|
public override async dispose() {
|
|
141
177
|
super.dispose();
|
|
142
|
-
this.stream.close();
|
|
178
|
+
await this.stream.close();
|
|
143
179
|
await this.writer.close();
|
|
144
180
|
}
|
|
145
181
|
}
|
package/src/crypto.ts
CHANGED
|
@@ -5,48 +5,60 @@ const BigInt1 = BigInt(1);
|
|
|
5
5
|
const BigInt2 = BigInt(2);
|
|
6
6
|
const BigInt64 = BigInt(64);
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Gets the `BigInt` value at the specified byte offset and length from the start of the view. There is
|
|
10
|
+
* no alignment constraint; multi-byte values may be fetched from any offset.
|
|
11
|
+
*
|
|
12
|
+
* Only supports Big-Endian, because that's what ADB uses.
|
|
13
|
+
* @param byteOffset The place in the buffer at which the value should be retrieved.
|
|
14
|
+
*/
|
|
15
|
+
export function getBigUint(dataView: DataView, byteOffset: number, length: number): bigint {
|
|
15
16
|
let result = BigInt0;
|
|
16
17
|
|
|
17
18
|
// Currently `length` must be a multiplication of 8
|
|
18
19
|
// Support for arbitrary length can be easily added
|
|
19
20
|
|
|
20
|
-
for (let i =
|
|
21
|
+
for (let i = byteOffset; i < byteOffset + length; i += 8) {
|
|
21
22
|
result <<= BigInt64;
|
|
22
|
-
const value = getBigUint64(
|
|
23
|
+
const value = getBigUint64(dataView, i, false);
|
|
23
24
|
result += value;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
return result;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Stores an arbitrary-precision positive `BigInt` value at the specified byte offset from the start of the view.
|
|
32
|
+
* @param byteOffset The place in the buffer at which the value should be set.
|
|
33
|
+
* @param value The value to set.
|
|
34
|
+
* @param littleEndian If `false` or `undefined`, a big-endian value should be written,
|
|
35
|
+
* otherwise a little-endian value should be written.
|
|
36
|
+
*/
|
|
37
|
+
export function setBigUint(dataView: DataView, byteOffset: number, value: bigint, littleEndian?: boolean) {
|
|
38
|
+
const start = byteOffset;
|
|
39
|
+
|
|
40
|
+
if (littleEndian) {
|
|
41
|
+
while (value > BigInt0) {
|
|
42
|
+
setBigUint64(dataView, byteOffset, value, true);
|
|
43
|
+
byteOffset += 8;
|
|
44
|
+
value >>= BigInt64;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
// Because we don't know how long (in bits) the `value` is,
|
|
48
|
+
// Convert it to an array of `uint64` first.
|
|
49
|
+
const uint64Array: bigint[] = [];
|
|
50
|
+
while (value > BigInt0) {
|
|
51
|
+
uint64Array.push(BigInt.asUintN(64, value));
|
|
52
|
+
value >>= BigInt64;
|
|
53
|
+
}
|
|
35
54
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
55
|
+
for (let i = uint64Array.length - 1; i >= 0; i -= 1) {
|
|
56
|
+
setBigUint64(dataView, byteOffset, uint64Array[i]!, false);
|
|
57
|
+
byteOffset += 8;
|
|
58
|
+
}
|
|
40
59
|
}
|
|
41
|
-
}
|
|
42
60
|
|
|
43
|
-
|
|
44
|
-
const view = new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
45
|
-
while (value > BigInt0) {
|
|
46
|
-
setBigUint64(view, offset, value, true);
|
|
47
|
-
offset += 8;
|
|
48
|
-
value >>= BigInt64;
|
|
49
|
-
}
|
|
61
|
+
return byteOffset - start;
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
// These values are correct only if
|
|
@@ -76,9 +88,9 @@ const RsaPrivateKeyDOffset = 303;
|
|
|
76
88
|
const RsaPrivateKeyDLength = 2048 / 8;
|
|
77
89
|
|
|
78
90
|
export function parsePrivateKey(key: Uint8Array): [n: bigint, d: bigint] {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
const view = new DataView(key.buffer, key.byteOffset, key.byteLength);
|
|
92
|
+
const n = getBigUint(view, RsaPrivateKeyNOffset, RsaPrivateKeyNLength);
|
|
93
|
+
const d = getBigUint(view, RsaPrivateKeyDOffset, RsaPrivateKeyDLength);
|
|
82
94
|
return [n, d];
|
|
83
95
|
}
|
|
84
96
|
|
|
@@ -132,7 +144,7 @@ export function calculatePublicKey(
|
|
|
132
144
|
// [
|
|
133
145
|
// modulusLengthInWords, // 32-bit integer, a "word" is 32-bit so it must be 2048 / 8 / 4
|
|
134
146
|
// // Actually the comment in Android source code was wrong
|
|
135
|
-
// n0inv, // 32-bit integer, the modular inverse of (
|
|
147
|
+
// n0inv, // 32-bit integer, the modular inverse of (low 32 bits of n)
|
|
136
148
|
// modulus, // n
|
|
137
149
|
// rr, // Montgomery parameter R^2
|
|
138
150
|
// exponent, // 32-bit integer, must be 65537
|
|
@@ -172,13 +184,12 @@ export function calculatePublicKey(
|
|
|
172
184
|
outputOffset += 4;
|
|
173
185
|
|
|
174
186
|
// Write n
|
|
175
|
-
|
|
187
|
+
setBigUint(outputView, outputOffset, n, true);
|
|
176
188
|
outputOffset += 256;
|
|
177
189
|
|
|
178
190
|
// Calculate rr = (2^(rsa_size)) ^ 2 mod n
|
|
179
191
|
let rr = BigInt(2) ** BigInt(4096) % n;
|
|
180
|
-
|
|
181
|
-
outputOffset += 256;
|
|
192
|
+
outputOffset += setBigUint(outputView, outputOffset, rr, true);
|
|
182
193
|
|
|
183
194
|
// exponent
|
|
184
195
|
outputView.setUint32(outputOffset, 65537, true);
|
|
@@ -218,21 +229,21 @@ export function powMod(base: bigint, exponent: bigint, modulus: bigint): bigint
|
|
|
218
229
|
return r;
|
|
219
230
|
}
|
|
220
231
|
|
|
221
|
-
export const
|
|
232
|
+
export const SHA1_DIGEST_LENGTH = 20;
|
|
222
233
|
|
|
223
|
-
export const
|
|
224
|
-
export const
|
|
225
|
-
export const
|
|
226
|
-
export const
|
|
234
|
+
export const ASN1_SEQUENCE = 0x30;
|
|
235
|
+
export const ASN1_OCTET_STRING = 0x04;
|
|
236
|
+
export const ASN1_NULL = 0x05;
|
|
237
|
+
export const ASN1_OID = 0x06;
|
|
227
238
|
|
|
228
239
|
// PKCS#1 SHA-1 hash digest info
|
|
229
|
-
export const
|
|
230
|
-
|
|
231
|
-
|
|
240
|
+
export const SHA1_DIGEST_INFO = new Uint8Array([
|
|
241
|
+
ASN1_SEQUENCE, 0x0d + SHA1_DIGEST_LENGTH,
|
|
242
|
+
ASN1_SEQUENCE, 0x09,
|
|
232
243
|
// SHA-1 (1 3 14 3 2 26)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
244
|
+
ASN1_OID, 0x05, 1 * 40 + 3, 14, 3, 2, 26,
|
|
245
|
+
ASN1_NULL, 0x00,
|
|
246
|
+
ASN1_OCTET_STRING, SHA1_DIGEST_LENGTH
|
|
236
247
|
]);
|
|
237
248
|
|
|
238
249
|
// SubtleCrypto.sign() will hash the given data and sign the hash
|
|
@@ -241,7 +252,7 @@ export const Sha1DigestInfo = new Uint8Array([
|
|
|
241
252
|
// encrypt the given data with its private key)
|
|
242
253
|
// However SubtileCrypto.encrypt() doesn't accept 'RSASSA-PKCS1-v1_5' algorithm
|
|
243
254
|
// So we need to implement the encryption by ourself
|
|
244
|
-
export function sign(privateKey: Uint8Array, data: Uint8Array):
|
|
255
|
+
export function sign(privateKey: Uint8Array, data: Uint8Array): Uint8Array {
|
|
245
256
|
const [n, d] = parsePrivateKey(privateKey);
|
|
246
257
|
|
|
247
258
|
// PKCS#1 padding
|
|
@@ -254,7 +265,7 @@ export function sign(privateKey: Uint8Array, data: Uint8Array): ArrayBuffer {
|
|
|
254
265
|
padded[index] = 1;
|
|
255
266
|
index += 1;
|
|
256
267
|
|
|
257
|
-
const fillLength = padded.length -
|
|
268
|
+
const fillLength = padded.length - SHA1_DIGEST_INFO.length - data.length - 1;
|
|
258
269
|
while (index < fillLength) {
|
|
259
270
|
padded[index] = 0xff;
|
|
260
271
|
index += 1;
|
|
@@ -263,18 +274,23 @@ export function sign(privateKey: Uint8Array, data: Uint8Array): ArrayBuffer {
|
|
|
263
274
|
padded[index] = 0;
|
|
264
275
|
index += 1;
|
|
265
276
|
|
|
266
|
-
padded.set(
|
|
267
|
-
index +=
|
|
277
|
+
padded.set(SHA1_DIGEST_INFO, index);
|
|
278
|
+
index += SHA1_DIGEST_INFO.length;
|
|
268
279
|
|
|
269
280
|
padded.set(data, index);
|
|
270
281
|
|
|
271
282
|
// Encryption
|
|
272
283
|
// signature = padded ** d % n
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
284
|
+
const view = new DataView(padded.buffer);
|
|
285
|
+
const signature = powMod(
|
|
286
|
+
getBigUint(view, 0, view.byteLength),
|
|
287
|
+
d,
|
|
288
|
+
n
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
// `padded` is not used anymore,
|
|
292
|
+
// re-use the buffer to store the result
|
|
293
|
+
setBigUint(view, 0, signature, false);
|
|
294
|
+
|
|
295
|
+
return padded;
|
|
280
296
|
}
|
package/src/features.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// The order follows
|
|
2
|
+
// https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
|
|
1
3
|
export enum AdbFeatures {
|
|
2
|
-
|
|
4
|
+
ShellV2 = "shell_v2",
|
|
3
5
|
Cmd = 'cmd',
|
|
4
|
-
|
|
6
|
+
StatV2 = 'stat_v2',
|
|
7
|
+
ListV2 = 'ls_v2',
|
|
8
|
+
FixedPushMkdir = 'fixed_push_mkdir',
|
|
5
9
|
}
|
package/src/packet.ts
CHANGED
|
@@ -10,7 +10,7 @@ export enum AdbCommand {
|
|
|
10
10
|
Write = 0x45545257, // 'WRTE'
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const AdbPacketHeader =
|
|
13
|
+
export const AdbPacketHeader =
|
|
14
14
|
new Struct({ littleEndian: true })
|
|
15
15
|
.uint32('command')
|
|
16
16
|
.uint32('arg0')
|
|
@@ -19,6 +19,8 @@ const AdbPacketHeader =
|
|
|
19
19
|
.uint32('checksum')
|
|
20
20
|
.int32('magic');
|
|
21
21
|
|
|
22
|
+
export type AdbPacketHeader = typeof AdbPacketHeader['TDeserializeResult'];
|
|
23
|
+
|
|
22
24
|
type AdbPacketHeaderInit = typeof AdbPacketHeader['TInit'];
|
|
23
25
|
|
|
24
26
|
export const AdbPacket =
|
|
@@ -28,15 +30,24 @@ export const AdbPacket =
|
|
|
28
30
|
|
|
29
31
|
export type AdbPacket = typeof AdbPacket['TDeserializeResult'];
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
/**
|
|
34
|
+
* `AdbPacketData` contains all the useful fields of `AdbPacket`.
|
|
35
|
+
*
|
|
36
|
+
* `AdbBackend#connect` will return a `ReadableStream<AdbPacketData>`,
|
|
37
|
+
* so each backend can encode `AdbPacket` in different ways.
|
|
38
|
+
*
|
|
39
|
+
* `AdbBackend#connect` will return a `WritableStream<AdbPacketInit>`,
|
|
40
|
+
* however, `AdbPacketDispatcher` will transform `AdbPacketData` to `AdbPacketInit` for you,
|
|
41
|
+
* so `AdbSocket#writable#write` only needs `AdbPacketData`.
|
|
42
|
+
*/
|
|
43
|
+
export type AdbPacketData = Omit<typeof AdbPacket['TInit'], 'checksum' | 'magic'>;
|
|
33
44
|
|
|
34
45
|
// All fields except `magic`, which can be calculated in `AdbPacketSerializeStream`
|
|
35
46
|
export type AdbPacketInit = Omit<typeof AdbPacket['TInit'], 'magic'>;
|
|
36
47
|
|
|
37
48
|
export function calculateChecksum(payload: Uint8Array): number;
|
|
38
|
-
export function calculateChecksum(init:
|
|
39
|
-
export function calculateChecksum(payload: Uint8Array |
|
|
49
|
+
export function calculateChecksum(init: AdbPacketData): AdbPacketInit;
|
|
50
|
+
export function calculateChecksum(payload: Uint8Array | AdbPacketData): number | AdbPacketInit {
|
|
40
51
|
if (payload instanceof Uint8Array) {
|
|
41
52
|
return payload.reduce((result, item) => result + item, 0);
|
|
42
53
|
} else {
|
|
@@ -49,7 +60,7 @@ export class AdbPacketSerializeStream extends TransformStream<AdbPacketInit, Uin
|
|
|
49
60
|
public constructor() {
|
|
50
61
|
super({
|
|
51
62
|
transform: async (init, controller) => {
|
|
52
|
-
// This syntax is ugly, but I don't want to create
|
|
63
|
+
// This syntax is ugly, but I don't want to create a new object.
|
|
53
64
|
(init as unknown as AdbPacketHeaderInit).magic = init.command ^ 0xFFFFFFFF;
|
|
54
65
|
(init as unknown as AdbPacketHeaderInit).payloadLength = init.payload.byteLength;
|
|
55
66
|
|