@yume-chan/adb 0.0.20 → 0.0.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.
Files changed (132) hide show
  1. package/CHANGELOG.json +45 -0
  2. package/CHANGELOG.md +22 -1
  3. package/README.md +46 -364
  4. package/esm/adb.d.ts +9 -5
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +21 -11
  7. package/esm/adb.js.map +1 -1
  8. package/esm/banner.d.ts.map +1 -1
  9. package/esm/banner.js +1 -1
  10. package/esm/banner.js.map +1 -1
  11. package/esm/commands/base.d.ts.map +1 -1
  12. package/esm/commands/base.js.map +1 -1
  13. package/esm/commands/framebuffer.d.ts +9 -0
  14. package/esm/commands/framebuffer.d.ts.map +1 -1
  15. package/esm/commands/framebuffer.js +27 -3
  16. package/esm/commands/framebuffer.js.map +1 -1
  17. package/esm/commands/power.d.ts.map +1 -1
  18. package/esm/commands/power.js.map +1 -1
  19. package/esm/commands/reverse.d.ts.map +1 -1
  20. package/esm/commands/reverse.js.map +1 -1
  21. package/esm/commands/subprocess/command.d.ts +1 -1
  22. package/esm/commands/subprocess/command.d.ts.map +1 -1
  23. package/esm/commands/subprocess/command.js +15 -13
  24. package/esm/commands/subprocess/command.js.map +1 -1
  25. package/esm/commands/subprocess/protocols/none.d.ts +2 -1
  26. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  27. package/esm/commands/subprocess/protocols/none.js +11 -14
  28. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  29. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  30. package/esm/commands/subprocess/protocols/shell.js +21 -17
  31. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  32. package/esm/commands/subprocess/utils.js.map +1 -1
  33. package/esm/commands/sync/list.d.ts +2 -1
  34. package/esm/commands/sync/list.d.ts.map +1 -1
  35. package/esm/commands/sync/list.js +2 -2
  36. package/esm/commands/sync/list.js.map +1 -1
  37. package/esm/commands/sync/pull.d.ts.map +1 -1
  38. package/esm/commands/sync/pull.js +4 -0
  39. package/esm/commands/sync/pull.js.map +1 -1
  40. package/esm/commands/sync/push.js +1 -1
  41. package/esm/commands/sync/push.js.map +1 -1
  42. package/esm/commands/sync/request.js +1 -1
  43. package/esm/commands/sync/request.js.map +1 -1
  44. package/esm/commands/sync/response.d.ts +3 -1
  45. package/esm/commands/sync/response.d.ts.map +1 -1
  46. package/esm/commands/sync/response.js +5 -3
  47. package/esm/commands/sync/response.js.map +1 -1
  48. package/esm/commands/sync/socket.d.ts +1 -1
  49. package/esm/commands/sync/socket.d.ts.map +1 -1
  50. package/esm/commands/sync/socket.js +7 -3
  51. package/esm/commands/sync/socket.js.map +1 -1
  52. package/esm/commands/sync/stat.js +2 -2
  53. package/esm/commands/sync/stat.js.map +1 -1
  54. package/esm/commands/sync/sync.d.ts +15 -0
  55. package/esm/commands/sync/sync.d.ts.map +1 -1
  56. package/esm/commands/sync/sync.js +17 -2
  57. package/esm/commands/sync/sync.js.map +1 -1
  58. package/esm/commands/tcpip.d.ts +21 -0
  59. package/esm/commands/tcpip.d.ts.map +1 -1
  60. package/esm/commands/tcpip.js +18 -0
  61. package/esm/commands/tcpip.js.map +1 -1
  62. package/esm/daemon/auth.d.ts +11 -9
  63. package/esm/daemon/auth.d.ts.map +1 -1
  64. package/esm/daemon/auth.js +21 -12
  65. package/esm/daemon/auth.js.map +1 -1
  66. package/esm/daemon/crypto.js +2 -2
  67. package/esm/daemon/crypto.js.map +1 -1
  68. package/esm/daemon/dispatcher.d.ts +6 -5
  69. package/esm/daemon/dispatcher.d.ts.map +1 -1
  70. package/esm/daemon/dispatcher.js +69 -58
  71. package/esm/daemon/dispatcher.js.map +1 -1
  72. package/esm/daemon/packet.d.ts +5 -5
  73. package/esm/daemon/packet.d.ts.map +1 -1
  74. package/esm/daemon/packet.js +2 -2
  75. package/esm/daemon/packet.js.map +1 -1
  76. package/esm/daemon/socket.d.ts +7 -14
  77. package/esm/daemon/socket.d.ts.map +1 -1
  78. package/esm/daemon/socket.js +58 -46
  79. package/esm/daemon/socket.js.map +1 -1
  80. package/esm/daemon/transport.d.ts +16 -4
  81. package/esm/daemon/transport.d.ts.map +1 -1
  82. package/esm/daemon/transport.js +11 -7
  83. package/esm/daemon/transport.js.map +1 -1
  84. package/esm/features.js +1 -1
  85. package/esm/features.js.map +1 -1
  86. package/esm/server/client.d.ts +12 -8
  87. package/esm/server/client.d.ts.map +1 -1
  88. package/esm/server/client.js +41 -22
  89. package/esm/server/client.js.map +1 -1
  90. package/esm/server/transport.d.ts.map +1 -1
  91. package/esm/server/transport.js.map +1 -1
  92. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  93. package/esm/utils/auto-reset-event.js.map +1 -1
  94. package/esm/utils/base64.js.map +1 -1
  95. package/esm/utils/conditional-variable.d.ts.map +1 -1
  96. package/esm/utils/conditional-variable.js.map +1 -1
  97. package/esm/utils/hex.js.map +1 -1
  98. package/package.json +13 -14
  99. package/src/adb.ts +49 -35
  100. package/src/banner.ts +7 -7
  101. package/src/commands/base.ts +1 -1
  102. package/src/commands/framebuffer.ts +31 -3
  103. package/src/commands/power.ts +9 -9
  104. package/src/commands/reverse.ts +13 -13
  105. package/src/commands/subprocess/command.ts +24 -25
  106. package/src/commands/subprocess/protocols/none.ts +23 -27
  107. package/src/commands/subprocess/protocols/shell.ts +42 -37
  108. package/src/commands/sync/list.ts +11 -7
  109. package/src/commands/sync/pull.ts +7 -4
  110. package/src/commands/sync/push.ts +6 -6
  111. package/src/commands/sync/request.ts +3 -3
  112. package/src/commands/sync/response.ts +8 -6
  113. package/src/commands/sync/socket.ts +19 -14
  114. package/src/commands/sync/stat.ts +5 -5
  115. package/src/commands/sync/sync.ts +32 -17
  116. package/src/commands/tcpip.ts +46 -2
  117. package/src/daemon/auth.ts +49 -30
  118. package/src/daemon/crypto.ts +9 -9
  119. package/src/daemon/dispatcher.ts +104 -88
  120. package/src/daemon/packet.ts +2 -2
  121. package/src/daemon/socket.ts +106 -115
  122. package/src/daemon/transport.ts +49 -29
  123. package/src/server/client.ts +88 -77
  124. package/src/server/transport.ts +13 -13
  125. package/src/utils/auto-reset-event.ts +4 -4
  126. package/src/utils/base64.ts +5 -5
  127. package/src/utils/conditional-variable.ts +4 -4
  128. package/tsconfig.build.tsbuildinfo +1 -1
  129. package/esm/daemon/connection.d.ts +0 -11
  130. package/esm/daemon/connection.d.ts.map +0 -1
  131. package/esm/daemon/connection.js +0 -2
  132. package/esm/daemon/connection.js.map +0 -1
