@certchip/signer 0.1.19 → 0.1.27

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/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  Cross-platform code and document signing CLI tool with SSH key authentication.
4
4
 
5
+ > **Note:** This program module can be used in environments where Certchip Signer Server is deployed.
6
+
5
7
  ## Features
6
8
 
7
- - **Cross-platform** - Windows, Linux, macOS (x64, arm64)
9
+ - **Cross-platform** - Windows (x64), Linux (x64), macOS (coming soon)
8
10
  - **SSH Key Authentication** - Ed25519, ECDSA, RSA support
9
11
  - **Code Signing** - PE executables (EXE, DLL, SYS, OCX), MSI, MSP, CAB
10
12
  - **Document Signing** - PDF with visual signature (watermark, box, barcode, QR code)
@@ -13,6 +15,9 @@ Cross-platform code and document signing CLI tool with SSH key authentication.
13
15
  - **Hash-based Signing** - Default mode: only hash sent to server, not the file
14
16
  - **Windows KSP** - Native Windows crypto integration (Windows only)
15
17
  - **Structured Output** - JSON, table, or CSV output for scripting and automation
18
+ - **Certificate Distribution** - Remote certificate download, renewal, and sync for SSL/TLS, device, and signing certificates (`-cert-dist`)
19
+ - **Let's Encrypt Management** - Direct access to Let's Encrypt SSL certificates stored on the server (`-letsencrypt`)
20
+ - **Certificate Management API** - Upload, download, delete certificates/keys, CSR generation (`-cert`, `-privkey`, `-pubkey`, `-csr`)
16
21
 
17
22
  ## Installation
18
23
 
@@ -32,8 +37,9 @@ npm install @certchip/signer
32
37
  # Login with SSH key authentication
33
38
  signercli -login https://signer.example.com username
34
39
 
35
- # Sign a file
36
- signercli myapp.exe
40
+ # Sign a file (two equivalent forms)
41
+ signercli myapp.exe # Implicit form
42
+ signercli -sign myapp.exe # Explicit form
37
43
 
38
44
  # Verify signature
39
45
  signercli -verify myapp.exe
@@ -48,8 +54,9 @@ signercli -logout
48
54
  # Login (certificate is installed to Windows certificate store)
49
55
  signer -login https://signer.example.com username
50
56
 
51
- # Sign directly with signer (same options as signercli)
52
- signer myapp.exe # Default: hash-only mode
57
+ # Sign directly with signer (two equivalent forms, same options as signercli)
58
+ signer myapp.exe # Implicit form (default: hash-only mode)
59
+ signer -sign myapp.exe # Explicit form
53
60
  signer myapp.exe -o myapp_signed.exe # Specify output file
54
61
  signer myapp.exe -file-upload -save-signed # Upload file, save with _signed suffix
55
62
 
@@ -74,26 +81,100 @@ npx signer myapp.exe
74
81
 
75
82
  ## CLI Commands
76
83
 
77
- This package provides two CLI tools with different purposes:
84
+ This package provides two CLI tools with different capabilities:
85
+
86
+ ### Tool Comparison Overview
78
87
 
79
88
  | | signercli | signer |
80
89
  |---|-----------|--------|
81
- | **Purpose** | Direct file signing | Direct signing + Windows signtool integration |
90
+ | **Purpose** | Full-featured signing and certificate management | Windows signtool.exe integration + direct signing |
82
91
  | **Platform** | Windows, Linux, macOS | Windows only |
83
- | **How it works** | Signs files directly via server API | Signs files directly OR provides certificates to Windows crypto system |
84
- | **Best for** | CI/CD, cross-platform, simple signing | Windows developers, signtool.exe integration |
85
-
86
- ### When to use which tool?
87
-
88
- | Scenario | Recommended |
89
- |----------|-------------|
90
- | CI/CD pipeline (any platform) | signercli |
91
- | Linux/macOS development | signercli |
92
- | Simple file signing | signercli or signer |
93
- | Windows direct signing | signer or signercli |
94
- | Using Windows signtool.exe | signer |
95
- | Windows certificate store integration | signer |
96
- | Visual Studio post-build signing | signercli or signer |
92
+ | **How it works** | Signs files directly via server API | Registers certificates in Windows store for signtool.exe integration |
93
+ | **Best for** | CI/CD, automation, cross-platform, certificate management | Windows developers, signtool.exe, Visual Studio integration |
94
+
95
+ ### Feature Comparison
96
+
97
+ | Feature | signercli | signer |
98
+ |---------|:---------:|:------:|
99
+ | **Platform Support** | | |
100
+ | Windows | | |
101
+ | Linux | | |
102
+ | macOS | | |
103
+ | ARM64 support | | |
104
+ | **Authentication** | | |
105
+ | SSH key (Ed25519, ECDSA, RSA) | | |
106
+ | Password authentication | ✅ | ✅ |
107
+ | API key (no login required) | ✅ | ❌ |
108
+ | Profile-based configuration | ✅ | ✅ |
109
+ | **File Signing** | | |
110
+ | PE executables (.exe, .dll, .sys, .ocx) | ✅ | ✅ |
111
+ | Installers (.msi, .msp, .cab) | ✅ | ✅ |
112
+ | PDF documents | ✅ | ✅ |
113
+ | Scripts (.ps1, .vbs) | ✅ | ✅ |
114
+ | Source code (JS, Python, Go, Rust, etc.) | ✅ | ✅ |
115
+ | JAR files | ✅ | ✅ |
116
+ | Hash-only signing (default) | ✅ | ✅ |
117
+ | File upload signing | ✅ | ✅ |
118
+ | **PDF Signature Options** | | |
119
+ | Watermark style | ✅ | ✅ |
120
+ | Box style | ✅ | ✅ |
121
+ | Barcode style | ✅ | ✅ |
122
+ | QR code style | ✅ | ✅ |
123
+ | Position/opacity control | ✅ | ✅ |
124
+ | **Certificate Management** | | |
125
+ | List certificates | ✅ | ✅ |
126
+ | Get/Set certificate ID | ✅ | ✅ |
127
+ | Get certificate PEM | ✅ | ✅ |
128
+ | Set private key password | ✅ | ✅ |
129
+ | Upload certificates | ✅ | ❌ |
130
+ | Download certificates (PEM/DER/PFX) | ✅ | ❌ |
131
+ | Delete certificates | ✅ | ❌ |
132
+ | Update certificate metadata | ✅ | ❌ |
133
+ | **Private Key Management** | | |
134
+ | List private keys | ✅ | ❌ |
135
+ | Upload private keys | ✅ | ❌ |
136
+ | Download private keys | ✅ | ❌ |
137
+ | Delete private keys | ✅ | ❌ |
138
+ | Link/Unlink to certificates | ✅ | ❌ |
139
+ | **CSR & Public Key** | | |
140
+ | Generate CSR | ✅ | ❌ |
141
+ | Public key management | ✅ | ❌ |
142
+ | **Certificate Distribution** | | |
143
+ | Let's Encrypt SSL certificates | ✅ | ❌ |
144
+ | Let's Encrypt direct management | ✅ | ❌ |
145
+ | Device certificates | ✅ | ❌ |
146
+ | Signing certificates | ✅ | ❌ |
147
+ | Auto-renewal check | ✅ | ❌ |
148
+ | Multiple download formats | ✅ | ❌ |
149
+ | **Windows Integration** | | |
150
+ | signtool.exe integration | ❌ | ✅ |
151
+ | Windows certificate store | ❌ | ✅ |
152
+ | KSP provider registration | ❌ | ✅ |
153
+ | Key container management | ❌ | ✅ |
154
+ | **Output & Automation** | | |
155
+ | Classic output | ✅ | ✅ |
156
+ | JSON output | ✅ | ❌ |
157
+ | Table output | ✅ | ❌ |
158
+ | CSV output | ✅ | ❌ |
159
+ | Log level control | ✅ | ✅ |
160
+
161
+ ### When to Use Which Tool?
162
+
163
+ | Scenario | Recommended Tool |
164
+ |----------|------------------|
165
+ | CI/CD pipeline (any platform) | **signercli** - Cross-platform, JSON output, API key auth |
166
+ | Linux/macOS development | **signercli** - Only option for non-Windows |
167
+ | Simple file signing | **signercli** or **signer** - Both work equally |
168
+ | Windows signtool.exe integration | **signer** - Registers cert to Windows store |
169
+ | Visual Studio post-build signing | **signer** - signtool.exe compatible |
170
+ | Windows certificate store integration | **signer** - KSP provider support |
171
+ | Certificate upload/download/delete | **signercli** - `-cert` with API key |
172
+ | Let's Encrypt certificate distribution | **signercli** - `-cert-dist` command |
173
+ | Let's Encrypt direct management | **signercli** - `-letsencrypt` command |
174
+ | Private key management | **signercli** - `-privkey` command |
175
+ | CSR generation | **signercli** - `-csr` command |
176
+ | Automation without SSH keys | **signercli** - API key authentication |
177
+ | Parsing output in scripts | **signercli** - `-format json` option |
97
178
 
