ds-01 1.0.8 → 1.0.9
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secureKeyStore.d.ts","sourceRoot":"","sources":["../../src/utils/secureKeyStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"secureKeyStore.d.ts","sourceRoot":"","sources":["../../src/utils/secureKeyStore.ts"],"names":[],"mappings":"AAmZA;;;;GAIG;AAEH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CASrD;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ1D;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,UAAU,CAAC,CAQrB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CASrD"}
|
|
@@ -23,24 +23,66 @@ function ensureSupportedOS() {
|
|
|
23
23
|
* ---------------------------------------------------------
|
|
24
24
|
* WINDOWS
|
|
25
25
|
* ---------------------------------------------------------
|
|
26
|
+
*
|
|
27
|
+
* Windows uses:
|
|
28
|
+
*
|
|
29
|
+
* Microsoft Platform Crypto Provider
|
|
30
|
+
* RSA 2048
|
|
31
|
+
* NonExportable private key
|
|
32
|
+
*
|
|
33
|
+
* The private key never enters Node.js.
|
|
34
|
+
*
|
|
35
|
+
* Node -> PowerShell -> Windows crypto provider
|
|
36
|
+
* ↓
|
|
37
|
+
* private key
|
|
38
|
+
* ↓
|
|
39
|
+
* signature
|
|
40
|
+
* ↓
|
|
41
|
+
* Node
|
|
42
|
+
*
|
|
43
|
+
* IMPORTANT:
|
|
44
|
+
*
|
|
45
|
+
* We identify the certificate using its properties rather
|
|
46
|
+
* than blindly taking the first certificate with the same
|
|
47
|
+
* subject.
|
|
26
48
|
*/
|
|
49
|
+
/**
|
|
50
|
+
* PowerShell expression used to identify a valid DS01
|
|
51
|
+
* certificate.
|
|
52
|
+
*
|
|
53
|
+
* Requirements:
|
|
54
|
+
*
|
|
55
|
+
* - Correct subject
|
|
56
|
+
* - Has private key
|
|
57
|
+
* - RSA certificate
|
|
58
|
+
* - Platform Crypto Provider
|
|
59
|
+
*/
|
|
60
|
+
const WINDOWS_CERT_FILTER = `
|
|
61
|
+
$_.Subject -eq "CN=${KEY_NAME}" -and
|
|
62
|
+
$_.HasPrivateKey -and
|
|
63
|
+
$_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
|
|
64
|
+
`;
|
|
27
65
|
async function createWindowsDeviceKey() {
|
|
28
66
|
const script = `
|
|
29
67
|
$ErrorActionPreference = "Stop"
|
|
30
68
|
|
|
31
|
-
$
|
|
69
|
+
$certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
|
|
32
70
|
Where-Object {
|
|
33
|
-
$
|
|
34
|
-
}
|
|
35
|
-
|
|
71
|
+
${WINDOWS_CERT_FILTER}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
if ($certificates.Count -gt 1) {
|
|
75
|
+
throw "Multiple valid DS01 device certificates found. Remove old DS01 device certificates before continuing."
|
|
76
|
+
}
|
|
36
77
|
|
|
37
|
-
if ($
|
|
78
|
+
if ($certificates.Count -eq 1) {
|
|
38
79
|
Write-Output "EXISTS"
|
|
39
80
|
exit 0
|
|
40
81
|
}
|
|
41
82
|
|
|
42
83
|
$params = @{
|
|
43
84
|
Type = "Custom"
|
|
85
|
+
|
|
44
86
|
Subject = "CN=${KEY_NAME}"
|
|
45
87
|
|
|
46
88
|
Provider = "Microsoft Platform Crypto Provider"
|
|
@@ -48,6 +90,7 @@ $params = @{
|
|
|
48
90
|
KeyAlgorithm = "RSA"
|
|
49
91
|
KeyLength = 2048
|
|
50
92
|
|
|
93
|
+
# Private key cannot be exported.
|
|
51
94
|
KeyExportPolicy = "NonExportable"
|
|
52
95
|
|
|
53
96
|
KeyUsage = "DigitalSignature"
|
|
@@ -58,7 +101,11 @@ $params = @{
|
|
|
58
101
|
NotAfter = (Get-Date).AddYears(10)
|
|
59
102
|
}
|
|
60
103
|
|
|
61
|
-
New-SelfSignedCertificate @params
|
|
104
|
+
$certificate = New-SelfSignedCertificate @params
|
|
105
|
+
|
|
106
|
+
if (-not $certificate) {
|
|
107
|
+
throw "Windows failed to create the DS01 device certificate."
|
|
108
|
+
}
|
|
62
109
|
|
|
63
110
|
Write-Output "CREATED"
|
|
64
111
|
`;
|
|
@@ -77,20 +124,42 @@ Write-Output "CREATED"
|
|
|
77
124
|
throw new Error("Failed to create Windows DS01 device key.");
|
|
78
125
|
}
|
|
79
126
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Find the exact DS01 certificate.
|
|
129
|
+
*
|
|
130
|
+
* We deliberately DO NOT use Select-Object -First 1.
|
|
131
|
+
*
|
|
132
|
+
* If multiple matching certificates exist, we fail instead
|
|
133
|
+
* of potentially using the wrong private key.
|
|
134
|
+
*/
|
|
135
|
+
function windowsCertificateLookupScript() {
|
|
136
|
+
return `
|
|
137
|
+
$certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
|
|
85
138
|
Where-Object {
|
|
86
|
-
$
|
|
87
|
-
}
|
|
88
|
-
Select-Object -First 1
|
|
139
|
+
${WINDOWS_CERT_FILTER}
|
|
140
|
+
})
|
|
89
141
|
|
|
90
|
-
if (-
|
|
142
|
+
if ($certificates.Count -eq 0) {
|
|
91
143
|
throw "DS01 device key not found."
|
|
92
144
|
}
|
|
93
145
|
|
|
146
|
+
if ($certificates.Count -gt 1) {
|
|
147
|
+
throw "Multiple valid DS01 device certificates found."
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
$certificates[0]
|
|
151
|
+
`;
|
|
152
|
+
}
|
|
153
|
+
async function getWindowsPublicKey() {
|
|
154
|
+
const script = `
|
|
155
|
+
$ErrorActionPreference = "Stop"
|
|
156
|
+
|
|
157
|
+
$cert = ${windowsCertificateLookupScript()}
|
|
158
|
+
|
|
159
|
+
# Return the complete public certificate.
|
|
160
|
+
#
|
|
161
|
+
# The certificate contains the public key and certificate
|
|
162
|
+
# metadata, but never the private key.
|
|
94
163
|
[Convert]::ToBase64String($cert.RawData)
|
|
95
164
|
`;
|
|
96
165
|
const { stdout } = await execFileAsync("powershell.exe", [
|
|
@@ -114,21 +183,14 @@ async function signWindowsDeviceKey(data) {
|
|
|
114
183
|
const script = `
|
|
115
184
|
$ErrorActionPreference = "Stop"
|
|
116
185
|
|
|
117
|
-
$cert =
|
|
118
|
-
Where-Object {
|
|
119
|
-
$_.Subject -eq "CN=${KEY_NAME}"
|
|
120
|
-
} |
|
|
121
|
-
Select-Object -First 1
|
|
122
|
-
|
|
123
|
-
if (-not $cert) {
|
|
124
|
-
throw "DS01 device key not found."
|
|
125
|
-
}
|
|
186
|
+
$cert = ${windowsCertificateLookupScript()}
|
|
126
187
|
|
|
127
188
|
if (-not $cert.HasPrivateKey) {
|
|
128
189
|
throw "DS01 device certificate has no private key."
|
|
129
190
|
}
|
|
130
191
|
|
|
131
|
-
$rsa =
|
|
192
|
+
$rsa =
|
|
193
|
+
[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
|
|
132
194
|
|
|
133
195
|
if (-not $rsa) {
|
|
134
196
|
throw "Unable to access DS01 private signing key."
|
|
@@ -169,15 +231,20 @@ async function deleteWindowsDeviceKey() {
|
|
|
169
231
|
const script = `
|
|
170
232
|
$ErrorActionPreference = "Stop"
|
|
171
233
|
|
|
172
|
-
$
|
|
234
|
+
$certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
|
|
173
235
|
Where-Object {
|
|
174
|
-
$
|
|
175
|
-
}
|
|
176
|
-
Select-Object -First 1
|
|
236
|
+
${WINDOWS_CERT_FILTER}
|
|
237
|
+
})
|
|
177
238
|
|
|
178
|
-
if ($
|
|
179
|
-
|
|
239
|
+
if ($certificates.Count -gt 1) {
|
|
240
|
+
throw "Multiple valid DS01 device certificates found."
|
|
180
241
|
}
|
|
242
|
+
|
|
243
|
+
if ($certificates.Count -eq 1) {
|
|
244
|
+
Remove-Item $certificates[0].PSPath
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
Write-Output "DELETED"
|
|
181
248
|
`;
|
|
182
249
|
await execFileAsync("powershell.exe", [
|
|
183
250
|
"-NoProfile",
|
|
@@ -208,8 +275,10 @@ async function runMacHelper(operation, data) {
|
|
|
208
275
|
}
|
|
209
276
|
async function createMacDeviceKey() {
|
|
210
277
|
const result = await runMacHelper("create");
|
|
211
|
-
if (result !== "CREATED" &&
|
|
212
|
-
|
|
278
|
+
if (result !== "CREATED" &&
|
|
279
|
+
result !== "EXISTS") {
|
|
280
|
+
throw new Error(result ||
|
|
281
|
+
"Failed to create macOS Secure Enclave device key.");
|
|
213
282
|
}
|
|
214
283
|
}
|
|
215
284
|
async function getMacPublicKey() {
|
package/package.json
CHANGED
|
@@ -22,7 +22,7 @@ function getMacHelperPath(): string {
|
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function ensureSupportedOS() {
|
|
25
|
+
function ensureSupportedOS(): void {
|
|
26
26
|
const platform = os.platform();
|
|
27
27
|
|
|
28
28
|
if (platform !== "win32" && platform !== "darwin") {
|
|
@@ -36,25 +36,68 @@ function ensureSupportedOS() {
|
|
|
36
36
|
* ---------------------------------------------------------
|
|
37
37
|
* WINDOWS
|
|
38
38
|
* ---------------------------------------------------------
|
|
39
|
+
*
|
|
40
|
+
* Windows uses:
|
|
41
|
+
*
|
|
42
|
+
* Microsoft Platform Crypto Provider
|
|
43
|
+
* RSA 2048
|
|
44
|
+
* NonExportable private key
|
|
45
|
+
*
|
|
46
|
+
* The private key never enters Node.js.
|
|
47
|
+
*
|
|
48
|
+
* Node -> PowerShell -> Windows crypto provider
|
|
49
|
+
* ↓
|
|
50
|
+
* private key
|
|
51
|
+
* ↓
|
|
52
|
+
* signature
|
|
53
|
+
* ↓
|
|
54
|
+
* Node
|
|
55
|
+
*
|
|
56
|
+
* IMPORTANT:
|
|
57
|
+
*
|
|
58
|
+
* We identify the certificate using its properties rather
|
|
59
|
+
* than blindly taking the first certificate with the same
|
|
60
|
+
* subject.
|
|
39
61
|
*/
|
|
40
62
|
|
|
63
|
+
/**
|
|
64
|
+
* PowerShell expression used to identify a valid DS01
|
|
65
|
+
* certificate.
|
|
66
|
+
*
|
|
67
|
+
* Requirements:
|
|
68
|
+
*
|
|
69
|
+
* - Correct subject
|
|
70
|
+
* - Has private key
|
|
71
|
+
* - RSA certificate
|
|
72
|
+
* - Platform Crypto Provider
|
|
73
|
+
*/
|
|
74
|
+
const WINDOWS_CERT_FILTER = `
|
|
75
|
+
$_.Subject -eq "CN=${KEY_NAME}" -and
|
|
76
|
+
$_.HasPrivateKey -and
|
|
77
|
+
$_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
|
|
78
|
+
`;
|
|
79
|
+
|
|
41
80
|
async function createWindowsDeviceKey(): Promise<void> {
|
|
42
81
|
const script = `
|
|
43
82
|
$ErrorActionPreference = "Stop"
|
|
44
83
|
|
|
45
|
-
$
|
|
84
|
+
$certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
|
|
46
85
|
Where-Object {
|
|
47
|
-
$
|
|
48
|
-
}
|
|
49
|
-
|
|
86
|
+
${WINDOWS_CERT_FILTER}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
if ($certificates.Count -gt 1) {
|
|
90
|
+
throw "Multiple valid DS01 device certificates found. Remove old DS01 device certificates before continuing."
|
|
91
|
+
}
|
|
50
92
|
|
|
51
|
-
if ($
|
|
93
|
+
if ($certificates.Count -eq 1) {
|
|
52
94
|
Write-Output "EXISTS"
|
|
53
95
|
exit 0
|
|
54
96
|
}
|
|
55
97
|
|
|
56
98
|
$params = @{
|
|
57
99
|
Type = "Custom"
|
|
100
|
+
|
|
58
101
|
Subject = "CN=${KEY_NAME}"
|
|
59
102
|
|
|
60
103
|
Provider = "Microsoft Platform Crypto Provider"
|
|
@@ -62,6 +105,7 @@ $params = @{
|
|
|
62
105
|
KeyAlgorithm = "RSA"
|
|
63
106
|
KeyLength = 2048
|
|
64
107
|
|
|
108
|
+
# Private key cannot be exported.
|
|
65
109
|
KeyExportPolicy = "NonExportable"
|
|
66
110
|
|
|
67
111
|
KeyUsage = "DigitalSignature"
|
|
@@ -72,7 +116,11 @@ $params = @{
|
|
|
72
116
|
NotAfter = (Get-Date).AddYears(10)
|
|
73
117
|
}
|
|
74
118
|
|
|
75
|
-
New-SelfSignedCertificate @params
|
|
119
|
+
$certificate = New-SelfSignedCertificate @params
|
|
120
|
+
|
|
121
|
+
if (-not $certificate) {
|
|
122
|
+
throw "Windows failed to create the DS01 device certificate."
|
|
123
|
+
}
|
|
76
124
|
|
|
77
125
|
Write-Output "CREATED"
|
|
78
126
|
`;
|
|
@@ -95,24 +143,49 @@ Write-Output "CREATED"
|
|
|
95
143
|
const result = stdout.trim();
|
|
96
144
|
|
|
97
145
|
if (result !== "CREATED" && result !== "EXISTS") {
|
|
98
|
-
throw new Error(
|
|
146
|
+
throw new Error(
|
|
147
|
+
"Failed to create Windows DS01 device key.",
|
|
148
|
+
);
|
|
99
149
|
}
|
|
100
150
|
}
|
|
101
151
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Find the exact DS01 certificate.
|
|
154
|
+
*
|
|
155
|
+
* We deliberately DO NOT use Select-Object -First 1.
|
|
156
|
+
*
|
|
157
|
+
* If multiple matching certificates exist, we fail instead
|
|
158
|
+
* of potentially using the wrong private key.
|
|
159
|
+
*/
|
|
160
|
+
function windowsCertificateLookupScript(): string {
|
|
161
|
+
return `
|
|
162
|
+
$certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
|
|
107
163
|
Where-Object {
|
|
108
|
-
$
|
|
109
|
-
}
|
|
110
|
-
Select-Object -First 1
|
|
164
|
+
${WINDOWS_CERT_FILTER}
|
|
165
|
+
})
|
|
111
166
|
|
|
112
|
-
if (-
|
|
167
|
+
if ($certificates.Count -eq 0) {
|
|
113
168
|
throw "DS01 device key not found."
|
|
114
169
|
}
|
|
115
170
|
|
|
171
|
+
if ($certificates.Count -gt 1) {
|
|
172
|
+
throw "Multiple valid DS01 device certificates found."
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
$certificates[0]
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function getWindowsPublicKey(): Promise<string> {
|
|
180
|
+
const script = `
|
|
181
|
+
$ErrorActionPreference = "Stop"
|
|
182
|
+
|
|
183
|
+
$cert = ${windowsCertificateLookupScript()}
|
|
184
|
+
|
|
185
|
+
# Return the complete public certificate.
|
|
186
|
+
#
|
|
187
|
+
# The certificate contains the public key and certificate
|
|
188
|
+
# metadata, but never the private key.
|
|
116
189
|
[Convert]::ToBase64String($cert.RawData)
|
|
117
190
|
`;
|
|
118
191
|
|
|
@@ -134,7 +207,9 @@ if (-not $cert) {
|
|
|
134
207
|
const certificate = stdout.trim();
|
|
135
208
|
|
|
136
209
|
if (!certificate) {
|
|
137
|
-
throw new Error(
|
|
210
|
+
throw new Error(
|
|
211
|
+
"Unable to read Windows DS01 public certificate.",
|
|
212
|
+
);
|
|
138
213
|
}
|
|
139
214
|
|
|
140
215
|
return certificate;
|
|
@@ -143,26 +218,20 @@ if (-not $cert) {
|
|
|
143
218
|
async function signWindowsDeviceKey(
|
|
144
219
|
data: Uint8Array,
|
|
145
220
|
): Promise<Uint8Array> {
|
|
146
|
-
const dataBase64 =
|
|
221
|
+
const dataBase64 =
|
|
222
|
+
Buffer.from(data).toString("base64");
|
|
147
223
|
|
|
148
224
|
const script = `
|
|
149
225
|
$ErrorActionPreference = "Stop"
|
|
150
226
|
|
|
151
|
-
$cert =
|
|
152
|
-
Where-Object {
|
|
153
|
-
$_.Subject -eq "CN=${KEY_NAME}"
|
|
154
|
-
} |
|
|
155
|
-
Select-Object -First 1
|
|
156
|
-
|
|
157
|
-
if (-not $cert) {
|
|
158
|
-
throw "DS01 device key not found."
|
|
159
|
-
}
|
|
227
|
+
$cert = ${windowsCertificateLookupScript()}
|
|
160
228
|
|
|
161
229
|
if (-not $cert.HasPrivateKey) {
|
|
162
230
|
throw "DS01 device certificate has no private key."
|
|
163
231
|
}
|
|
164
232
|
|
|
165
|
-
$rsa =
|
|
233
|
+
$rsa =
|
|
234
|
+
[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
|
|
166
235
|
|
|
167
236
|
if (-not $rsa) {
|
|
168
237
|
throw "Unable to access DS01 private signing key."
|
|
@@ -202,25 +271,34 @@ finally {
|
|
|
202
271
|
const signature = stdout.trim();
|
|
203
272
|
|
|
204
273
|
if (!signature) {
|
|
205
|
-
throw new Error(
|
|
274
|
+
throw new Error(
|
|
275
|
+
"Failed to sign data with Windows device key.",
|
|
276
|
+
);
|
|
206
277
|
}
|
|
207
278
|
|
|
208
|
-
return new Uint8Array(
|
|
279
|
+
return new Uint8Array(
|
|
280
|
+
Buffer.from(signature, "base64"),
|
|
281
|
+
);
|
|
209
282
|
}
|
|
210
283
|
|
|
211
284
|
async function deleteWindowsDeviceKey(): Promise<void> {
|
|
212
285
|
const script = `
|
|
213
286
|
$ErrorActionPreference = "Stop"
|
|
214
287
|
|
|
215
|
-
$
|
|
288
|
+
$certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
|
|
216
289
|
Where-Object {
|
|
217
|
-
$
|
|
218
|
-
}
|
|
219
|
-
Select-Object -First 1
|
|
290
|
+
${WINDOWS_CERT_FILTER}
|
|
291
|
+
})
|
|
220
292
|
|
|
221
|
-
if ($
|
|
222
|
-
|
|
293
|
+
if ($certificates.Count -gt 1) {
|
|
294
|
+
throw "Multiple valid DS01 device certificates found."
|
|
223
295
|
}
|
|
296
|
+
|
|
297
|
+
if ($certificates.Count -eq 1) {
|
|
298
|
+
Remove-Item $certificates[0].PSPath
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
Write-Output "DELETED"
|
|
224
302
|
`;
|
|
225
303
|
|
|
226
304
|
await execFileAsync(
|
|
@@ -246,7 +324,11 @@ if ($cert) {
|
|
|
246
324
|
*/
|
|
247
325
|
|
|
248
326
|
async function runMacHelper(
|
|
249
|
-
operation:
|
|
327
|
+
operation:
|
|
328
|
+
| "create"
|
|
329
|
+
| "public"
|
|
330
|
+
| "sign"
|
|
331
|
+
| "delete",
|
|
250
332
|
data?: Uint8Array,
|
|
251
333
|
): Promise<string> {
|
|
252
334
|
const helper = getMacHelperPath();
|
|
@@ -254,7 +336,9 @@ async function runMacHelper(
|
|
|
254
336
|
const args = [helper, operation];
|
|
255
337
|
|
|
256
338
|
if (data) {
|
|
257
|
-
args.push(
|
|
339
|
+
args.push(
|
|
340
|
+
Buffer.from(data).toString("base64"),
|
|
341
|
+
);
|
|
258
342
|
}
|
|
259
343
|
|
|
260
344
|
const { stdout } = await execFileAsync(
|
|
@@ -269,17 +353,23 @@ async function runMacHelper(
|
|
|
269
353
|
}
|
|
270
354
|
|
|
271
355
|
async function createMacDeviceKey(): Promise<void> {
|
|
272
|
-
const result =
|
|
356
|
+
const result =
|
|
357
|
+
await runMacHelper("create");
|
|
273
358
|
|
|
274
|
-
if (
|
|
359
|
+
if (
|
|
360
|
+
result !== "CREATED" &&
|
|
361
|
+
result !== "EXISTS"
|
|
362
|
+
) {
|
|
275
363
|
throw new Error(
|
|
276
|
-
result ||
|
|
364
|
+
result ||
|
|
365
|
+
"Failed to create macOS Secure Enclave device key.",
|
|
277
366
|
);
|
|
278
367
|
}
|
|
279
368
|
}
|
|
280
369
|
|
|
281
370
|
async function getMacPublicKey(): Promise<string> {
|
|
282
|
-
const result =
|
|
371
|
+
const result =
|
|
372
|
+
await runMacHelper("public");
|
|
283
373
|
|
|
284
374
|
if (!result) {
|
|
285
375
|
throw new Error(
|
|
@@ -293,7 +383,8 @@ async function getMacPublicKey(): Promise<string> {
|
|
|
293
383
|
async function signMacDeviceKey(
|
|
294
384
|
data: Uint8Array,
|
|
295
385
|
): Promise<Uint8Array> {
|
|
296
|
-
const result =
|
|
386
|
+
const result =
|
|
387
|
+
await runMacHelper("sign", data);
|
|
297
388
|
|
|
298
389
|
if (!result) {
|
|
299
390
|
throw new Error(
|