@@ -48,27 +48,27 @@ export class AdbSync extends AutoDisposable {
48
48
  readonly #supportsSendReceiveV2: boolean;
49
49
  readonly #needPushMkdirWorkaround: boolean;
50
50
 
51
- public get supportsStat(): boolean {
51
+ get supportsStat(): boolean {
52
52
  return this.#supportsStat;
53
53
  }
54
54
 
55
- public get supportsListV2(): boolean {
55
+ get supportsListV2(): boolean {
56
56
  return this.#supportsListV2;
57
57
  }
58
58
 
59
- public get fixedPushMkdir(): boolean {
59
+ get fixedPushMkdir(): boolean {
60
60
  return this.#fixedPushMkdir;
61
61
  }
62
62
 
63
- public get supportsSendReceiveV2(): boolean {
63
+ get supportsSendReceiveV2(): boolean {
64
64
  return this.#supportsSendReceiveV2;
65
65
  }
66
66
 
67
- public get needPushMkdirWorkaround(): boolean {
67
+ get needPushMkdirWorkaround(): boolean {
68
68
  return this.#needPushMkdirWorkaround;
69
69
  }
70
70
 
71
- public constructor(adb: Adb, socket: AdbSocket) {
71
+ constructor(adb: Adb, socket: AdbSocket) {
72
72
  super();
73
73
 
74
74
  this._adb = adb;
@@ -78,7 +78,7 @@ export class AdbSync extends AutoDisposable {
78
78
  this.#supportsListV2 = adb.supportsFeature(AdbFeature.ListV2);
79
79
  this.#fixedPushMkdir = adb.supportsFeature(AdbFeature.FixedPushMkdir);
80
80
  this.#supportsSendReceiveV2 = adb.supportsFeature(
81
- AdbFeature.SendReceiveV2
81
+ AdbFeature.SendReceiveV2,
82
82
  );
83
83
  // https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
84
84
  this.#needPushMkdirWorkaround =
@@ -86,19 +86,34 @@ export class AdbSync extends AutoDisposable {
86
86
  !this.fixedPushMkdir;
87
87
  }
88
88
 
89
- public async lstat(path: string): Promise<AdbSyncStat> {
90
- return await adbSyncLstat(this._socket, path, this.supportsStat);
89
+ /**
90
+ * Gets information of a file or folder.
91
+ *
92
+ * If `path` points to a symbolic link, the returned information is about the link itself (with `type` being `LinuxFileType.Link`).
93
+ */
94
+ async lstat(path: string): Promise<AdbSyncStat> {
95
+ return await adbSyncLstat(this._socket, path, this.#supportsStat);
91
96
  }
92
97
 
93
- public async stat(path: string) {
94
- if (!this.supportsStat) {
98
+ /**
99
+ * Gets the information of a file or folder.
100
+ *
101
+ * If `path` points to a symbolic link, it will be resolved and the returned information is about the target (with `type` being `LinuxFileType.File` or `LinuxFileType.Directory`).
102
+ */
103
+ async stat(path: string) {
104
+ if (!this.#supportsStat) {
95
105
  throw new Error("Not supported");
96
106
  }
97
107
 
98
108
  return await adbSyncStat(this._socket, path);
99
109
  }
100
110
 
101
- public async isDirectory(path: string): Promise<boolean> {
111
+ /**
112
+ * Checks if `path` is a directory, or a symbolic link to a directory.
113
+ *
114
+ * This uses `lstat` internally, thus works on all Android versions.
115
+ */
116
+ async isDirectory(path: string): Promise<boolean> {
102
117
  try {
103
118
  await this.lstat(path + "/");
104
119
  return true;
@@ -107,11 +122,11 @@ export class AdbSync extends AutoDisposable {
107
122
  }
108
123
  }
109
124
 
110
- public opendir(path: string): AsyncGenerator<AdbSyncEntry, void, void> {
125
+ opendir(path: string): AsyncGenerator<AdbSyncEntry, void, void> {
111
126
  return adbSyncOpenDir(this._socket, path, this.supportsListV2);
112
127
  }
113
128
 
114
- public async readdir(path: string) {
129
+ async readdir(path: string) {
115
130
  const results: AdbSyncEntry[] = [];
116
131
  for await (const entry of this.opendir(path)) {
117
132
  results.push(entry);
@@ -125,7 +140,7 @@ export class AdbSync extends AutoDisposable {
125
140
  * @param filename The full path of the file on device to read.
126
141
  * @returns A `ReadableStream` that contains the file content.
127
142
  */
128
- public read(filename: string): ReadableStream<Uint8Array> {
143
+ read(filename: string): ReadableStream<Uint8Array> {
129
144
  return adbSyncPull(this._socket, filename);
130
145
  }
131
146
 
@@ -134,7 +149,7 @@ export class AdbSync extends AutoDisposable {
134
149
  *
135
150
  * @param options The content and options of the file to write.
136
151
  */
137
- public async write(options: AdbSyncWriteOptions): Promise<void> {
152
+ async write(options: AdbSyncWriteOptions): Promise<void> {
138
153
  if (this.needPushMkdirWorkaround) {
139
154
  // It may fail if the path is already existed.
140
155
  // Ignore the result.
@@ -153,7 +168,7 @@ export class AdbSync extends AutoDisposable {
153
168
  });
154
169
  }
155
170
 
156
- public override async dispose() {
171
+ override async dispose() {
157
172
  super.dispose();
158
173
  await this._socket.close();
159
174
  }
@@ -1,7 +1,51 @@
1
1
  import { AdbCommandBase } from "./base.js";
2
2
 
3
+ /**
4
+ * ADB daemon checks for the following properties in the order of
5
+ *
6
+ * * `serviceListenAddresses` (`service.adb.listen_addrs`)
7
+ * * `servicePort` (`service.adb.tcp.port`)
8
+ * * `persistPort` (`persist.adb.tcp.port`)
9
+ *
10
+ * Once it finds a non-empty value, it will use it and ignore the rest.
11
+ *
12
+ * `serviceListenAddresses` and `persistPort` are fixed at build time,
13
+ * only `servicePort` can be changed using `setPort` and `disable`.
14
+ * This means if either `serviceListenAddresses` or `persistPort` is non-empty,
15
+ * ADB over WiFi is always enabled.
16
+ */
17
+ export interface AdbTcpIpListenAddresses {
18
+ serviceListenAddresses: string[];
19
+ servicePort: number | undefined;
20
+ persistPort: number | undefined;
21
+ }
22
+
3
23
  export class AdbTcpIpCommand extends AdbCommandBase {
4
- public async setPort(port: number): Promise<string> {
24
+ #parsePort(value: string): number | undefined {
25
+ if (!value || value === "0") {
26
+ return undefined;
27
+ }
28
+ return Number.parseInt(value, 10);
29
+ }
30
+
31
+ async getListenAddresses(): Promise<AdbTcpIpListenAddresses> {
32
+ const serviceListenAddresses = await this.adb.getProp(
33
+ "service.adb.listen_addrs",
34
+ );
35
+ const servicePort = await this.adb.getProp("service.adb.tcp.port");
36
+ const persistPort = await this.adb.getProp("persist.adb.tcp.port");
37
+
38
+ return {
39
+ serviceListenAddresses:
40
+ serviceListenAddresses != ""
41
+ ? serviceListenAddresses.split(",")
42
+ : [],
43
+ servicePort: this.#parsePort(servicePort),
44
+ persistPort: this.#parsePort(persistPort),
45
+ };
46
+ }
47
+
48
+ async setPort(port: number): Promise<string> {
5
49
  if (port <= 0) {
6
50
  throw new Error(`Invalid port ${port}`);
7
51
  }
@@ -13,7 +57,7 @@ export class AdbTcpIpCommand extends AdbCommandBase {
13
57
  return output;
14
58
  }
15
59
 
16
- public async disable(): Promise<string> {
60
+ async disable(): Promise<string> {
17
61
  const output = await this.adb.createSocketAndWait("usb:");
18
62
  if (output !== "restarting in USB mode\n") {
19
63
  throw new Error(output);
@@ -1,8 +1,13 @@
1
1
  import { PromiseResolver } from "@yume-chan/async";
2
2
  import type { Disposable } from "@yume-chan/event";
3
3
  import type { ValueOrPromise } from "@yume-chan/struct";
4
+ import { EMPTY_UINT8_ARRAY } from "@yume-chan/struct";
4
5
 
5
- import { calculateBase64EncodedLength, encodeBase64 } from "../utils/index.js";
6
+ import {
7
+ calculateBase64EncodedLength,
8
+ encodeBase64,
9
+ encodeUtf8,
10
+ } from "../utils/index.js";
6
11
 
7
12
  import {
8
13
  adbGeneratePublicKey,
@@ -12,18 +17,26 @@ import {
12
17
  import type { AdbPacketData } from "./packet.js";
13
18
  import { AdbCommand } from "./packet.js";
14
19
 
15
- export type AdbKeyIterable = Iterable<Uint8Array> | AsyncIterable<Uint8Array>;
20
+ export interface AdbPrivateKey {
21
+ /**
22
+ * The private key in PKCS #8 format.
23
+ */
24
+ buffer: Uint8Array;
25
+ name?: string | undefined;
26
+ }
27
+
28
+ export type AdbKeyIterable =
29
+ | Iterable<AdbPrivateKey>
30
+ | AsyncIterable<AdbPrivateKey>;
16
31
 
17
32
  export interface AdbCredentialStore {
18
33
  /**
19
- * Generate and store a RSA private key with modulus length `2048` and public exponent `65537`.
20
- *
21
- * The returned `Uint8Array` is the private key in PKCS #8 format.
34
+ * Generates and stores a RSA private key with modulus length `2048` and public exponent `65537`.
22
35
  */
23
- generateKey(): ValueOrPromise<Uint8Array>;
36
+ generateKey(): ValueOrPromise<AdbPrivateKey>;
24
37
 
25
38
  /**
26
- * Synchronously or asynchronously iterate through all stored RSA private keys.
39
+ * Synchronously or asynchronously iterates through all stored RSA private keys.
27
40
  *
28
41
  * Each call to `iterateKeys` must return a different iterator that iterate through all stored keys.
29
42
  */
@@ -50,13 +63,13 @@ export interface AdbAuthenticator {
50
63
  */
51
64
  (
52
65
  credentialStore: AdbCredentialStore,
53
- getNextRequest: () => Promise<AdbPacketData>
66
+ getNextRequest: () => Promise<AdbPacketData>,
54
67
  ): AsyncIterable<AdbPacketData>;
55
68
  }
56
69
 
57
70
  export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
58
71
  credentialStore: AdbCredentialStore,
59
- getNextRequest: () => Promise<AdbPacketData>
72
+ getNextRequest: () => Promise<AdbPacketData>,
60
73
  ): AsyncIterable<AdbPacketData> {
61
74
  for await (const key of credentialStore.iterateKeys()) {
62
75
  const packet = await getNextRequest();
@@ -65,7 +78,7 @@ export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
65
78
  return;
66
79
  }
67
80
 
68
- const signature = rsaSign(key, packet.payload);
81
+ const signature = rsaSign(key.buffer, packet.payload);
69
82
  yield {
70
83
  command: AdbCommand.Auth,
71
84
  arg0: AdbAuthType.Signature,
@@ -77,7 +90,7 @@ export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
77
90
 
78
91
  export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
79
92
  credentialStore: AdbCredentialStore,
80
- getNextRequest: () => Promise<AdbPacketData>
93
+ getNextRequest: () => Promise<AdbPacketData>,
81
94
  ): AsyncIterable<AdbPacketData> {
82
95
  const packet = await getNextRequest();
83
96
 
@@ -85,7 +98,7 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
85
98
  return;
86
99
  }
87
100
 
88
- let privateKey: Uint8Array | undefined;
101
+ let privateKey: AdbPrivateKey | undefined;
89
102
  for await (const key of credentialStore.iterateKeys()) {
90
103
  privateKey = key;
91
104
  break;
@@ -99,13 +112,23 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
99
112
  const [publicKeyBase64Length] =
100
113
  calculateBase64EncodedLength(publicKeyLength);
101
114
 
115
+ const nameBuffer = privateKey.name?.length
116
+ ? encodeUtf8(privateKey.name)
117
+ : EMPTY_UINT8_ARRAY;
102
118
  const publicKeyBuffer = new Uint8Array(
103
- publicKeyBase64Length + 1 // Null character
119
+ publicKeyBase64Length +
120
+ (nameBuffer.length ? nameBuffer.length + 1 : 0) + // Space character + name
121
+ 1, // Null character
104
122
  );
105
123
 
106
- adbGeneratePublicKey(privateKey, publicKeyBuffer);
124
+ adbGeneratePublicKey(privateKey.buffer, publicKeyBuffer);
107
125
  encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer);
108
126
 
127
+ if (nameBuffer.length) {
128
+ publicKeyBuffer[publicKeyBase64Length] = 0x20;
129
+ publicKeyBuffer.set(nameBuffer, publicKeyBase64Length + 1);
130
+ }
131
+
109
132
  yield {
110
133
  command: AdbCommand.Auth,
111
134
  arg0: AdbAuthType.PublicKey,
@@ -120,34 +143,30 @@ export const ADB_DEFAULT_AUTHENTICATORS: AdbAuthenticator[] = [
120
143
  ];
121
144
 
122
145
  export class AdbAuthenticationProcessor implements Disposable {
123
- public readonly authenticators: readonly AdbAuthenticator[];
146
+ readonly authenticators: readonly AdbAuthenticator[];
124
147
 
125
- private readonly credentialStore: AdbCredentialStore;
148
+ readonly #credentialStore: AdbCredentialStore;
126
149
 
127
150
  #pendingRequest = new PromiseResolver<AdbPacketData>();
128
151
  #iterator: AsyncIterator<AdbPacketData, void, void> | undefined;
129
152
 
130
- public constructor(
153
+ constructor(
131
154
  authenticators: readonly AdbAuthenticator[],
132
- credentialStore: AdbCredentialStore
155
+ credentialStore: AdbCredentialStore,
133
156
  ) {
134
157
  this.authenticators = authenticators;
135
- this.credentialStore = credentialStore;
158
+ this.#credentialStore = credentialStore;
136
159
  }
137
160
 
138
- private getNextRequest = (): Promise<AdbPacketData> => {
161
+ #getNextRequest = (): Promise<AdbPacketData> => {
139
162
  return this.#pendingRequest.promise;
140
163
  };
141
164
 
142
- private async *invokeAuthenticator(): AsyncGenerator<
143
- AdbPacketData,
144
- void,
145
- void
146
- > {
165
+ async *#invokeAuthenticator(): AsyncGenerator<AdbPacketData, void, void> {
147
166
  for (const authenticator of this.authenticators) {
148
167
  for await (const packet of authenticator(
149
- this.credentialStore,
150
- this.getNextRequest
168
+ this.#credentialStore,
169
+ this.#getNextRequest,
151
170
  )) {
152
171
  // If the authenticator yielded a response
153
172
  // Prepare `nextRequest` for next authentication request
@@ -162,9 +181,9 @@ export class AdbAuthenticationProcessor implements Disposable {
162
181
  }
163
182
  }
164
183
 
165
- public async process(packet: AdbPacketData): Promise<AdbPacketData> {
184
+ async process(packet: AdbPacketData): Promise<AdbPacketData> {
166
185
  if (!this.#iterator) {
167
- this.#iterator = this.invokeAuthenticator();
186
+ this.#iterator = this.#invokeAuthenticator();
168
187
  }
169
188
 
170
189
  this.#pendingRequest.resolve(packet);
@@ -177,7 +196,7 @@ export class AdbAuthenticationProcessor implements Disposable {
177
196
  return result.value;
178
197
  }
179
198
 
180
- public dispose() {
199
+ dispose() {
181
200
  void this.#iterator?.return?.();
182
201
  }
183
202
  }
@@ -13,7 +13,7 @@ import {
13
13
  export function getBigUint(
14
14
  dataView: DataView,
15
15
  byteOffset: number,
16
- length: number
16
+ length: number,
17
17
  ): bigint {
18
18
  let result = 0n;
19
19
 
@@ -40,7 +40,7 @@ export function setBigUint(
40
40
  dataView: DataView,
41
41
  byteOffset: number,
42
42
  value: bigint,
43
- littleEndian?: boolean
43
+ littleEndian?: boolean,
44
44
  ) {
45
45
  const start = byteOffset;
46
46
 
@@ -135,11 +135,11 @@ export function adbGetPublicKeySize() {
135
135
  export function adbGeneratePublicKey(privateKey: Uint8Array): Uint8Array;
136
136
  export function adbGeneratePublicKey(
137
137
  privateKey: Uint8Array,
138
- output: Uint8Array
138
+ output: Uint8Array,
139
139
  ): number;
140
140
  export function adbGeneratePublicKey(
141
141
  privateKey: Uint8Array,
142
- output?: Uint8Array
142
+ output?: Uint8Array,
143
143
  ): Uint8Array | number {
144
144
  // Android has its own public key generation algorithm
145
145
  // See https://android.googlesource.com/platform/system/core.git/+/91784040db2b9273687f88d8b95f729d4a61ecc2/libcrypto_utils/android_pubkey.cpp#111
@@ -158,9 +158,6 @@ export function adbGeneratePublicKey(
158
158
  // (All in little endian)
159
159
  // See https://android.googlesource.com/platform/system/core.git/+/91784040db2b9273687f88d8b95f729d4a61ecc2/libcrypto_utils/android_pubkey.cpp#38
160
160
 
161
- // extract `n` from private key
162
- const [n] = rsaParsePrivateKey(privateKey);
163
-
164
161
  let outputType: "Uint8Array" | "number";
165
162
  const outputLength = adbGetPublicKeySize();
166
163
  if (!output) {
@@ -177,7 +174,7 @@ export function adbGeneratePublicKey(
177
174
  const outputView = new DataView(
178
175
  output.buffer,
179
176
  output.byteOffset,
180
- output.byteLength
177
+ output.byteLength,
181
178
  );
182
179
  let outputOffset = 0;
183
180
 
@@ -185,6 +182,9 @@ export function adbGeneratePublicKey(
185
182
  outputView.setUint32(outputOffset, 2048 / 8 / 4, true);
186
183
  outputOffset += 4;
187
184
 
185
+ // extract `n` from private key
186
+ const [n] = rsaParsePrivateKey(privateKey);
187
+
188
188
  // Calculate `n0inv`
189
189
  // Don't know why need to multiply by -1
190
190
  // Didn't exist in Android codebase
@@ -221,7 +221,7 @@ export function adbGeneratePublicKey(
221
221
  export function powMod(
222
222
  base: bigint,
223
223
  exponent: bigint,
224
- modulus: bigint
224
+ modulus: bigint,
225
225
  ): bigint {
226
226
  if (modulus === 1n) {
227
227
  return 0n;