98
179
  ---
99
180
 
@@ -130,10 +211,12 @@ signercli -logout [url]
130
211
 
131
212
  ```bash
132
213
  # Basic signing (default: hash-only mode)
133
- signercli <file>
214
+ signercli <file> # Implicit form
215
+ signercli -sign <file> # Explicit form (same result)
134
216
 
135
217
  # Signing options
136
218
  signercli <file> -o <output> # Specify output file
219
+ signercli -sign <file> -o <output> # Explicit form
137
220
  signercli <file> -save-signed # Save with _signed suffix (preserve original)
138
221
  signercli <file> -hash-only # Hash-based signing (default)
139
222
  signercli <file> -file-upload # Upload entire file to server
@@ -142,6 +225,8 @@ signercli <file> -timestamp-url <url> # Timestamp server URL
142
225
  signercli <file> -profile <name> # Use config profile
143
226
  ```
144
227
 
228
+ > **Note:** Both `signercli <file>` (implicit) and `signercli -sign <file>` (explicit) forms are equivalent. The explicit form makes intent clearer in scripts and automation.
229
+
145
230
  > **Note:** Hash-only signing is the default mode. Only the file hash is sent to the server, not the entire file.
146
231
 
147
232
  #### Signature Verification
@@ -175,9 +260,17 @@ signercli -codesign-set <password>
175
260
 
176
261
  ```bash
177
262
  # List certificates (with purpose filter)
178
- signercli -cert -list # List all certificates
179
- signercli -cert -list codesign # List code signing certificates
180
- signercli -cert -list docsign # List document signing certificates
263
+ signercli -cert list # List all certificates with private keys (default)
264
+ signercli -cert list any # List all certificates (including without private keys)
265
+ signercli -cert list codesign # List code signing certificates
266
+ signercli -cert list docsign # List document signing certificates
267
+ signercli -cert list serverauth # List server authentication (SSL/TLS) certificates
268
+ signercli -cert list clientauth # List client authentication certificates
269
+ signercli -cert list ca # List CA certificates
270
+ signercli -cert list timestamp # List timestamping certificates
271
+ signercli -cert list ocsp # List OCSP signing certificates
272
+ signercli -cert list encrypt # List encryption certificates
273
+ signercli -cert list verify # List verification certificates
181
274
 
182
275
  # Get/Set certificate ID
183
276
  signercli -cert -id # Show current configuration
@@ -195,37 +288,151 @@ signercli -cert -password <password>
195
288
 
196
289
  #### Configuration
197
290
 
198
- Profiles store connection settings. The `default` profile is used when no profile is specified. Other profiles inherit missing settings from `default`.
291
+ The configuration file allows you to store connection settings, authentication credentials, and signing options in reusable profiles. This eliminates the need to specify the same options repeatedly on the command line.
292
+
293
+ > **Detailed guide:** See [docs/CONFIG-FILE-GUIDE.md](docs/CONFIG-FILE-GUIDE.md) for complete configuration options and examples.
294
+
295
+ **Why Use Configuration Profiles:**
296
+
297
+ - **Convenience:** Store server URL, API key, and other settings once
298
+ - **Multiple Environments:** Switch between production, staging, and development servers
299
+ - **CI/CD Integration:** Pre-configure settings for automated signing workflows
300
+ - **Security:** Keep credentials out of command history and scripts
301
+
302
+ **Understanding the Default Profile:**
303
+
304
+ The `[default]` profile is special - it serves as the base configuration for all operations:
305
+
306
+ 1. **Automatic loading:** When no `-profile` option is specified, SignerCLI automatically uses `[default]`
307
+ 2. **Inheritance:** Named profiles (like `[production]` or `[staging]`) inherit all settings from `[default]`
308
+ 3. **Override behavior:** Named profiles only need to specify settings that differ from `[default]`
309
+
310
+ This inheritance model means you should:
311
+ - Store **common settings** (server URL, API key) in `[default]`
312
+ - Store **environment-specific settings** (certificate ID, timestamp URL) in named profiles
313
+
314
+ ```
315
+ ┌─────────────────────────────────────────────────────┐
316
+ │ [default] │
317
+ │ host = https://signer.example.com:7443 │
318
+ │ api_key = cdk_xxx... │
319
+ │ hash_algorithm = sha256 │
320
+ ├─────────────────────────────────────────────────────┤
321
+ │ [production] │ [staging] │
322
+ │ cert_id = prod-001 │ host = https://stg:7443│
323
+ │ (inherits host, │ cert_id = stg-001 │
324
+ │ api_key, hash_alg) │ (inherits api_key, │
325
+ │ │ hash_alg) │
326
+ └───────────────────────────┴─────────────────────────┘
327
+ ```
328
+
329
+ **Config File Location:**
330
+
331
+ | OS | Path |
332
+ |----|------|
333
+ | Linux/macOS | `~/.signer/config` |
334
+ | Windows | `%USERPROFILE%\.signer\config` |
335
+
336
+ **Basic Commands:**
199
337
 
200
338
  ```bash
201
339
  # View configuration
202
- signercli -config # Show config file
340
+ signercli -config # Show entire config file
203
341
  signercli -config list # List all profiles
204
- signercli -config show <name> # Show profile details
342
+ signercli -config show <name> # Show specific profile details
205
343
 
206
- # Create/Update profile
207
- signercli -config set <name> [options]
344
+ # Create/Update profile (profile name defaults to 'default' if omitted)
345
+ signercli -config set [name] [options]
208
346
 
209
- # Delete profile
347
+ # Remove specific settings from profile
348
+ signercli -config unset [name] <options>
349
+
350
+ # Delete entire profile
210
351
  signercli -config delete <name>
211
352
  ```
212
353
 
354
+ **Removing Settings (`-config unset`):**
355
+
356
+ ```bash
357
+ # Remove api_key from default profile
358
+ signercli -config unset -api-key
359
+
360
+ # Remove multiple settings
361
+ signercli -config unset -api-key -host
362
+
363
+ # Remove from named profile
364
+ signercli -config unset production -cert-id
365
+ ```
366
+
367
+ **API Key Authentication (No Login Required):**
368
+
369
+ Store an API key in a profile to use `-cert`, `-privkey`, `-pubkey`, `-csr`, `-cert-dist` commands without login.
370
+
371
+ ```bash
372
+ # Set API key in default profile (profile name omitted = 'default')
373
+ signercli -config set \
374
+ -host https://signer.example.com:7443 \
375
+ -api-key cdk_e2f369e7c85bfa7835d375f6b088f15dac2c2d8ebeb0815c392a6d6b34ee916f
376
+
377
+ # Same as above (explicit 'default')
378
+ signercli -config set default \
379
+ -host https://signer.example.com:7443 \
380
+ -api-key cdk_e2f369e7c85bfa7835d375f6b088f15dac2c2d8ebeb0815c392a6d6b34ee916f
381
+
382
+ # Use commands without login (API key auto-applied)
383
+ signercli -cert list
384
+ signercli -cert get <id>
385
+ signercli -cert upload cert.pem -name "My Cert"
386
+ signercli -cert-dist list
387
+ ```
388
+
213
389
  **Profile Inheritance Example:**
214
390
 
215
391
  ```bash
216
- # Set common settings in 'default' profile
217
- signercli -config set default -host https://signer.example.com -username admin
392
+ # Set common settings in default profile (profile name optional)
393
+ signercli -config set \
394
+ -host https://signer.example.com:7443 \
395
+ -api-key cdk_common_api_key \
396
+ -hash-algorithm sha256
218
397
 
219
- # Create 'production' profile (inherits host and username from default)
398
+ # Create production profile (inherits host, api_key, hash-algorithm)
220
399
  signercli -config set production -cert-id prod-cert-001
221
400
 
222
- # Create 'staging' profile with different host (overrides default)
223
- signercli -config set staging -host https://staging.example.com -cert-id staging-cert
401
+ # Create staging profile (overrides host, inherits others)
402
+ signercli -config set staging \
403
+ -host https://staging.example.com:7443 \
404
+ -cert-id staging-cert-001
224
405
 
225
406
  # Usage
