ds-01 1.0.9 → 1.0.10

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":"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"}
1
+ {"version":3,"file":"secureKeyStore.d.ts","sourceRoot":"","sources":["../../src/utils/secureKeyStore.ts"],"names":[],"mappings":"AA2WA;;;;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"}
@@ -9,8 +9,6 @@ const KEY_NAME = "DS01-CLI-Device-Key";
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
11
  function getMacHelperPath() {
12
- // dist/utils/secureKeyStore.js
13
- // ../native/macos-key-helper.swift
14
12
  return path.resolve(__dirname, "../native/macos-key-helper.swift");
15
13
  }
16
14
  function ensureSupportedOS() {
@@ -23,52 +21,16 @@ function ensureSupportedOS() {
23
21
  * ---------------------------------------------------------
24
22
  * WINDOWS
25
23
  * ---------------------------------------------------------
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.
48
24
  */
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
- `;
65
25
  async function createWindowsDeviceKey() {
66
26
  const script = `
67
27
  $ErrorActionPreference = "Stop"
68
28
 
69
29
  $certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
70
30
  Where-Object {
71
- ${WINDOWS_CERT_FILTER}
31
+ $_.Subject -eq "CN=${KEY_NAME}" -and
32
+ $_.HasPrivateKey -and
33
+ $_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
72
34
  })
73
35
 
74
36
  if ($certificates.Count -gt 1) {
@@ -82,7 +44,6 @@ if ($certificates.Count -eq 1) {
82
44
 
83
45
  $params = @{
84
46
  Type = "Custom"
85
-
86
47
  Subject = "CN=${KEY_NAME}"
87
48
 
88
49
  Provider = "Microsoft Platform Crypto Provider"
@@ -90,7 +51,6 @@ $params = @{
90
51
  KeyAlgorithm = "RSA"
91
52
  KeyLength = 2048
92
53
 
93
- # Private key cannot be exported.
94
54
  KeyExportPolicy = "NonExportable"
95
55
 
96
56
  KeyUsage = "DigitalSignature"
@@ -125,18 +85,21 @@ Write-Output "CREATED"
125
85
  }
126
86
  }
127
87
  /**
128
- * Find the exact DS01 certificate.
88
+ * Find exactly one valid DS01 certificate.
129
89
  *
130
- * We deliberately DO NOT use Select-Object -First 1.
90
+ * We intentionally do not use Select-Object -First 1.
131
91
  *
132
- * If multiple matching certificates exist, we fail instead
133
- * of potentially using the wrong private key.
92
+ * 0 certificates -> error
93
+ * 1 certificate -> use it
94
+ * 2+ certificates -> error
134
95
  */
135
- function windowsCertificateLookupScript() {
96
+ function getWindowsCertificateLookup() {
136
97
  return `
137
98
  $certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
138
99
  Where-Object {
139
- ${WINDOWS_CERT_FILTER}
100
+ $_.Subject -eq "CN=${KEY_NAME}" -and
101
+ $_.HasPrivateKey -and
102
+ $_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
140
103
  })
141
104
 
142
105
  if ($certificates.Count -eq 0) {
@@ -147,19 +110,15 @@ if ($certificates.Count -gt 1) {
147
110
  throw "Multiple valid DS01 device certificates found."
148
111
  }
149
112
 
150
- $certificates[0]
113
+ $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]$certificates[0]
151
114
  `;
152
115
  }
153
116
  async function getWindowsPublicKey() {
154
117
  const script = `
155
118
  $ErrorActionPreference = "Stop"
156
119
 
157
- $cert = ${windowsCertificateLookupScript()}
120
+ ${getWindowsCertificateLookup()}
158
121
 
159
- # Return the complete public certificate.
160
- #
161
- # The certificate contains the public key and certificate
162
- # metadata, but never the private key.
163
122
  [Convert]::ToBase64String($cert.RawData)
164
123
  `;
165
124
  const { stdout } = await execFileAsync("powershell.exe", [
@@ -183,7 +142,7 @@ async function signWindowsDeviceKey(data) {
183
142
  const script = `
184
143
  $ErrorActionPreference = "Stop"
185
144
 
186
- $cert = ${windowsCertificateLookupScript()}
145
+ ${getWindowsCertificateLookup()}
187
146
 
188
147
  if (-not $cert.HasPrivateKey) {
189
148
  throw "DS01 device certificate has no private key."
@@ -233,7 +192,9 @@ $ErrorActionPreference = "Stop"
233
192
 
234
193
  $certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
235
194
  Where-Object {
236
- ${WINDOWS_CERT_FILTER}
195
+ $_.Subject -eq "CN=${KEY_NAME}" -and
196
+ $_.HasPrivateKey -and
197
+ $_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
237
198
  })
238
199
 
239
200
  if ($certificates.Count -gt 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ds-01",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "Make your site best with DS01",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,8 +14,6 @@ const __filename = fileURLToPath(import.meta.url);
14
14
  const __dirname = path.dirname(__filename);
15
15
 
16
16
  function getMacHelperPath(): string {
17
- // dist/utils/secureKeyStore.js
18
- // ../native/macos-key-helper.swift
19
17
  return path.resolve(
20
18
  __dirname,
21
19
  "../native/macos-key-helper.swift",
@@ -36,54 +34,17 @@ function ensureSupportedOS(): void {
36
34
  * ---------------------------------------------------------
37
35
  * WINDOWS
38
36
  * ---------------------------------------------------------
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.
61
37
  */
62
38
 
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
-
80
39
  async function createWindowsDeviceKey(): Promise<void> {
81
40
  const script = `
82
41
  $ErrorActionPreference = "Stop"
83
42
 
84
43
  $certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
85
44
  Where-Object {
86
- ${WINDOWS_CERT_FILTER}
45
+ $_.Subject -eq "CN=${KEY_NAME}" -and
46
+ $_.HasPrivateKey -and
47
+ $_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
87
48
  })
88
49
 
89
50
  if ($certificates.Count -gt 1) {
@@ -97,7 +58,6 @@ if ($certificates.Count -eq 1) {
97
58
 
98
59
  $params = @{
99
60
  Type = "Custom"
100
-
101
61
  Subject = "CN=${KEY_NAME}"
102
62
 
103
63
  Provider = "Microsoft Platform Crypto Provider"
@@ -105,7 +65,6 @@ $params = @{
105
65
  KeyAlgorithm = "RSA"
106
66
  KeyLength = 2048
107
67
 
108
- # Private key cannot be exported.
109
68
  KeyExportPolicy = "NonExportable"
110
69
 
111
70
  KeyUsage = "DigitalSignature"
@@ -150,18 +109,21 @@ Write-Output "CREATED"
150
109
  }
151
110
 
152
111
  /**
153
- * Find the exact DS01 certificate.
112
+ * Find exactly one valid DS01 certificate.
154
113
  *
155
- * We deliberately DO NOT use Select-Object -First 1.
114
+ * We intentionally do not use Select-Object -First 1.
156
115
  *
157
- * If multiple matching certificates exist, we fail instead
158
- * of potentially using the wrong private key.
116
+ * 0 certificates -> error
117
+ * 1 certificate -> use it
118
+ * 2+ certificates -> error
159
119
  */
160
- function windowsCertificateLookupScript(): string {
120
+ function getWindowsCertificateLookup(): string {
161
121
  return `
162
122
  $certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
163
123
  Where-Object {
164
- ${WINDOWS_CERT_FILTER}
124
+ $_.Subject -eq "CN=${KEY_NAME}" -and
125
+ $_.HasPrivateKey -and
126
+ $_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
165
127
  })
166
128
 
167
129
  if ($certificates.Count -eq 0) {
@@ -172,7 +134,7 @@ if ($certificates.Count -gt 1) {
172
134
  throw "Multiple valid DS01 device certificates found."
173
135
  }
174
136
 
175
- $certificates[0]
137
+ $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]$certificates[0]
176
138
  `;
177
139
  }
178
140
 
@@ -180,12 +142,8 @@ async function getWindowsPublicKey(): Promise<string> {
180
142
  const script = `
181
143
  $ErrorActionPreference = "Stop"
182
144
 
183
- $cert = ${windowsCertificateLookupScript()}
145
+ ${getWindowsCertificateLookup()}
184
146
 
185
- # Return the complete public certificate.
186
- #
187
- # The certificate contains the public key and certificate
188
- # metadata, but never the private key.
189
147
  [Convert]::ToBase64String($cert.RawData)
190
148
  `;
191
149
 
@@ -224,7 +182,7 @@ async function signWindowsDeviceKey(
224
182
  const script = `
225
183
  $ErrorActionPreference = "Stop"
226
184
 
227
- $cert = ${windowsCertificateLookupScript()}
185
+ ${getWindowsCertificateLookup()}
228
186
 
229
187
  if (-not $cert.HasPrivateKey) {
230
188
  throw "DS01 device certificate has no private key."
@@ -287,7 +245,9 @@ $ErrorActionPreference = "Stop"
287
245
 
288
246
  $certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
289
247
  Where-Object {
290
- ${WINDOWS_CERT_FILTER}
248
+ $_.Subject -eq "CN=${KEY_NAME}" -and
249
+ $_.HasPrivateKey -and
250
+ $_.PublicKey.Oid.Value -eq "1.2.840.113549.1.1.1"
291
251
  })
292
252
 
293
253
  if ($certificates.Count -gt 1) {