226
- signercli -login # Uses 'default' profile
227
- signercli -login -profile production # Uses 'production' (inherits from default)
228
- signercli -login -profile staging # Uses 'staging' (overrides host)
407
+ signercli -cert list # Uses default profile
408
+ signercli -cert list -profile production # Uses production profile
409
+ signercli -cert list -profile staging # Uses staging profile
410
+ ```
411
+
412
+ **Inheritance Display:**
413
+
414
+ ```
415
+ $ signercli -config show production
416
+ Profile: [production]
417
+ ----------------------------------------
418
+ host = https://signer.example.com:7443 (default)
419
+ api_key = cdk_common_api_key (default)
420
+ cert_id = prod-cert-001
421
+ hash_algorithm = sha256 (default)
422
+ ```
423
+ > The `(default)` marker indicates the value is inherited from the `[default]` profile.
424
+
425
+ **Authentication Priority:**
426
+
427
+ 1. **Command-line arguments** (`-api-key`, `-host`) - Highest priority
428
+ 2. **Specified profile** (`-profile <name>`)
429
+ 3. **Default profile**
430
+ 4. **Login token** (if available)
431
+
432
+ ```bash
433
+ # Command-line args override profile settings
434
+ signercli -cert list -profile production -host https://other:7443
435
+ # → Uses other:7443 (ignores production's host)
229
436
  ```
230
437
 
231
438
  **Profile Options:**
@@ -235,14 +442,15 @@ signercli -login -profile staging # Uses 'staging' (overrides host)
235
442
  | `-host <url>` | Server URL |
236
443
  | `-ssh-key-path <path>` | SSH private key path |
237
444
  | `-username <name>` | SSH username |
238
- | `-user <id>` | Password auth user ID |
445
+ | `-user <id>` | User ID for password auth |
446
+ | `-api-key <key>` | API key (bypasses login) |
239
447
  | `-cert-id <id>` | Default certificate ID |
240
448
  | `-cert-serial <sn>` | Certificate serial number |
241
449
  | `-expires <time>` | Token expiration (24h, 7d, 1w) |
242
450
  | `-include-chain` | Include certificate chain |
243
451
  | `-timestamp-url <url>` | Timestamp server URL |
244
- | `-hash-algorithm <alg>` | Default hash algorithm |
245
- | `-output-format <type>` | Default output format (classic, json, table, csv) |
452
+ | `-hash-algorithm <alg>` | Hash algorithm (sha256, sha384, sha512) |
453
+ | `-output-format <type>` | Output format (classic, json, table, csv) |
246
454
 
247
455
  **Document Signing Options:**
248
456
 
@@ -251,9 +459,34 @@ signercli -login -profile staging # Uses 'staging' (overrides host)
251
459
  | `-doc-style <style>` | watermark, box, barcode, qrcode |
252
460
  | `-doc-position <pos>` | bottom-right, bottom-left, top-right, top-left, center |
253
461
  | `-doc-sig-position <pos>` | left, center, right (for barcode/qrcode) |
254
- | `-doc-font-size <size>` | Font size for signature |
462
+ | `-doc-font-size <size>` | Signature font size |
255
463
  | `-doc-opacity <value>` | Opacity (0.0-1.0 or 0-100) |
256
464
 
465
+ **Config File Example (`~/.signer/config`):**
466
+
467
+ ```ini
468
+ [default]
469
+ host=https://signer.example.com:7443
470
+ api_key=cdk_e2f369e7c85bfa7835d375f6b088f15dac2c2d8ebeb0815c392a6d6b34ee916f
471
+ hash_algorithm=sha256
472
+ output_format=classic
473
+
474
+ [production]
475
+ cert_id=prod-codesign-001
476
+ timestamp_url=http://timestamp.digicert.com
477
+ include_chain=true
478
+
479
+ [ci-automation]
480
+ api_key=cdk_ci_specific_api_key
481
+ output_format=json
482
+ cert_id=automation-cert-001
483
+ ```
484
+
485
+ **Security Notes:**
486
+
487
+ - API keys are stored in plain text in the config file
488
+ - Set appropriate file permissions: `chmod 600 ~/.signer/config` (Linux/macOS)
489
+
257
490
  #### Windows DLL Installation
258
491
 
259
492
  ```bash
@@ -282,17 +515,17 @@ The `-version` command displays comprehensive version information:
282
515
 
283
516
  ```
284
517
  # signercli -version
285
- Certchip Signer CLI v0.1.18
518
+ Certchip Signer CLI v0.1.27
286
519
  Cross-platform code and document signing tool
287
520
  Copyright (c) 2025 Certchip. All rights reserved.
288
521
 
289
522
  DLL Versions (Local):
290
- otpkey.dll: 0.1.18.0
291
- Certchip.dll: 0.1.18.0
523
+ otpkey.dll: 0.1.27.0
524
+ Certchip.dll: 0.1.27.0
292
525
 
293
526
  DLL Versions (System32):
294
- otpkey.dll: 0.1.18.0
295
- Certchip.dll: 0.1.18.0
527
+ otpkey.dll: 0.1.27.0
528
+ Certchip.dll: 0.1.27.0
296
529
  ```
297
530
 
298
531
  | Information | Description |
@@ -394,7 +627,7 @@ $ signercli -login https://signer.example.com admin -pw secret -format json
394
627
  Windows-specific tool that integrates with the Windows cryptographic system via KSP (Key Storage Provider). It can both sign files directly (like signercli) and register certificates in the Windows certificate store for use with `signtool.exe`.
395
628
 
396
629
  **Two signing methods:**
397
- 1. **Direct signing** - Sign files directly with `signer <file>` (same as signercli)
630
+ 1. **Direct signing** - Sign files directly with `signer <file>` or `signer -sign <file>` (same as signercli)
398
631
  2. **signtool integration** - Login to register certificate, then use Windows signtool.exe
399
632
 
400
633
  ```bash
@@ -403,7 +636,8 @@ signer -login <url> [username] # Login and register certificate
403
636
  signer -logout # Logout and remove certificate
404
637
 
405
638
  # File Signing (direct - same options as signercli)
406
- signer <file> [options] # Sign a file directly
639
+ signer <file> [options] # Sign a file (implicit form)
640
+ signer -sign <file> [options] # Sign a file (explicit form)
407
641
  -o <path> # Output file path
408
642
  -hash-only # Hash-based signing (default)
409
643
  -file-upload # Upload entire file to server
@@ -439,37 +673,880 @@ signtool sign /sha1 <thumbprint> /fd sha256 /tr http://timestamp.digicert.com my
439
673
 
440
674
  **Examples:**
441
675
  ```bash
442
- # Direct signing with output path
676
+ # Direct signing with output path (two equivalent forms)
443
677
  signer myapp.exe -o myapp_signed.exe
678
+ signer -sign myapp.exe -o myapp_signed.exe
444
679
 
445
680
  # Upload entire file for signing
446
681
  signer myapp.exe -file-upload -o myapp_signed.exe
447
682
 
448
683
  # Hash-only signing with _signed suffix
449
684
  signer myapp.exe -save-signed
685
+ signer -sign myapp.exe -save-signed
450
686
  ```
451
687
 
452
688
  **Version Output:**
453
689
 
454
690
  ```
455
691
  # signer -version
456
- Certchip Signer v0.1.18
692
+ Certchip Signer v0.1.27
457
693
  Windows Key Storage Provider and Code Signing Tool
458
694
  Copyright (c) 2025 Certchip. All rights reserved.
459
695
 
460
696
  DLL Versions (Local):
461
- otpkey.dll: 0.1.18.0
462
- Certchip.dll: 0.1.18.0
697
+ otpkey.dll: 0.1.27.0
698
+ Certchip.dll: 0.1.27.0
463
699
 
464
700
  DLL Versions (System32):
465
- otpkey.dll: 0.1.18.0
466
- Certchip.dll: 0.1.18.0
701
+ otpkey.dll: 0.1.27.0
702
+ Certchip.dll: 0.1.27.0
467
703
  ```
468
704
 
469
705
  The version output helps diagnose DLL version mismatches between local and system-wide installations.
470
706
 
471
707
  ---
472
708
 
709
+ ### cert-dist (Certificate Distribution)
710
+
711
+ Download and manage certificates from a remote server. Supports various certificate types including SSL/TLS, device, and signing certificates.
712
+
713
+ **Supported Certificate Types:**
714
+ - SSL/TLS server certificates (including Let's Encrypt)
715
+ - Device certificates
716
+ - Code signing certificates
717
+ - Document signing certificates
718
+
719
+ ```bash
720
+ # Check certificate status
721
+ signercli -cert-dist status <domain> -api-key <key> -host <url>
722
+
723
+ # Check if renewal is needed
724
+ signercli -cert-dist check <domain> -api-key <key> -host <url>
725
+
726
+ # Download certificate
727
+ signercli -cert-dist download <domain> -api-key <key> -host <url> [-format <type>] [-o <dir>]
728
+
729
+ # Trigger certificate renewal
730
+ signercli -cert-dist renew <domain> -api-key <key> -host <url> [-force] [-wait|-no-wait]
731
+
732
+ # List available domains
733
+ signercli -cert-dist list -api-key <key> -host <url>
734
+
735
+ # Full sync (check + renew + download)
736
+ signercli -cert-dist sync <domain> -api-key <key> -host <url> [-reload-cmd <cmd>]
737
+
738
+ # Help
739
+ signercli -cert-dist help
740
+ ```
741
+
742
+ #### API Key Permission Modes
743
+
744
+ API keys support two permission modes:
745
+
746
+ | Mode | Description |
747
+ |------|-------------|
748
+ | `explicit` | Use only the permissions explicitly assigned to the API key |
749
+ | `inherited` | Inherit permissions from the linked user account's role and groups |
750
+
751
+ **Explicit Mode:**
752
+ - Permissions are set when creating the API key
753
+ - Ideal for applying the principle of least privilege
754
+ - Permissions don't change when user permissions change
755
+
756
+ **Inherited Mode:**
757
+ - Permissions come from the linked user account
758
+ - When user permissions change, API key permissions update automatically
759
+ - Simplifies management for users with multiple API keys
760
+
761
+ #### Extended Permissions
762
+
763
+ | Permission | Description | cert-dist | cert-api | letsencrypt |
764
+ |------------|-------------|-----------|----------|-------------|
765
+ | `read` | View certificate info | ✅ | ✅ | ✅ |
766
+ | `renew` | Renew certificates | ✅ | - | - |
767
+ | `download` | Download certificates | ✅ | ✅ | ✅ |
768
+ | `upload` | Upload certificates/keys | - | ✅ | - |
769
+ | `delete` | Delete certificates/keys | - | ✅ | - |
770
+ | `edit` | Edit metadata | - | ✅ | - |
771
+ | `csr` | Generate CSR | - | ✅ | - |
772
+ | `hsm` | HSM operations (protect/unprotect) | - | ✅ | - |
773
+ | `letsencrypt` | Let's Encrypt SSL certificate management | - | - | ✅ |
774
+ | `all` | All permissions | ✅ | ✅ | ✅ |
775
+
776
+ #### User Account Linking
777
+
778
+ Link a user account to an API key for:
779
+ - **Audit Trail**: API call logs include the linked user information
780
+ - **Permission Inheritance**: Use `inherited` mode to automatically apply user permissions
781
+ - **Resource Access**: Access certificates/keys owned by the linked user
782
+
783
+ **Format Options by Command:**
784
+
785
+ | Command | `-format json` | File Formats |
786
+ |---------|---------------|--------------|
787
+ | `status` | ✅ JSON output | - |
788
+ | `check` | ✅ JSON output | - |
789
+ | `list` | ✅ JSON output | - |
790
+ | `renew` | ✅ JSON output | - |
791
+ | `download` | ✅ JSON output | nginx, pem, letsencrypt, json (file) |
792
+ | `sync` | ✅ JSON output | nginx, pem, letsencrypt |
793
+
794
+ **Download File Formats:**
795
+
796
+ | Format | Description | Generated Files |
797
+ |--------|-------------|-----------------|
798
+ | `nginx` | Nginx format (default) | `<domain>.crt`, `<domain>.key` |
799
+ | `pem` | Standard PEM format | `<domain>.fullchain.pem`, `<domain>.privkey.pem` |
800
+ | `letsencrypt` | Let's Encrypt style | `<domain>/cert.pem`, `<domain>/chain.pem`, `<domain>/fullchain.pem`, `<domain>/privkey.pem` |
801
+ | `json` | JSON format | `<domain>.json` |
802
+
803
+ **Examples:**
804
+
805
+ ```bash
806
+ # Download in Nginx format (default)
807
+ signercli -cert-dist download example.com -api-key cdk_xxx -host https://signer.example.com:7443
808
+
809
+ # Download in Let's Encrypt style
810
+ signercli -cert-dist download example.com -api-key cdk_xxx -host https://signer.example.com:7443 \
811
+ -format letsencrypt -o /etc/letsencrypt/live
812
+
813
+ # Automation: renew if needed, download, and reload Nginx
814
+ signercli -cert-dist sync example.com -api-key cdk_xxx -host https://signer.example.com:7443 \
815
+ -o /etc/nginx/ssl -reload-cmd "systemctl reload nginx"
816
+
817
+ # Get status in JSON format (for scripting)
818
+ signercli -cert-dist status example.com -api-key cdk_xxx -host https://signer.example.com:7443 -format json
819
+ ```
820
+
821
+ **Exit Codes:**
822
+ - `0`: Success (for check command: no renewal needed)
823
+ - `1`: Error
824
+ - `2`: Renewal needed (check command only)
825
+
826
+ > **Detailed usage:** See [cert-dist-guide.md](docs/cert-dist-guide.md)
827
+
828
+ ---
829
+
830
+ ### cert-api (Certificate Management API)
831
+
832
+ General certificate and key management commands. Uses the same API key as cert-dist.
833
+
834
+ **Three Command Systems:**
835
+
836
+ | Commands | Purpose | API Endpoint |
837
+ |----------|---------|--------------|
838
+ | `-cert-dist` | Let's Encrypt certificate distribution/renewal | `/api/cert-distribution` |
839
+ | `-cert`, `-privkey`, `-pubkey`, `-csr` | General certificate/key management | `/api/cert-api` |
840
+ | `-letsencrypt` | Let's Encrypt SSL certificate direct management | `/api/cert-api/letsencrypt` |
841
+
842
+ #### API Key Authentication (-api-key)
843
+
844
+ API keys allow direct API access without SSH key-based login.
845
+
846
+ **What is an API Key?**
847
+
848
+ - A unique authentication token issued by the server (format: `cdk_` prefix + 64-char hex)
849
+ - Alternative to SSH key-based challenge-response login
850
+ - Ideal for CI/CD pipelines, automation scripts, and programmatic access
851
+
852
+ **API Key Format:**
853
+ ```
854
+ cdk_e2f369e7c85bfa7835d375f6b088f15dac2c2d8ebeb0815c392a6d6b34ee916f
855
+ ```
856
+
857
+ **Usage Methods:**
858
+
859
+ ```bash
860
+ # Method 1: Specify directly on command line
861
+ signercli -cert list -api-key cdk_xxx -host https://server:7443
862
+
863
+ # Method 2: Store in profile (recommended)
864
+ signercli -config set default -host https://server:7443 -api-key cdk_xxx
865
+ signercli -cert list # api-key and host auto-applied
866
+
867
+ # Method 3: Use named profile
868
+ signercli -config set production -host https://prod:7443 -api-key cdk_prod_key
869
+ signercli -cert list -profile production
870
+ ```
871
+
872
+ **Supported Commands:**
873
+
874
+ | Command | Description |
875
+ |---------|-------------|
876
+ | `-cert` | Certificate management (list, upload, download, delete) |
877
+ | `-cert-dist` | Let's Encrypt certificate distribution/renewal |
878
+ | `-letsencrypt` | Let's Encrypt SSL certificate direct management |
879
+ | `-privkey` | Private key management |
880
+ | `-pubkey` | Public key management |
881
+ | `-csr` | Certificate Signing Request generation |
882
+
883
+ **Login Authentication vs API Key Authentication:**
884
+
885
+ | Aspect | Login Authentication | API Key Authentication |
886
+ |--------|---------------------|------------------------|
887
+ | Method | SSH key challenge-response | Direct API key transmission |
888
+ | Token Expiry | Yes (default 24h) | Depends on server config |
889
+ | Commands | All commands after `-login` | `-cert`, `-cert-dist`, etc. only |
890
+ | Best For | Interactive use, code signing | Automation, CI/CD, scripts |
891
+
892
+ **Security Notes:**
893
+
894
+ - Protect API keys like passwords
895
+ - Set config file permissions: `chmod 600 ~/.signer/config`
896
+ - Don't hardcode API keys in scripts
897
+ - Use secret managers in CI/CD environments
898
+
899
+ #### Certificate Commands (-cert)
900
+
901
+ ```bash
902
+ # List certificates
903
+ signercli -cert list -api-key <key> [-host <url>]
904
+
905
+ # Get certificate details
906
+ signercli -cert get <id> -api-key <key>
907
+
908
+ # Upload certificate (default: DB storage)
909
+ signercli -cert upload <file> -name "Certificate Name" -api-key <key>
910
+
911
+ # Upload certificate to Software HSM (no PIN required)
912
+ signercli -cert upload <file> -name "My Cert" -storage SW_HSM -api-key <key>
913
+
914
+ # Upload certificate to Hardware HSM (slot and PIN required)
915
+ signercli -cert upload <file> -name "My Cert" -storage HW_HSM -hsm-slot 0 -hsm-pin <pin> -api-key <key>
916
+
917
+ # Download certificate (PEM/DER)
918
+ signercli -cert download <id> -format pem -o <dir> -api-key <key>
919
+
920
+ # Download certificate (PFX)
921
+ signercli -cert download-pfx <id> -password <pwd> -o <dir> -api-key <key>
922
+
923
+ # Update certificate metadata
924
+ signercli -cert update <id> -name "New Name" -desc "Description" -api-key <key>
925
+
926
+ # Delete certificate
927
+ signercli -cert delete <id> -api-key <key>
928
+
929
+ # Delete certificate with related private key
930
+ signercli -cert delete <id> -delete-related -api-key <key>
931
+
932
+ # Delete HSM certificate (PIN required)
933
+ signercli -cert delete <id> -hsm-pin <pin> -api-key <key>
934
+ ```
935
+
936
+ **Storage Types:**
937
+
938
+ | Type | Description | Requirements |
939
+ |------|-------------|--------------|
940
+ | `DB` | Database storage (default) | None |
941
+ | `SW_HSM` | Software HSM (encrypted storage) | None |
942
+ | `HW_HSM` | Hardware HSM (PKCS#11 device) | `-hsm-slot`, `-hsm-pin` |
943
+
944
+ **Using Profile with API Key:**
945
+
946
+ You can store the API key in a profile to avoid specifying it on every command:
947
+
948
+ ```bash
949
+ # Configure profile with API key (one-time setup)
950
+ signercli -config set default -host https://server:7443 -api-key cdk_xxx
951
+
952
+ # Now use -cert commands without -api-key and -host
953
+ signercli -cert list
954
+ signercli -cert get <id>
955
+ signercli -cert upload cert.pem -name "My Cert"
956
+
957
+ # Or use a named profile
958
+ signercli -config set myserver -host https://server:7443 -api-key cdk_xxx
959
+ signercli -cert list -profile myserver
960
+ ```
961
+
962
+ #### Creating Test Certificates (OpenSSL)
963
+
964
+ For testing `-cert upload` and other certificate commands, you can create test certificates using OpenSSL.
965
+
966
+ ##### Linux / macOS
967
+
968
+ **1. Self-Signed Certificate (Simple)**
969
+
970
+ ```bash
971
+ # Generate RSA key + certificate in one command
972
+ openssl req -x509 -newkey rsa:2048 -keyout test_key.pem -out test_cert.pem -days 365 -nodes \
973
+ -subj "/C=KR/ST=Seoul/L=Gangnam/O=TestOrg/OU=Dev/CN=Test Certificate"
974
+
975
+ # Verify certificate
976
+ openssl x509 -in test_cert.pem -text -noout
977
+ ```
978
+
979
+ **2. Code Signing Certificate**
980
+
981
+ ```bash
982
+ # Generate private key
983
+ openssl genrsa -out codesign_key.pem 2048
984
+
985
+ # Generate certificate with code signing extensions
986
+ openssl req -new -x509 -key codesign_key.pem -out codesign_cert.pem -days 365 \
987
+ -subj "/C=KR/O=MyCompany/CN=Code Signing Certificate" \
988
+ -addext "keyUsage=digitalSignature" \
989
+ -addext "extendedKeyUsage=codeSigning"
990
+ ```
991
+
992
+ **3. PFX/P12 Bundle (Key + Certificate)**
993
+
994
+ ```bash
995
+ # Create PFX from PEM files
996
+ openssl pkcs12 -export -out test_bundle.pfx \
997
+ -inkey test_key.pem -in test_cert.pem \
998
+ -password pass:test1234
999
+ ```
1000
+
1001
+ **4. DER Format Certificate**
1002
+
1003
+ ```bash
1004
+ # Convert PEM to DER
1005
+ openssl x509 -in test_cert.pem -outform DER -out test_cert.der
1006
+ ```
1007
+
1008
+ **5. Complete Test Script (Linux/macOS)**
1009
+
1010
+ ```bash
1011
+ #!/bin/bash
1012
+ # create_test_certs.sh
1013
+ mkdir -p test_certs && cd test_certs
1014
+
1015
+ # Basic test certificate
1016
+ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes \
1017
+ -subj "/CN=Test Certificate"
1018
+
1019
+ # Code signing certificate
1020
+ openssl req -x509 -newkey rsa:4096 -keyout codesign_key.pem -out codesign_cert.pem -days 365 -nodes \
1021
+ -subj "/C=KR/O=TestOrg/CN=Code Signing Test" \
1022
+ -addext "keyUsage=digitalSignature" \
1023
+ -addext "extendedKeyUsage=codeSigning"
1024
+
1025
+ # PFX bundle
1026
+ openssl pkcs12 -export -out bundle.pfx -inkey key.pem -in cert.pem -password pass:test1234
1027
+
1028
+ # DER format
1029
+ openssl x509 -in cert.pem -outform DER -out cert.der
1030
+
1031
+ echo "Created files:"
1032
+ ls -la
1033
+ ```
1034
+
1035
+ ##### Windows (PowerShell / CMD)
1036
+
1037
+ > **Note:** Windows requires OpenSSL to be installed. You can install it via:
1038
+ > - [Git for Windows](https://git-scm.com/) (includes OpenSSL in Git Bash)
1039
+ > - [MSYS2](https://www.msys2.org/) (`pacman -S openssl`)
1040
+ > - [OpenSSL for Windows](https://slproweb.com/products/Win32OpenSSL.html)
1041
+
1042
+ **1. Self-Signed Certificate (PowerShell)**
1043
+
1044
+ ```powershell
1045
+ # Using Git Bash OpenSSL (adjust path as needed)
1046
+ & "C:\Program Files\Git\usr\bin\openssl.exe" req -x509 -newkey rsa:2048 `
1047
+ -keyout test_key.pem -out test_cert.pem -days 365 -nodes `
1048
+ -subj "/C=KR/ST=Seoul/L=Gangnam/O=TestOrg/OU=Dev/CN=Test Certificate"
1049
+
1050
+ # Verify certificate
1051
+ & "C:\Program Files\Git\usr\bin\openssl.exe" x509 -in test_cert.pem -text -noout
1052
+ ```
1053
+
1054
+ **2. Using Windows Native (certreq + PowerShell)**
1055
+
1056
+ ```powershell
1057
+ # Create self-signed certificate using PowerShell
1058
+ $cert = New-SelfSignedCertificate -DnsName "Test Certificate" `
1059
+ -CertStoreLocation "Cert:\CurrentUser\My" `
1060
+ -KeyUsage DigitalSignature `
1061
+ -Type CodeSigningCert `
1062
+ -NotAfter (Get-Date).AddYears(1)
1063
+
1064
+ # Export to PFX
1065
+ $password = ConvertTo-SecureString -String "test1234" -Force -AsPlainText
1066
+ Export-PfxCertificate -Cert $cert -FilePath "test_bundle.pfx" -Password $password
1067
+
1068
+ # Export certificate only (CER/DER format)
1069
+ Export-Certificate -Cert $cert -FilePath "test_cert.cer" -Type CERT
1070
+
1071
+ # Show certificate info
1072
+ $cert | Format-List Subject, Thumbprint, NotAfter
1073
+ ```
1074
+
1075
+ **3. Complete Test Script (Windows CMD with Git Bash OpenSSL)**
1076
+
1077
+ ```batch
1078
+ @echo off
1079
+ REM create_test_certs.bat
1080
+ REM Requires OpenSSL (Git Bash or standalone)
1081
+
1082
+ set OPENSSL="C:\Program Files\Git\usr\bin\openssl.exe"
1083
+ mkdir test_certs 2>nul
1084
+ cd test_certs
1085
+
1086
+ REM Basic test certificate
1087
+ %OPENSSL% req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=Test Certificate"
1088
+
1089
+ REM Code signing certificate
1090
+ %OPENSSL% req -x509 -newkey rsa:4096 -keyout codesign_key.pem -out codesign_cert.pem -days 365 -nodes -subj "/C=KR/O=TestOrg/CN=Code Signing Test" -addext "keyUsage=digitalSignature" -addext "extendedKeyUsage=codeSigning"
1091
+
1092
+ REM PFX bundle
1093
+ %OPENSSL% pkcs12 -export -out bundle.pfx -inkey key.pem -in cert.pem -password pass:test1234
1094
+
1095
+ REM DER format
1096
+ %OPENSSL% x509 -in cert.pem -outform DER -out cert.der
1097
+
1098
+ echo Created files:
1099
+ dir /b
1100
+ ```
1101
+
1102
+ **4. Complete Test Script (Windows PowerShell Native)**
1103
+
1104
+ ```powershell
1105
+ # create_test_certs.ps1
1106
+ # Uses Windows native certificate APIs (no OpenSSL required)
1107
+
1108
+ $testDir = "test_certs"
1109
+ New-Item -ItemType Directory -Force -Path $testDir | Out-Null
1110
+ Set-Location $testDir
1111
+
1112
+ $password = ConvertTo-SecureString -String "test1234" -Force -AsPlainText
1113
+
1114
+ # Basic test certificate
1115
+ $basicCert = New-SelfSignedCertificate -DnsName "Test Certificate" `
1116
+ -CertStoreLocation "Cert:\CurrentUser\My" `
1117
+ -NotAfter (Get-Date).AddYears(1)
1118
+
1119
+ Export-PfxCertificate -Cert $basicCert -FilePath "bundle.pfx" -Password $password
1120
+ Export-Certificate -Cert $basicCert -FilePath "cert.cer" -Type CERT
1121
+ Export-Certificate -Cert $basicCert -FilePath "cert.der" -Type CERT
1122
+
1123
+ # Code signing certificate
1124
+ $codeCert = New-SelfSignedCertificate -Subject "CN=Code Signing Test, O=TestOrg, C=KR" `
1125
+ -CertStoreLocation "Cert:\CurrentUser\My" `
1126
+ -KeyUsage DigitalSignature `
1127
+ -Type CodeSigningCert `
1128
+ -NotAfter (Get-Date).AddYears(1)
1129
+
1130
+ Export-PfxCertificate -Cert $codeCert -FilePath "codesign_bundle.pfx" -Password $password
1131
+
1132
+ # Clean up from certificate store (optional)
1133
+ # Remove-Item -Path $basicCert.PSPath
1134
+ # Remove-Item -Path $codeCert.PSPath
1135
+
1136
+ Write-Host "Created files:"
1137
+ Get-ChildItem
1138
+ ```
1139
+
1140
+ ##### Upload Test Commands (All Platforms)
1141
+
1142
+ ```bash
1143
+ # Upload PEM certificate
1144
+ signercli -cert upload test_certs/cert.pem -name "Test Cert" -api-key <key> -host https://server:7443
1145
+
1146
+ # Upload PFX bundle
1147
+ signercli -cert upload test_certs/bundle.pfx -name "PFX Bundle" -api-key <key> -host https://server:7443
1148
+
1149
+ # Upload DER certificate
1150
+ signercli -cert upload test_certs/cert.der -name "DER Cert" -api-key <key> -host https://server:7443
1151
+ ```
1152
+
1153
+ ##### File Format Summary
1154
+
1155
+ | Format | Extension | Description | Created By |
1156
+ |--------|-----------|-------------|------------|
1157
+ | PEM | `.pem`, `.crt` | Base64 encoded, text format | OpenSSL |
1158
+ | DER | `.der`, `.cer` | Binary format | OpenSSL, Windows |
1159
+ | PFX/P12 | `.pfx`, `.p12` | Key + Certificate bundle | OpenSSL, Windows |
1160
+
1161
+ #### Private Key Commands (-privkey)
1162
+
1163
+ ```bash
1164
+ # List private keys
1165
+ signercli -privkey list -api-key <key>
1166
+
1167
+ # Get private key details
1168
+ signercli -privkey get <id> -api-key <key>
1169
+
1170
+ # Upload private key (default: DB storage)
1171
+ signercli -privkey upload <file> -api-key <key>
1172
+
1173
+ # Upload encrypted private key
1174
+ signercli -privkey upload <file> -password <pwd> -api-key <key>
1175
+
1176
+ # Upload private key to Software HSM
1177
+ signercli -privkey upload <file> -storage SW_HSM -api-key <key>
1178
+
1179
+ # Upload private key to Hardware HSM
1180
+ signercli -privkey upload <file> -storage HW_HSM -hsm-slot 0 -hsm-pin <pin> -api-key <key>
1181
+
1182
+ # Delete private key
1183
+ signercli -privkey delete <id> -api-key <key>
1184
+
1185
+ # Delete HSM private key (PIN required)
1186
+ signercli -privkey delete <id> -hsm-pin <pin> -api-key <key>
1187
+
1188
+ # Link private key to certificate
1189
+ signercli -privkey link <key-id> <cert-id> -api-key <key>
1190
+
1191
+ # Unlink private key from certificate
1192
+ signercli -privkey unlink <key-id> -api-key <key>
1193
+ ```
1194
+
1195
+ #### Public Key Commands (-pubkey)
1196
+
1197
+ ```bash
1198
+ # List public keys
1199
+ signercli -pubkey list -api-key <key>
1200
+
1201
+ # Extract public key from certificate
1202
+ signercli -pubkey extract <cert-id> -api-key <key>
1203
+
1204
+ # Extract with custom name
1205
+ signercli -pubkey extract <cert-id> -name "Public Key Name" -api-key <key>
1206
+ ```
1207
+
1208
+ #### CSR Commands (-csr)
1209
+
1210
+ ```bash
1211
+ # Generate CSR
1212
+ signercli -csr generate -cn <common-name> -api-key <key>
1213
+
1214
+ # Generate CSR with full subject
1215
+ signercli -csr generate \
1216
+ -cn example.com \
1217
+ -c KR \
1218
+ -st Seoul \
1219
+ -l Gangnam \
1220
+ -org "Example Corp" \
1221
+ -ou "IT Department" \
1222
+ -email admin@example.com \
1223
+ -keysize 4096 \
1224
+ -api-key <key>
1225
+
1226
+ # Save CSR to file
1227
+ signercli -csr generate -cn example.com -o <dir> -api-key <key>
1228
+ ```
1229
+
1230
+ #### Let's Encrypt Commands (-letsencrypt)
1231
+
1232
+ Direct management of Let's Encrypt SSL certificates stored on the server. Requires `SYSTEM_ADMIN` role or explicit `letsencrypt` permission.
1233
+
1234
+ > **Note:** This command directly accesses Let's Encrypt certificates stored on the server, while `-cert-dist` is for distributing certificates to external servers/devices.
1235
+
1236
+ **Authentication:**
1237
+
1238
+ You can authenticate using either method:
1239
+ 1. **Login first** - Use JWT token from login session (no API key needed)
1240
+ 2. **API key** - Provide API key directly
1241
+
1242
+ ```bash
1243
+ # Method 1: Login first, then use commands without API key
1244
+ signercli -login https://signer.example.com:7443 admin
1245
+ signercli -letsencrypt list
1246
+
1247
+ # Method 2: Use API key directly
1248
+ signercli -letsencrypt list -api-key <key>
1249
+ ```
1250
+
1251
+ **Access Control:**
1252
+
1253
+ | Authentication | Condition | Access |
1254
+ |---------------|-----------|--------|
1255
+ | JWT | role = `SYSTEM_ADMIN` | ✅ Allowed |
1256
+ | JWT | role = `OPERATION_MANAGER` or `USER` | ❌ Denied |
1257
+ | API Key (inherited) | linkedUserRole = `SYSTEM_ADMIN` | ✅ Allowed |
1258
+ | API Key (inherited) | linkedUserRole ≠ `SYSTEM_ADMIN` | ❌ Denied |
1259
+ | API Key (explicit) | permissions includes `letsencrypt` or `all` | ✅ Allowed |
1260
+ | API Key (explicit) | permissions excludes `letsencrypt` | ❌ Denied |
1261
+
1262
+ **Commands:**
1263
+
1264
+ | Command | Description |
1265
+ |---------|-------------|
1266
+ | `list` | List Let's Encrypt certificates |
1267
+ | `get <id>` | Get certificate details |
1268
+ | `download <id>` | Download certificate files |
1269
+ | `request` | Request new certificate (HTTP-01 or DNS-01) |
1270
+ | `dns-request` | Start DNS-01 challenge (outputs challenge ID) |
1271
+ | `dns-request -interactive` | DNS-01 challenge (interactive mode) |
1272
+ | `dns-complete` | Complete DNS-01 challenge |
1273
+ | `dns-providers` | List available DNS providers |
1274
+ | `renew <id>` | Renew certificate (automatic) |
1275
+ | `renew-dns <id>` | Start manual DNS-01 renewal (outputs challenge ID) |
1276
+ | `renew-dns <id> -interactive` | Manual DNS-01 renewal (interactive mode) |
1277
+ | `delete <id>` | Delete certificate |
1278
+ | `auto-renewal <id>` | Enable/disable auto-renewal |
1279
+ | `activate <id>` | Set certificate as Signer server's SSL certificate |
1280
+
1281
+ **List/Get/Download Options:**
1282
+
1283
+ | Option | Description | Default |
1284
+ |--------|-------------|---------|
1285
+ | `-api-key <key>` | API key (optional if logged in) | - |
1286
+ | `-host <url>` | Server URL | `https://localhost:7443` |
1287
+ | `-format <type>` | Output format: text, json | text |
1288
+ | `-env <environment>` | Filter by environment: staging, production | - |
1289
+ | `-domain <pattern>` | Filter by domain (supports `*` wildcard, e.g., `*.example.com`) | - |
1290
+ | `-type <type>` | Download type: cert, chain, fullchain, key, all | fullchain |
1291
+ | `-o <dir>` | Output directory for downloads | Current directory |
1292
+ | `-naming <style>` | Filename style: `letsencrypt` or `domain` | letsencrypt |
1293
+
1294
+ **Request Options:**
1295
+
1296
+ | Option | Description | Default |
1297
+ |--------|-------------|---------|
1298
+ | `-domain <domain>` | Domain name for the certificate (required) | - |
1299
+ | `-email <email>` | Contact email for Let's Encrypt account (required) | - |
1300
+ | `-agree-tos` | Agree to Let's Encrypt Terms of Service (required) | - |
1301
+ | `-env <environment>` | Environment: staging, production | staging |
1302
+ | `-key-type <type>` | Key type: RSA, ECDSA | RSA |
1303
+ | `-keysize <bits>` | Key size: 2048, 4096, etc. | 2048 |
1304
+ | `-san <domains>` | Subject Alternative Names (comma-separated) | - |
1305
+ | `-challenge <type>` | Challenge type: http-01, dns-01 | http-01 |
1306
+ | `-dns-provider <mode>` | DNS provider mode: auto, selected (for dns-01) | auto |
1307
+ | `-provider-id <id>` | DNS Provider ID (auto-sets -dns-provider to 'selected') | - |
1308
+
1309
+ **DNS-01 Challenge Options (for dns-request/dns-complete):**
1310
+
1311
+ | Option | Description | Default |
1312
+ |--------|-------------|---------|
1313
+ | `-interactive, -i` | Interactive mode: wait for Enter, then complete (dns-request) | - |
1314
+ | `-challenge-id <id>` | Challenge ID from dns-request (for dns-complete) | - |
1315
+
1316
+ **Auto-Renewal Options:**
1317
+
1318
+ | Option | Description |
1319
+ |--------|-------------|
1320
+ | `-enable` | Enable auto-renewal |
1321
+ | `-disable` | Disable auto-renewal |
1322
+
1323
+ ```bash
1324
+ # List Let's Encrypt certificates
1325
+ signercli -letsencrypt list # Using login token
1326
+ signercli -letsencrypt list -api-key <key> # Using API key
1327
+
1328
+ # Filter by environment
1329
+ signercli -letsencrypt list -env production
1330
+ signercli -letsencrypt list -env staging
1331
+
1332
+ # Filter by domain (partial match or wildcard)
1333
+ signercli -letsencrypt list -domain example.com
1334
+ signercli -letsencrypt list -domain api # Matches api.example.com, etc.
1335
+ signercli -letsencrypt list -domain "*.example.com" # Matches wildcard certificates
1336
+
1337
+ # Combine filters
1338
+ signercli -letsencrypt list -env production -domain example.com
1339
+
1340
+ # Get certificate details
1341
+ signercli -letsencrypt get <id>
1342
+
1343
+ # Download certificate (fullchain by default)
1344
+ signercli -letsencrypt download <id>
1345
+
1346
+ # Download specific type
1347
+ signercli -letsencrypt download <id> -type cert # Certificate only
1348
+ signercli -letsencrypt download <id> -type chain # Chain only
1349
+ signercli -letsencrypt download <id> -type fullchain # Full chain (default)
1350
+ signercli -letsencrypt download <id> -type key # Private key
1351
+ signercli -letsencrypt download <id> -type all # All files
1352
+
1353
+ # Download to specific directory (default: cert.pem, privkey.pem, etc.)
1354
+ signercli -letsencrypt download <id> -type all -o /etc/ssl
1355
+
1356
+ # Download with domain-based naming (<domain>.crt, <domain>.key, etc.)
1357
+ signercli -letsencrypt download <id> -type all -o /etc/ssl -naming domain
1358
+ ```
1359
+
1360
+ **Download Types:**
1361
+
1362
+ | Type | Description | Let's Encrypt (default) | Domain Style |
1363
+ |------|-------------|-------------------------|--------------|
1364
+ | `cert` | Certificate only | `cert.pem` | `<domain>.crt` |
1365
+ | `chain` | Intermediate chain | `chain.pem` | `<domain>.chain.crt` |
1366
+ | `fullchain` | Certificate + chain (default) | `fullchain.pem` | `<domain>.fullchain.crt` |
1367
+ | `key` | Private key | `privkey.pem` | `<domain>.key` |
1368
+ | `all` | All files | All above files | All above files |
1369
+
1370
+ **Output Options:**
1371
+
1372
+ ```bash
1373
+ # JSON format output
1374
+ signercli -letsencrypt list -format json
1375
+
1376
+ # Table format output
1377
+ signercli -letsencrypt list -format table
1378
+ ```
1379
+
1380
+ **Examples:**
1381
+
1382
+ ```bash
1383
+ # Login first (recommended for interactive use)
1384
+ signercli -login https://signer.example.com:7443 admin
1385
+
1386
+ # List all production certificates
1387
+ signercli -letsencrypt list -env production
1388
+
1389
+ # List certificates for a specific domain
1390
+ signercli -letsencrypt list -domain example.com
1391
+
1392
+ # Get specific certificate details
1393
+ signercli -letsencrypt get 6789abcd
1394
+
1395
+ # Download fullchain to /etc/nginx/ssl
1396
+ signercli -letsencrypt download 6789abcd -type fullchain -o /etc/nginx/ssl
1397
+
1398
+ # Download all files for Nginx configuration
1399
+ signercli -letsencrypt download 6789abcd -type all -o /etc/nginx/ssl
1400
+
1401
+ # Using API key (for automation/scripts)
1402
+ signercli -letsencrypt list -env production -api-key cdk_xxx -host https://signer.example.com:7443
1403
+
1404
+ # --- HTTP-01 Challenge (default) ---
1405
+ # Request new certificate (staging environment - for testing)
1406
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos
1407
+
1408
+ # Request production certificate
1409
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos -env production
1410
+
1411
+ # Request certificate with Subject Alternative Names
1412
+ signercli -letsencrypt request -domain example.com -san "www.example.com,api.example.com" -email admin@example.com -agree-tos
1413
+
1414
+ # --- DNS-01 Challenge with DNS Provider ---
1415
+ # Auto-detect DNS provider for domain (default when using dns-01)
1416
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos \
1417
+ -challenge dns-01
1418
+
1419
+ # Use specific DNS provider (provider-id auto-sets mode to 'selected')
1420
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos \
1421
+ -challenge dns-01 -provider-id 6789abc
1422
+
1423
+ # Wildcard certificate with DNS provider (auto mode)
1424
+ signercli -letsencrypt request -domain "*.example.com" -email admin@example.com -agree-tos \
1425
+ -challenge dns-01 -env production
1426
+
1427
+ # --- DNS-01 Challenge (Manual - Two-step process) ---
1428
+ # Step 1: Start DNS challenge (get TXT records to add)
1429
+ signercli -letsencrypt dns-request -domain example.com -email admin@example.com -agree-tos
1430
+ # Step 2: After adding TXT records to DNS, complete the challenge
1431
+ signercli -letsencrypt dns-complete -challenge-id <challenge-id>
1432
+
1433
+ # --- DNS-01 Challenge (Manual - Interactive mode) ---
1434
+ # Single command that waits for Enter and completes automatically
1435
+ signercli -letsencrypt dns-request -domain example.com -email admin@example.com -agree-tos -interactive
1436
+
1437
+ # --- DNS Provider Management ---
1438
+ # List available DNS providers
1439
+ signercli -letsencrypt dns-providers
1440
+
1441
+ # --- Certificate Renewal ---
1442
+ # Renew certificate (automatic - for HTTP-01 or auto DNS-01)
1443
+ signercli -letsencrypt renew 6789abcd
1444
+
1445
+ # --- Manual DNS-01 Renewal (Two-step process) ---
1446
+ # Step 1: Start renewal (get DNS records and challenge ID)
1447
+ signercli -letsencrypt renew-dns 6789abcd
1448
+ # Step 2: After adding TXT records to DNS, complete the renewal
1449
+ signercli -letsencrypt dns-complete -challenge-id <challenge-id>
1450
+
1451
+ # --- Manual DNS-01 Renewal (Interactive mode) ---
1452
+ # Single command that waits for Enter and completes automatically
1453
+ signercli -letsencrypt renew-dns 6789abcd -interactive
1454
+
1455
+ # Delete certificate
1456
+ signercli -letsencrypt delete 6789abcd
1457
+
1458
+ # Enable auto-renewal
1459
+ signercli -letsencrypt auto-renewal 6789abcd -enable
1460
+
1461
+ # Disable auto-renewal
1462
+ signercli -letsencrypt auto-renewal 6789abcd -disable
1463
+
1464
+ # --- Activating Server SSL Certificate ---
1465
+ # Activate certificate for HTTPS server
1466
+ signercli -letsencrypt activate 6789abcd
1467
+ ```
1468
+
1469
+ > **Important: About the 'activate' command**
1470
+ >
1471
+ > The `activate` command sets the specified Let's Encrypt certificate as the **Signer server's own SSL certificate**.
1472
+ > This means that after activation:
1473
+ > - The Signer server will use this certificate for HTTPS connections
1474
+ > - Clients connecting to the Signer server will see this certificate
1475
+ >
1476
+ > **This does NOT mean:**
1477
+ > - ❌ Enabling or disabling the certificate itself
1478
+ > - ❌ Making the certificate "active" vs "inactive"
1479
+ > - ❌ Publishing or unpublishing the certificate
1480
+ >
1481
+ > All issued certificates remain valid and usable regardless of activation status.
1482
+ > The `activate` command is only for configuring which certificate the Signer server uses for its own HTTPS endpoint.
1483
+
1484
+ **Certificate Issuance/Renewal Notes:**
1485
+
1486
+ | Scenario | Command | Description |
1487
+ |----------|---------|-------------|
1488
+ | **New Certificate** | | |
1489
+ | DNS-01 manual (scripted) | `dns-request` + `dns-complete` | Two-step process for automation |
1490
+ | DNS-01 manual (interactive) | `dns-request -interactive` | Single command with Enter prompt |
1491
+ | **Certificate Renewal** | | |
1492
+ | HTTP-01 challenge | `renew` | Automatic renewal via HTTP validation |
1493
+ | DNS-01 with provider | `renew` | Automatic renewal via DNS API |
1494
+ | DNS-01 manual (scripted) | `renew-dns` + `dns-complete` | Two-step process for automation |
1495
+ | DNS-01 manual (interactive) | `renew-dns -interactive` | Single command with Enter prompt |
1496
+ | Renewal failed | `renew-dns` | Use when `renew` shows "Manual DNS renewal required" |
1497
+
1498
+ **Challenge Types:**
1499
+
1500
+ | Challenge | Description | Use Case |
1501
+ |-----------|-------------|----------|
1502
+ | HTTP-01 | Validates via HTTP on port 80 | Standard domains, internet-accessible servers |
1503
+ | DNS-01 | Validates via DNS TXT record | Wildcard certs, internal servers, port 80 blocked |
1504
+
1505
+ **DNS Provider Modes:**
1506
+
1507
+ | Mode | Description |
1508
+ |------|-------------|
1509
+ | `auto` | Auto-detect DNS provider based on domain (default for dns-01) |
1510
+ | `selected` | Use specific provider (auto-set when `-provider-id` is provided) |
1511
+ | Manual | Use `dns-request`/`dns-complete` commands |
1512
+
1513
+ > **Note:** When using `-challenge dns-01`:
1514
+ > - If `-dns-provider` is not specified, it defaults to `auto`
1515
+ > - If `-provider-id` is specified, `-dns-provider` is automatically set to `selected`
1516
+
1517
+ **Supported DNS Providers:**
1518
+ - Cloudflare
1519
+ - AWS Route 53
1520
+ - GoDaddy
1521
+ - Custom Script
1522
+
1523
+ **Notes:**
1524
+ - HTTP-01 challenge (default) requires port 80 to be accessible from the internet.
1525
+ - DNS-01 challenge is required for wildcard certificates (e.g., `*.example.com`).
1526
+ - DNS-01 with DNS provider enables full automation including auto-renewal.
1527
+ - Production environment has rate limits. Test with staging first.
1528
+ - SYSTEM_ADMIN role is required for all Let's Encrypt operations.
1529
+
1530
+ #### cert-api Common Options
1531
+
1532
+ | Option | Description | Default |
1533
+ |--------|-------------|---------|
1534
+ | `-api-key <key>` | API key (optional for `-letsencrypt` if logged in) | - |
1535
+ | `-host <url>` | Signer Server URL | `https://localhost:7443` |
1536
+ | `-profile <name>` | Use settings from config profile | default |
1537
+ | `-format <type>` | Output format (json, pem, der) | text |
1538
+ | `-o <dir>` | Output directory | Current directory |
1539
+ | `-name <name>` | Name for upload/create | Filename |
1540
+ | `-desc <text>` | Description | - |
1541
+ | `-password <pwd>` | PFX/encrypted key password | - |
1542
+ | `-storage <type>` | Storage type: DB, SW_HSM, HW_HSM | DB |
1543
+ | `-hsm-slot <id>` | HSM slot ID (required for HW_HSM) | - |
1544
+ | `-hsm-pin <pin>` | HSM PIN (for HSM objects) | - |
1545
+ | `-include-chain` | Include certificate chain | - |
1546
+ | `-delete-related` | Delete related private key | - |
1547
+
1548
+ ---
1549
+
473
1550
  ### DLL System Installation (Windows)
474
1551
 
475
1552
  For system-wide DLL access (required for signtool integration), install DLLs to System32:
@@ -562,11 +1639,22 @@ signercli -config set automation \
562
1639
  -host https://signer.example.com \
563
1640
  -output-format json
564
1641
 
1642
+ # Create a profile with API key (no login required)
1643
+ signercli -config set cert-api \
1644
+ -host https://signer.example.com:7443 \
1645
+ -api-key cdk_e2f369e7c85bfa7835d375f6b088f15dac2c2d8ebeb0815c392a6d6b34ee916f
1646
+
565
1647
  # Use the profile
566
1648
  signercli -login -profile production
567
- signercli myapp.exe -profile production
1649
+ signercli myapp.exe -profile production # Implicit form
1650
+ signercli -sign myapp.exe -profile production # Explicit form (same result)
568
1651
  signercli document.pdf -profile pdf-signing
569
1652
  signercli -verify myapp.exe -profile automation # Outputs JSON automatically
1653
+
1654
+ # Use API key profile (no login required)
1655
+ signercli -cert list -profile cert-api
1656
+ signercli -cert get <id> -profile cert-api
1657
+ signercli -cert upload cert.pem -profile cert-api
570
1658
  ```
571
1659
 
572
1660
  ## Supported File Types
@@ -589,11 +1677,13 @@ signercli -verify myapp.exe -profile automation # Outputs JSON automatically
589
1677
  └── bin/
590
1678
  ├── signercli.js # Cross-platform wrapper
591
1679
  ├── signer.js # Windows KSP wrapper
1680
+ ├── linux-x64/
1681
+ │ └── signercli # Fully static binary (no dynamic dependencies)
592
1682
  └── win32-x64/
593
- ├── signercli.exe # 9.3 MB (static build)
594
- ├── signer.exe # 420 KB (static build)
595
- ├── otpkey.dll # 6.2 MB (static linked)
596
- └── Certchip.dll # 700 KB (KSP provider)
1683
+ ├── signercli.exe # Static build
1684
+ ├── signer.exe # Static build
1685
+ ├── otpkey.dll # Static linked
1686
+ └── Certchip.dll # KSP provider
597
1687
  ```
598
1688
 
599
1689
  ### Binary Comparison
@@ -789,14 +1879,59 @@ On Linux/macOS, ensure the binary is executable:
789
1879
  chmod +x node_modules/@certchip/signer/bin/*/signercli
790
1880
  ```
791
1881
 
1882
+ ## Build from Source
1883
+
1884
+ ### Linux x64 (Fullstatic)
1885
+
1886
+ Build a fully static binary for Linux distribution (no dynamic library dependencies):
1887
+
1888
+ ```bash
1889
+ cd core/signer-cli
1890
+
1891
+ # Fullstatic build (auto-builds libcurl.a if missing)
1892
+ ./build_fullstatic_linux_x64.sh
1893
+
1894
+ # Or step by step:
1895
+ ./build_fullstatic_linux_x64.sh --check # Check static library dependencies
1896
+ ./build_fullstatic_linux_x64.sh --build-curl # Build static libcurl if missing
1897
+ ./build_fullstatic_linux_x64.sh # Build fullstatic binary
1898
+
1899
+ # Output: bin/linux-x64/signercli (fully static, no dynamic dependencies)
1900
+ ```
1901
+
1902
+ Required static libraries (in `../../libs/`):
1903
+ - OpenSSL 3.4.1 (`libssl.a`, `libcrypto.a`)
1904
+ - cJSON (`libcjson.a`)
1905
+ - json-c (`libjson-c.a`)
1906
+ - libcurl (`libcurl.a`)
1907
+ - libotpkey (`libotpkey.a`)
1908
+
1909
+ ### Windows x64 (MSYS2)
1910
+
1911
+ ```bash
1912
+ cd core/signer-cli
1913
+
1914
+ # Static build for npm package
1915
+ make -f Makefile.msys2 STATIC_CURL=1 RELEASE=1
1916
+
1917
+ # Build + copy dependencies for npm
1918
+ make -f Makefile.msys2 npm-package
1919
+ ```
1920
+
1921
+ ### Debug Build (any platform)
1922
+
1923
+ ```bash
1924
+ cd core/signer-cli
1925
+ make # Debug build (auto-detects platform)
1926
+ make RELEASE=1 # Release build
1927
+ ```
1928
+
792
1929
  ## Requirements
793
1930
 
794
1931
  - **Node.js** >= 14.0.0
795
- - **Platforms**: Windows x64 (Linux x64/arm64, macOS x64/arm64 coming soon)
1932
+ - **Platforms**: Windows x64, Linux x64 (macOS x64/arm64 coming soon)
796
1933
  - **Server**: Certchip Signer API compatible server
797
1934
 
798
- > **Note:** The current npm package includes Windows x64 binaries only. Linux and macOS binaries will be added in a future release.
799
-
800
1935
  ## License
801
1936
 
802
1937
  Copyright (c) 2025 Certchip. All rights reserved.
@@ -806,3 +1941,10 @@ Copyright (c) 2025 Certchip. All rights reserved.
806
1941
  - [Homepage](https://certchip.com/signer)
807
1942
  - [Documentation](https://certchip.com/signer/help)
808
1943
  - [Issues](https://github.com/certchip/signer-cli/issues)
1944
+
1945
+ ## Additional Documentation
1946
+
1947
+ - [Configuration File Guide](docs/CONFIG-FILE-GUIDE.md) - Profile and config file options
1948
+ - [cert-dist Guide](docs/cert-dist-guide.md) - Let's Encrypt certificate distribution
1949
+ - [Server API Key Auth Guide](docs/SERVER-API-KEY-AUTH-GUIDE.md) - Server-side API key implementation
1950
+ - [Server Cert API Endpoints](docs/SERVER-CERT-API-ENDPOINTS.md) - Certificate API specification