@certchip/signer 0.1.19 → 0.1.28

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.28
286
519
  Cross-platform code and document signing tool
287
- Copyright (c) 2025 Certchip. All rights reserved.
520
+ Copyright (c) 2026 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.28.0
524
+ Certchip.dll: 0.1.28.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.28.0
528
+ Certchip.dll: 0.1.28.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,882 @@ 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.28
457
693
  Windows Key Storage Provider and Code Signing Tool
458
- Copyright (c) 2025 Certchip. All rights reserved.
694
+ Copyright (c) 2026 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.28.0
698
+ Certchip.dll: 0.1.28.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.28.0
702
+ Certchip.dll: 0.1.28.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
+ > **Note:** Wildcard domains (e.g., `*.example.com`) are automatically sanitized for file/folder names. The `*` and other invalid filename characters are replaced with `_`. For example, `*.example.com` becomes `_.example.com` in file paths.
804
+
805
+ **Examples:**
806
+
807
+ ```bash
808
+ # Download in Nginx format (default)
809
+ signercli -cert-dist download example.com -api-key cdk_xxx -host https://signer.example.com:7443
810
+
811
+ # Download in Let's Encrypt style
812
+ signercli -cert-dist download example.com -api-key cdk_xxx -host https://signer.example.com:7443 \
813
+ -format letsencrypt -o /etc/letsencrypt/live
814
+
815
+ # Automation: renew if needed, download, and reload Nginx
816
+ signercli -cert-dist sync example.com -api-key cdk_xxx -host https://signer.example.com:7443 \
817
+ -o /etc/nginx/ssl -reload-cmd "systemctl reload nginx"
818
+
819
+ # Get status in JSON format (for scripting)
820
+ signercli -cert-dist status example.com -api-key cdk_xxx -host https://signer.example.com:7443 -format json
821
+ ```
822
+
823
+ **Exit Codes:**
824
+ - `0`: Success (for check command: no renewal needed)
825
+ - `1`: Error
826
+ - `2`: Renewal needed (check command only)
827
+
828
+ > **Detailed usage:** See [cert-dist-guide.md](docs/cert-dist-guide.md)
829
+
830
+ ---
831
+
832
+ ### cert-api (Certificate Management API)
833
+
834
+ General certificate and key management commands. Uses the same API key as cert-dist.
835
+
836
+ **Three Command Systems:**
837
+
838
+ | Commands | Purpose | API Endpoint |
839
+ |----------|---------|--------------|
840
+ | `-cert-dist` | Let's Encrypt certificate distribution/renewal | `/api/cert-distribution` |
841
+ | `-cert`, `-privkey`, `-pubkey`, `-csr` | General certificate/key management | `/api/cert-api` |
842
+ | `-letsencrypt` | Let's Encrypt SSL certificate direct management | `/api/cert-api/letsencrypt` |
843
+
844
+ #### API Key Authentication (-api-key)
845
+
846
+ API keys allow direct API access without SSH key-based login.
847
+
848
+ **What is an API Key?**
849
+
850
+ - A unique authentication token issued by the server (format: `cdk_` prefix + 64-char hex)
851
+ - Alternative to SSH key-based challenge-response login
852
+ - Ideal for CI/CD pipelines, automation scripts, and programmatic access
853
+
854
+ **API Key Format:**
855
+ ```
856
+ cdk_e2f369e7c85bfa7835d375f6b088f15dac2c2d8ebeb0815c392a6d6b34ee916f
857
+ ```
858
+
859
+ **Usage Methods:**
860
+
861
+ ```bash
862
+ # Method 1: Specify directly on command line
863
+ signercli -cert list -api-key cdk_xxx -host https://server:7443
864
+
865
+ # Method 2: Store in profile (recommended)
866
+ signercli -config set default -host https://server:7443 -api-key cdk_xxx
867
+ signercli -cert list # api-key and host auto-applied
868
+
869
+ # Method 3: Use named profile
870
+ signercli -config set production -host https://prod:7443 -api-key cdk_prod_key
871
+ signercli -cert list -profile production
872
+ ```
873
+
874
+ **Supported Commands:**
875
+
876
+ | Command | Description |
877
+ |---------|-------------|
878
+ | `-cert` | Certificate management (list, upload, download, delete) |
879
+ | `-cert-dist` | Let's Encrypt certificate distribution/renewal |
880
+ | `-letsencrypt` | Let's Encrypt SSL certificate direct management |
881
+ | `-privkey` | Private key management |
882
+ | `-pubkey` | Public key management |
883
+ | `-csr` | Certificate Signing Request generation |
884
+
885
+ **Login Authentication vs API Key Authentication:**
886
+
887
+ | Aspect | Login Authentication | API Key Authentication |
888
+ |--------|---------------------|------------------------|
889
+ | Method | SSH key challenge-response | Direct API key transmission |
890
+ | Token Expiry | Yes (default 24h) | Depends on server config |
891
+ | Commands | All commands after `-login` | `-cert`, `-cert-dist`, etc. only |
892
+ | Best For | Interactive use, code signing | Automation, CI/CD, scripts |
893
+
894
+ **Security Notes:**
895
+
896
+ - Protect API keys like passwords
897
+ - Set config file permissions: `chmod 600 ~/.signer/config`
898
+ - Don't hardcode API keys in scripts
899
+ - Use secret managers in CI/CD environments
900
+
901
+ #### Certificate Commands (-cert)
902
+
903
+ ```bash
904
+ # List certificates
905
+ signercli -cert list -api-key <key> [-host <url>]
906
+
907
+ # Get certificate details
908
+ signercli -cert get <id> -api-key <key>
909
+
910
+ # Upload certificate (default: DB storage)
911
+ signercli -cert upload <file> -name "Certificate Name" -api-key <key>
912
+
913
+ # Upload certificate to Software HSM (no PIN required)
914
+ signercli -cert upload <file> -name "My Cert" -storage SW_HSM -api-key <key>
915
+
916
+ # Upload certificate to Hardware HSM (slot and PIN required)
917
+ signercli -cert upload <file> -name "My Cert" -storage HW_HSM -hsm-slot 0 -hsm-pin <pin> -api-key <key>
918
+
919
+ # Download certificate (PEM/DER)
920
+ signercli -cert download <id> -format pem -o <dir> -api-key <key>
921
+
922
+ # Download certificate (PFX)
923
+ signercli -cert download-pfx <id> -password <pwd> -o <dir> -api-key <key>
924
+
925
+ # Update certificate metadata
926
+ signercli -cert update <id> -name "New Name" -desc "Description" -api-key <key>
927
+
928
+ # Delete certificate
929
+ signercli -cert delete <id> -api-key <key>
930
+
931
+ # Delete certificate with related private key
932
+ signercli -cert delete <id> -delete-related -api-key <key>
933
+
934
+ # Delete HSM certificate (PIN required)
935
+ signercli -cert delete <id> -hsm-pin <pin> -api-key <key>
936
+ ```
937
+
938
+ **Storage Types:**
939
+
940
+ | Type | Description | Requirements |
941
+ |------|-------------|--------------|
942
+ | `DB` | Database storage (default) | None |
943
+ | `SW_HSM` | Software HSM (encrypted storage) | None |
944
+ | `HW_HSM` | Hardware HSM (PKCS#11 device) | `-hsm-slot`, `-hsm-pin` |
945
+
946
+ **Using Profile with API Key:**
947
+
948
+ You can store the API key in a profile to avoid specifying it on every command:
949
+
950
+ ```bash
951
+ # Configure profile with API key (one-time setup)
952
+ signercli -config set default -host https://server:7443 -api-key cdk_xxx
953
+
954
+ # Now use -cert commands without -api-key and -host
955
+ signercli -cert list
956
+ signercli -cert get <id>
957
+ signercli -cert upload cert.pem -name "My Cert"
958
+
959
+ # Or use a named profile
960
+ signercli -config set myserver -host https://server:7443 -api-key cdk_xxx
961
+ signercli -cert list -profile myserver
962
+ ```
963
+
964
+ #### Creating Test Certificates (OpenSSL)
965
+
966
+ For testing `-cert upload` and other certificate commands, you can create test certificates using OpenSSL.
967
+
968
+ ##### Linux / macOS
969
+
970
+ **1. Self-Signed Certificate (Simple)**
971
+
972
+ ```bash
973
+ # Generate RSA key + certificate in one command
974
+ openssl req -x509 -newkey rsa:2048 -keyout test_key.pem -out test_cert.pem -days 365 -nodes \
975
+ -subj "/C=KR/ST=Seoul/L=Gangnam/O=TestOrg/OU=Dev/CN=Test Certificate"
976
+
977
+ # Verify certificate
978
+ openssl x509 -in test_cert.pem -text -noout
979
+ ```
980
+
981
+ **2. Code Signing Certificate**
982
+
983
+ ```bash
984
+ # Generate private key
985
+ openssl genrsa -out codesign_key.pem 2048
986
+
987
+ # Generate certificate with code signing extensions
988
+ openssl req -new -x509 -key codesign_key.pem -out codesign_cert.pem -days 365 \
989
+ -subj "/C=KR/O=MyCompany/CN=Code Signing Certificate" \
990
+ -addext "keyUsage=digitalSignature" \
991
+ -addext "extendedKeyUsage=codeSigning"
992
+ ```
993
+
994
+ **3. PFX/P12 Bundle (Key + Certificate)**
995
+
996
+ ```bash
997
+ # Create PFX from PEM files
998
+ openssl pkcs12 -export -out test_bundle.pfx \
999
+ -inkey test_key.pem -in test_cert.pem \
1000
+ -password pass:test1234
1001
+ ```
1002
+
1003
+ **4. DER Format Certificate**
1004
+
1005
+ ```bash
1006
+ # Convert PEM to DER
1007
+ openssl x509 -in test_cert.pem -outform DER -out test_cert.der
1008
+ ```
1009
+
1010
+ **5. Complete Test Script (Linux/macOS)**
1011
+
1012
+ ```bash
1013
+ #!/bin/bash
1014
+ # create_test_certs.sh
1015
+ mkdir -p test_certs && cd test_certs
1016
+
1017
+ # Basic test certificate
1018
+ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes \
1019
+ -subj "/CN=Test Certificate"
1020
+
1021
+ # Code signing certificate
1022
+ openssl req -x509 -newkey rsa:4096 -keyout codesign_key.pem -out codesign_cert.pem -days 365 -nodes \
1023
+ -subj "/C=KR/O=TestOrg/CN=Code Signing Test" \
1024
+ -addext "keyUsage=digitalSignature" \
1025
+ -addext "extendedKeyUsage=codeSigning"
1026
+
1027
+ # PFX bundle
1028
+ openssl pkcs12 -export -out bundle.pfx -inkey key.pem -in cert.pem -password pass:test1234
1029
+
1030
+ # DER format
1031
+ openssl x509 -in cert.pem -outform DER -out cert.der
1032
+
1033
+ echo "Created files:"
1034
+ ls -la
1035
+ ```
1036
+
1037
+ ##### Windows (PowerShell / CMD)
1038
+
1039
+ > **Note:** Windows requires OpenSSL to be installed. You can install it via:
1040
+ > - [Git for Windows](https://git-scm.com/) (includes OpenSSL in Git Bash)
1041
+ > - [MSYS2](https://www.msys2.org/) (`pacman -S openssl`)
1042
+ > - [OpenSSL for Windows](https://slproweb.com/products/Win32OpenSSL.html)
1043
+
1044
+ **1. Self-Signed Certificate (PowerShell)**
1045
+
1046
+ ```powershell
1047
+ # Using Git Bash OpenSSL (adjust path as needed)
1048
+ & "C:\Program Files\Git\usr\bin\openssl.exe" req -x509 -newkey rsa:2048 `
1049
+ -keyout test_key.pem -out test_cert.pem -days 365 -nodes `
1050
+ -subj "/C=KR/ST=Seoul/L=Gangnam/O=TestOrg/OU=Dev/CN=Test Certificate"
1051
+
1052
+ # Verify certificate
1053
+ & "C:\Program Files\Git\usr\bin\openssl.exe" x509 -in test_cert.pem -text -noout
1054
+ ```
1055
+
1056
+ **2. Using Windows Native (certreq + PowerShell)**
1057
+
1058
+ ```powershell
1059
+ # Create self-signed certificate using PowerShell
1060
+ $cert = New-SelfSignedCertificate -DnsName "Test Certificate" `
1061
+ -CertStoreLocation "Cert:\CurrentUser\My" `
1062
+ -KeyUsage DigitalSignature `
1063
+ -Type CodeSigningCert `
1064
+ -NotAfter (Get-Date).AddYears(1)
1065
+
1066
+ # Export to PFX
1067
+ $password = ConvertTo-SecureString -String "test1234" -Force -AsPlainText
1068
+ Export-PfxCertificate -Cert $cert -FilePath "test_bundle.pfx" -Password $password
1069
+
1070
+ # Export certificate only (CER/DER format)
1071
+ Export-Certificate -Cert $cert -FilePath "test_cert.cer" -Type CERT
1072
+
1073
+ # Show certificate info
1074
+ $cert | Format-List Subject, Thumbprint, NotAfter
1075
+ ```
1076
+
1077
+ **3. Complete Test Script (Windows CMD with Git Bash OpenSSL)**
1078
+
1079
+ ```batch
1080
+ @echo off
1081
+ REM create_test_certs.bat
1082
+ REM Requires OpenSSL (Git Bash or standalone)
1083
+
1084
+ set OPENSSL="C:\Program Files\Git\usr\bin\openssl.exe"
1085
+ mkdir test_certs 2>nul
1086
+ cd test_certs
1087
+
1088
+ REM Basic test certificate
1089
+ %OPENSSL% req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=Test Certificate"
1090
+
1091
+ REM Code signing certificate
1092
+ %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"
1093
+
1094
+ REM PFX bundle
1095
+ %OPENSSL% pkcs12 -export -out bundle.pfx -inkey key.pem -in cert.pem -password pass:test1234
1096
+
1097
+ REM DER format
1098
+ %OPENSSL% x509 -in cert.pem -outform DER -out cert.der
1099
+
1100
+ echo Created files:
1101
+ dir /b
1102
+ ```
1103
+
1104
+ **4. Complete Test Script (Windows PowerShell Native)**
1105
+
1106
+ ```powershell
1107
+ # create_test_certs.ps1
1108
+ # Uses Windows native certificate APIs (no OpenSSL required)
1109
+
1110
+ $testDir = "test_certs"
1111
+ New-Item -ItemType Directory -Force -Path $testDir | Out-Null
1112
+ Set-Location $testDir
1113
+
1114
+ $password = ConvertTo-SecureString -String "test1234" -Force -AsPlainText
1115
+
1116
+ # Basic test certificate
1117
+ $basicCert = New-SelfSignedCertificate -DnsName "Test Certificate" `
1118
+ -CertStoreLocation "Cert:\CurrentUser\My" `
1119
+ -NotAfter (Get-Date).AddYears(1)
1120
+
1121
+ Export-PfxCertificate -Cert $basicCert -FilePath "bundle.pfx" -Password $password
1122
+ Export-Certificate -Cert $basicCert -FilePath "cert.cer" -Type CERT
1123
+ Export-Certificate -Cert $basicCert -FilePath "cert.der" -Type CERT
1124
+
1125
+ # Code signing certificate
1126
+ $codeCert = New-SelfSignedCertificate -Subject "CN=Code Signing Test, O=TestOrg, C=KR" `
1127
+ -CertStoreLocation "Cert:\CurrentUser\My" `
1128
+ -KeyUsage DigitalSignature `
1129
+ -Type CodeSigningCert `
1130
+ -NotAfter (Get-Date).AddYears(1)
1131
+
1132
+ Export-PfxCertificate -Cert $codeCert -FilePath "codesign_bundle.pfx" -Password $password
1133
+
1134
+ # Clean up from certificate store (optional)
1135
+ # Remove-Item -Path $basicCert.PSPath
1136
+ # Remove-Item -Path $codeCert.PSPath
1137
+
1138
+ Write-Host "Created files:"
1139
+ Get-ChildItem
1140
+ ```
1141
+
1142
+ ##### Upload Test Commands (All Platforms)
1143
+
1144
+ ```bash
1145
+ # Upload PEM certificate
1146
+ signercli -cert upload test_certs/cert.pem -name "Test Cert" -api-key <key> -host https://server:7443
1147
+
1148
+ # Upload PFX bundle
1149
+ signercli -cert upload test_certs/bundle.pfx -name "PFX Bundle" -api-key <key> -host https://server:7443
1150
+
1151
+ # Upload DER certificate
1152
+ signercli -cert upload test_certs/cert.der -name "DER Cert" -api-key <key> -host https://server:7443
1153
+ ```
1154
+
1155
+ ##### File Format Summary
1156
+
1157
+ | Format | Extension | Description | Created By |
1158
+ |--------|-----------|-------------|------------|
1159
+ | PEM | `.pem`, `.crt` | Base64 encoded, text format | OpenSSL |
1160
+ | DER | `.der`, `.cer` | Binary format | OpenSSL, Windows |
1161
+ | PFX/P12 | `.pfx`, `.p12` | Key + Certificate bundle | OpenSSL, Windows |
1162
+
1163
+ #### Private Key Commands (-privkey)
1164
+
1165
+ ```bash
1166
+ # List private keys
1167
+ signercli -privkey list -api-key <key>
1168
+
1169
+ # Get private key details
1170
+ signercli -privkey get <id> -api-key <key>
1171
+
1172
+ # Upload private key (default: DB storage)
1173
+ signercli -privkey upload <file> -api-key <key>
1174
+
1175
+ # Upload encrypted private key
1176
+ signercli -privkey upload <file> -password <pwd> -api-key <key>
1177
+
1178
+ # Upload private key to Software HSM
1179
+ signercli -privkey upload <file> -storage SW_HSM -api-key <key>
1180
+
1181
+ # Upload private key to Hardware HSM
1182
+ signercli -privkey upload <file> -storage HW_HSM -hsm-slot 0 -hsm-pin <pin> -api-key <key>
1183
+
1184
+ # Delete private key
1185
+ signercli -privkey delete <id> -api-key <key>
1186
+
1187
+ # Delete HSM private key (PIN required)
1188
+ signercli -privkey delete <id> -hsm-pin <pin> -api-key <key>
1189
+
1190
+ # Link private key to certificate
1191
+ signercli -privkey link <key-id> <cert-id> -api-key <key>
1192
+
1193
+ # Unlink private key from certificate
1194
+ signercli -privkey unlink <key-id> -api-key <key>
1195
+ ```
1196
+
1197
+ #### Public Key Commands (-pubkey)
1198
+
1199
+ ```bash
1200
+ # List public keys
1201
+ signercli -pubkey list -api-key <key>
1202
+
1203
+ # Extract public key from certificate
1204
+ signercli -pubkey extract <cert-id> -api-key <key>
1205
+
1206
+ # Extract with custom name
1207
+ signercli -pubkey extract <cert-id> -name "Public Key Name" -api-key <key>
1208
+ ```
1209
+
1210
+ #### CSR Commands (-csr)
1211
+
1212
+ ```bash
1213
+ # Generate CSR
1214
+ signercli -csr generate -cn <common-name> -api-key <key>
1215
+
1216
+ # Generate CSR with full subject
1217
+ signercli -csr generate \
1218
+ -cn example.com \
1219
+ -c KR \
1220
+ -st Seoul \
1221
+ -l Gangnam \
1222
+ -org "Example Corp" \
1223
+ -ou "IT Department" \
1224
+ -email admin@example.com \
1225
+ -keysize 4096 \
1226
+ -api-key <key>
1227
+
1228
+ # Save CSR to file
1229
+ signercli -csr generate -cn example.com -o <dir> -api-key <key>
1230
+ ```
1231
+
1232
+ #### Let's Encrypt Commands (-letsencrypt)
1233
+
1234
+ Direct management of Let's Encrypt SSL certificates stored on the server. Requires `SYSTEM_ADMIN` role or explicit `letsencrypt` permission.
1235
+
1236
+ > **Note:** This command directly accesses Let's Encrypt certificates stored on the server, while `-cert-dist` is for distributing certificates to external servers/devices.
1237
+
1238
+ **Authentication:**
1239
+
1240
+ You can authenticate using either method:
1241
+ 1. **Login first** - Use JWT token from login session (no API key needed)
1242
+ 2. **API key** - Provide API key directly
1243
+
1244
+ ```bash
1245
+ # Method 1: Login first, then use commands without API key
1246
+ signercli -login https://signer.example.com:7443 admin
1247
+ signercli -letsencrypt list
1248
+
1249
+ # Method 2: Use API key directly
1250
+ signercli -letsencrypt list -api-key <key>
1251
+ ```
1252
+
1253
+ **Access Control:**
1254
+
1255
+ | Authentication | Condition | Access |
1256
+ |---------------|-----------|--------|
1257
+ | JWT | role = `SYSTEM_ADMIN` | ✅ Allowed |
1258
+ | JWT | role = `OPERATION_MANAGER` or `USER` | ❌ Denied |
1259
+ | API Key (inherited) | linkedUserRole = `SYSTEM_ADMIN` | ✅ Allowed |
1260
+ | API Key (inherited) | linkedUserRole ≠ `SYSTEM_ADMIN` | ❌ Denied |
1261
+ | API Key (explicit) | permissions includes `letsencrypt` or `all` | ✅ Allowed |
1262
+ | API Key (explicit) | permissions excludes `letsencrypt` | ❌ Denied |
1263
+
1264
+ **Commands:**
1265
+
1266
+ | Command | Description |
1267
+ |---------|-------------|
1268
+ | `list` | List Let's Encrypt certificates |
1269
+ | `get <id>` | Get certificate details |
1270
+ | `download <id>` | Download certificate files |
1271
+ | `request` | Request new certificate (HTTP-01 or DNS-01) |
1272
+ | `dns-request` | Start DNS-01 challenge (outputs challenge ID) |
1273
+ | `dns-request -interactive` | DNS-01 challenge (interactive mode) |
1274
+ | `dns-complete` | Complete DNS-01 challenge |
1275
+ | `dns-providers` | List available DNS providers |
1276
+ | `renew <id>` | Renew certificate (automatic) |
1277
+ | `renew-dns <id>` | Start manual DNS-01 renewal (outputs challenge ID) |
1278
+ | `renew-dns <id> -interactive` | Manual DNS-01 renewal (interactive mode) |
1279
+ | `delete <id>` | Delete certificate |
1280
+ | `auto-renewal <id>` | Enable/disable auto-renewal |
1281
+ | `activate <id>` | Set certificate as Signer server's SSL certificate |
1282
+
1283
+ **List/Get/Download Options:**
1284
+
1285
+ | Option | Description | Default |
1286
+ |--------|-------------|---------|
1287
+ | `-api-key <key>` | API key (optional if logged in) | - |
1288
+ | `-host <url>` | Server URL | `https://localhost:7443` |
1289
+ | `-format <type>` | Output format: text, json | text |
1290
+ | `-env <environment>` | Filter by environment: staging, production | - |
1291
+ | `-domain <pattern>` | Filter by domain (supports `*` wildcard, e.g., `*.example.com`) | - |
1292
+ | `-type <type>` | Download type: cert, chain, fullchain, key, all | fullchain |
1293
+ | `-o <dir>` | Output directory for downloads | Current directory |
1294
+ | `-naming <style>` | Filename style: `letsencrypt` or `domain` | letsencrypt |
1295
+
1296
+ **Request Options:**
1297
+
1298
+ | Option | Description | Default |
1299
+ |--------|-------------|---------|
1300
+ | `-domain <domain>` | Domain name for the certificate (required) | - |
1301
+ | `-email <email>` | Contact email for Let's Encrypt account (required) | - |
1302
+ | `-agree-tos` | Agree to Let's Encrypt Terms of Service (required) | - |
1303
+ | `-env <environment>` | Environment: staging, production | staging |
1304
+ | `-key-type <type>` | Key type: RSA, ECDSA | RSA |
1305
+ | `-keysize <bits>` | Key size: 2048, 4096, etc. | 2048 |
1306
+ | `-san <domains>` | Subject Alternative Names (comma-separated) | - |
1307
+ | `-challenge <type>` | Challenge type: http-01, dns-01 | http-01 |
1308
+ | `-dns-provider <mode>` | DNS provider mode: auto, selected (for dns-01) | auto |
1309
+ | `-provider-id <id>` | DNS Provider ID (auto-sets -dns-provider to 'selected') | - |
1310
+
1311
+ **DNS-01 Challenge Options (for dns-request/dns-complete):**
1312
+
1313
+ | Option | Description | Default |
1314
+ |--------|-------------|---------|
1315
+ | `-interactive, -i` | Interactive mode: wait for Enter, then complete (dns-request) | - |
1316
+ | `-challenge-id <id>` | Challenge ID from dns-request (for dns-complete) | - |
1317
+
1318
+ **Auto-Renewal Options:**
1319
+
1320
+ | Option | Description |
1321
+ |--------|-------------|
1322
+ | `-enable` | Enable auto-renewal |
1323
+ | `-disable` | Disable auto-renewal |
1324
+
1325
+ ```bash
1326
+ # List Let's Encrypt certificates
1327
+ signercli -letsencrypt list # Using login token
1328
+ signercli -letsencrypt list -api-key <key> # Using API key
1329
+
1330
+ # Filter by environment
1331
+ signercli -letsencrypt list -env production
1332
+ signercli -letsencrypt list -env staging
1333
+
1334
+ # Filter by domain (partial match or wildcard)
1335
+ signercli -letsencrypt list -domain example.com
1336
+ signercli -letsencrypt list -domain api # Matches api.example.com, etc.
1337
+ signercli -letsencrypt list -domain "*.example.com" # Matches wildcard certificates
1338
+
1339
+ # Combine filters
1340
+ signercli -letsencrypt list -env production -domain example.com
1341
+
1342
+ # Get certificate details
1343
+ signercli -letsencrypt get <id>
1344
+
1345
+ # Download certificate (fullchain by default)
1346
+ signercli -letsencrypt download <id>
1347
+
1348
+ # Download specific type
1349
+ signercli -letsencrypt download <id> -type cert # Certificate only
1350
+ signercli -letsencrypt download <id> -type chain # Chain only
1351
+ signercli -letsencrypt download <id> -type fullchain # Full chain (default)
1352
+ signercli -letsencrypt download <id> -type key # Private key
1353
+ signercli -letsencrypt download <id> -type all # All files
1354
+
1355
+ # Download to specific directory (default: cert.pem, privkey.pem, etc.)
1356
+ signercli -letsencrypt download <id> -type all -o /etc/ssl
1357
+
1358
+ # Download with domain-based naming (<domain>.crt, <domain>.key, etc.)
1359
+ signercli -letsencrypt download <id> -type all -o /etc/ssl -naming domain
1360
+ ```
1361
+
1362
+ **Download Types:**
1363
+
1364
+ | Type | Description | Let's Encrypt (default) | Domain Style |
1365
+ |------|-------------|-------------------------|--------------|
1366
+ | `cert` | Certificate only | `cert.pem` | `<domain>.crt` |
1367
+ | `chain` | Intermediate chain | `chain.pem` | `<domain>.chain.crt` |
1368
+ | `fullchain` | Certificate + chain (default) | `fullchain.pem` | `<domain>.fullchain.crt` |
1369
+ | `key` | Private key | `privkey.pem` | `<domain>.key` |
1370
+ | `all` | All files | All above files | All above files |
1371
+
1372
+ **Output Options:**
1373
+
1374
+ ```bash
1375
+ # JSON format output
1376
+ signercli -letsencrypt list -format json
1377
+
1378
+ # Table format output
1379
+ signercli -letsencrypt list -format table
1380
+ ```
1381
+
1382
+ **Examples:**
1383
+
1384
+ ```bash
1385
+ # Login first (recommended for interactive use)
1386
+ signercli -login https://signer.example.com:7443 admin
1387
+
1388
+ # List all production certificates
1389
+ signercli -letsencrypt list -env production
1390
+
1391
+ # List certificates for a specific domain
1392
+ signercli -letsencrypt list -domain example.com
1393
+
1394
+ # Get specific certificate details
1395
+ signercli -letsencrypt get 6789abcd
1396
+
1397
+ # Download fullchain to /etc/nginx/ssl
1398
+ signercli -letsencrypt download 6789abcd -type fullchain -o /etc/nginx/ssl
1399
+
1400
+ # Download all files for Nginx configuration
1401
+ signercli -letsencrypt download 6789abcd -type all -o /etc/nginx/ssl
1402
+
1403
+ # Using API key (for automation/scripts)
1404
+ signercli -letsencrypt list -env production -api-key cdk_xxx -host https://signer.example.com:7443
1405
+
1406
+ # --- HTTP-01 Challenge (default) ---
1407
+ # Request new certificate (staging environment - for testing)
1408
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos
1409
+
1410
+ # Request production certificate
1411
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos -env production
1412
+
1413
+ # Request certificate with Subject Alternative Names
1414
+ signercli -letsencrypt request -domain example.com -san "www.example.com,api.example.com" -email admin@example.com -agree-tos
1415
+
1416
+ # --- DNS-01 Challenge with DNS Provider ---
1417
+ # Auto-detect DNS provider for domain (default when using dns-01)
1418
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos \
1419
+ -challenge dns-01
1420
+
1421
+ # Use specific DNS provider (provider-id auto-sets mode to 'selected')
1422
+ signercli -letsencrypt request -domain example.com -email admin@example.com -agree-tos \
1423
+ -challenge dns-01 -provider-id 6789abc
1424
+
1425
+ # Wildcard certificate with DNS provider (auto mode)
1426
+ signercli -letsencrypt request -domain "*.example.com" -email admin@example.com -agree-tos \
1427
+ -challenge dns-01 -env production
1428
+
1429
+ # --- DNS-01 Challenge (Manual - Two-step process) ---
1430
+ # Step 1: Start DNS challenge (get TXT records to add)
1431
+ signercli -letsencrypt dns-request -domain example.com -email admin@example.com -agree-tos
1432
+ # Step 2: After adding TXT records to DNS, complete the challenge
1433
+ signercli -letsencrypt dns-complete -challenge-id <challenge-id>
1434
+
1435
+ # --- DNS-01 Challenge (Manual - Interactive mode) ---
1436
+ # Single command that waits for Enter and completes automatically
1437
+ signercli -letsencrypt dns-request -domain example.com -email admin@example.com -agree-tos -interactive
1438
+
1439
+ # --- DNS Provider Management ---
1440
+ # List available DNS providers
1441
+ signercli -letsencrypt dns-providers
1442
+
1443
+ # --- Certificate Renewal ---
1444
+ # Renew certificate (automatic - for HTTP-01 or auto DNS-01)
1445
+ signercli -letsencrypt renew 6789abcd
1446
+
1447
+ # --- Manual DNS-01 Renewal (Two-step process) ---
1448
+ # Step 1: Start renewal (get DNS records and challenge ID)
1449
+ signercli -letsencrypt renew-dns 6789abcd
1450
+ # Step 2: After adding TXT records to DNS, complete the renewal
1451
+ signercli -letsencrypt dns-complete -challenge-id <challenge-id>
1452
+
1453
+ # --- Manual DNS-01 Renewal (Interactive mode) ---
1454
+ # Single command that waits for Enter and completes automatically
1455
+ signercli -letsencrypt renew-dns 6789abcd -interactive
1456
+
1457
+ # Delete certificate
1458
+ signercli -letsencrypt delete 6789abcd
1459
+
1460
+ # Enable auto-renewal
1461
+ signercli -letsencrypt auto-renewal 6789abcd -enable
1462
+
1463
+ # Disable auto-renewal
1464
+ signercli -letsencrypt auto-renewal 6789abcd -disable
1465
+
1466
+ # --- Activating Server SSL Certificate ---
1467
+ # Activate certificate for HTTPS server
1468
+ signercli -letsencrypt activate 6789abcd
1469
+ ```
1470
+
1471
+ > **Important: About the 'activate' command**
1472
+ >
1473
+ > The `activate` command sets the specified Let's Encrypt certificate as the **Signer server's own SSL certificate**.
1474
+ > This means that after activation:
1475
+ > - The Signer server will use this certificate for HTTPS connections
1476
+ > - Clients connecting to the Signer server will see this certificate
1477
+ >
1478
+ > **This does NOT mean:**
1479
+ > - ❌ Enabling or disabling the certificate itself
1480
+ > - ❌ Making the certificate "active" vs "inactive"
1481
+ > - ❌ Publishing or unpublishing the certificate
1482
+ >
1483
+ > All issued certificates remain valid and usable regardless of activation status.
1484
+ > The `activate` command is only for configuring which certificate the Signer server uses for its own HTTPS endpoint.
1485
+
1486
+ **Certificate Issuance/Renewal Notes:**
1487
+
1488
+ | Scenario | Command | Description |
1489
+ |----------|---------|-------------|
1490
+ | **New Certificate** | | |
1491
+ | DNS-01 manual (scripted) | `dns-request` + `dns-complete` | Two-step process for automation |
1492
+ | DNS-01 manual (interactive) | `dns-request -interactive` | Single command with Enter prompt |
1493
+ | **Certificate Renewal** | | |
1494
+ | HTTP-01 challenge | `renew` | Automatic renewal via HTTP validation |
1495
+ | DNS-01 with provider | `renew` | Automatic renewal via DNS API |
1496
+ | DNS-01 manual (scripted) | `renew-dns` + `dns-complete` | Two-step process for automation |
1497
+ | DNS-01 manual (interactive) | `renew-dns -interactive` | Single command with Enter prompt |
1498
+ | Renewal failed | `renew-dns` | Use when `renew` shows "Manual DNS renewal required" |
1499
+
1500
+ **Challenge Types:**
1501
+
1502
+ | Challenge | Description | Use Case |
1503
+ |-----------|-------------|----------|
1504
+ | HTTP-01 | Validates via HTTP on port 80 | Standard domains, internet-accessible servers |
1505
+ | DNS-01 | Validates via DNS TXT record | Wildcard certs, internal servers, port 80 blocked |
1506
+
1507
+ **DNS Provider Modes:**
1508
+
1509
+ | Mode | Description |
1510
+ |------|-------------|
1511
+ | `auto` | Auto-detect DNS provider based on domain (default for dns-01) |
1512
+ | `selected` | Use specific provider (auto-set when `-provider-id` is provided) |
1513
+ | Manual | Use `dns-request`/`dns-complete` commands |
1514
+
1515
+ > **Note:** When using `-challenge dns-01`:
1516
+ > - If `-dns-provider` is not specified, it defaults to `auto`
1517
+ > - If `-provider-id` is specified, `-dns-provider` is automatically set to `selected`
1518
+
1519
+ **Supported DNS Providers:**
1520
+ - Cloudflare
1521
+ - AWS Route 53
1522
+ - GoDaddy
1523
+ - Custom Script
1524
+
1525
+ **Notes:**
1526
+ - HTTP-01 challenge (default) requires port 80 to be accessible from the internet.
1527
+ - DNS-01 challenge is required for wildcard certificates (e.g., `*.example.com`).
1528
+ - DNS-01 with DNS provider enables full automation including auto-renewal.
1529
+ - Production environment has rate limits. Test with staging first.
1530
+ - SYSTEM_ADMIN role is required for all Let's Encrypt operations.
1531
+
1532
+ #### cert-api Common Options
1533
+
1534
+ | Option | Description | Default |
1535
+ |--------|-------------|---------|
1536
+ | `-api-key <key>` | API key (optional for `-letsencrypt` if logged in) | - |
1537
+ | `-host <url>` | Signer Server URL | `https://localhost:7443` |
1538
+ | `-profile <name>` | Use settings from config profile | default |
1539
+ | `-format <type>` | Output format (json, pem, der) | text |
1540
+ | `-o <dir>` | Output directory | Current directory |
1541
+ | `-name <name>` | Name for upload/create | Filename |
1542
+ | `-desc <text>` | Description | - |
1543
+ | `-password <pwd>` | PFX/encrypted key password | - |
1544
+ | `-storage <type>` | Storage type: DB, SW_HSM, HW_HSM | DB |
1545
+ | `-hsm-slot <id>` | HSM slot ID (required for HW_HSM) | - |
1546
+ | `-hsm-pin <pin>` | HSM PIN (for HSM objects) | - |
1547
+ | `-include-chain` | Include certificate chain | - |
1548
+ | `-delete-related` | Delete related private key | - |
1549
+
1550
+ ---
1551
+
473
1552
  ### DLL System Installation (Windows)
474
1553
 
475
1554
  For system-wide DLL access (required for signtool integration), install DLLs to System32:
@@ -562,11 +1641,22 @@ signercli -config set automation \
562
1641
  -host https://signer.example.com \
563
1642
  -output-format json
564
1643
 
1644
+ # Create a profile with API key (no login required)
1645
+ signercli -config set cert-api \
1646
+ -host https://signer.example.com:7443 \
1647
+ -api-key cdk_e2f369e7c85bfa7835d375f6b088f15dac2c2d8ebeb0815c392a6d6b34ee916f
1648
+
565
1649
  # Use the profile
566
1650
  signercli -login -profile production
567
- signercli myapp.exe -profile production
1651
+ signercli myapp.exe -profile production # Implicit form
1652
+ signercli -sign myapp.exe -profile production # Explicit form (same result)
568
1653
  signercli document.pdf -profile pdf-signing
569
1654
  signercli -verify myapp.exe -profile automation # Outputs JSON automatically
1655
+
1656
+ # Use API key profile (no login required)
1657
+ signercli -cert list -profile cert-api
1658
+ signercli -cert get <id> -profile cert-api
1659
+ signercli -cert upload cert.pem -profile cert-api
570
1660
  ```
571
1661
 
572
1662
  ## Supported File Types
@@ -589,11 +1679,13 @@ signercli -verify myapp.exe -profile automation # Outputs JSON automatically
589
1679
  └── bin/
590
1680
  ├── signercli.js # Cross-platform wrapper
591
1681
  ├── signer.js # Windows KSP wrapper
1682
+ ├── linux-x64/
1683
+ │ └── signercli # Fully static binary (no dynamic dependencies)
592
1684
  └── 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)
1685
+ ├── signercli.exe # Static build
1686
+ ├── signer.exe # Static build
1687
+ ├── otpkey.dll # Static linked
1688
+ └── Certchip.dll # KSP provider
597
1689
  ```
598
1690
 
599
1691
  ### Binary Comparison
@@ -789,20 +1881,72 @@ On Linux/macOS, ensure the binary is executable:
789
1881
  chmod +x node_modules/@certchip/signer/bin/*/signercli
790
1882
  ```
791
1883
 
1884
+ ## Build from Source
1885
+
1886
+ ### Linux x64 (Fullstatic)
1887
+
1888
+ Build a fully static binary for Linux distribution (no dynamic library dependencies):
1889
+
1890
+ ```bash
1891
+ cd core/signer-cli
1892
+
1893
+ # Fullstatic build (auto-builds libcurl.a if missing)
1894
+ ./build_fullstatic_linux_x64.sh
1895
+
1896
+ # Or step by step:
1897
+ ./build_fullstatic_linux_x64.sh --check # Check static library dependencies
1898
+ ./build_fullstatic_linux_x64.sh --build-curl # Build static libcurl if missing
1899
+ ./build_fullstatic_linux_x64.sh # Build fullstatic binary
1900
+
1901
+ # Output: bin/linux-x64/signercli (fully static, no dynamic dependencies)
1902
+ ```
1903
+
1904
+ Required static libraries (in `../../libs/`):
1905
+ - OpenSSL 3.4.1 (`libssl.a`, `libcrypto.a`)
1906
+ - cJSON (`libcjson.a`)
1907
+ - json-c (`libjson-c.a`)
1908
+ - libcurl (`libcurl.a`)
1909
+ - libotpkey (`libotpkey.a`)
1910
+
1911
+ ### Windows x64 (MSYS2)
1912
+
1913
+ ```bash
1914
+ cd core/signer-cli
1915
+
1916
+ # Static build for npm package
1917
+ make -f Makefile.msys2 STATIC_CURL=1 RELEASE=1
1918
+
1919
+ # Build + copy dependencies for npm
1920
+ make -f Makefile.msys2 npm-package
1921
+ ```
1922
+
1923
+ ### Debug Build (any platform)
1924
+
1925
+ ```bash
1926
+ cd core/signer-cli
1927
+ make # Debug build (auto-detects platform)
1928
+ make RELEASE=1 # Release build
1929
+ ```
1930
+
792
1931
  ## Requirements
793
1932
 
794
1933
  - **Node.js** >= 14.0.0
795
- - **Platforms**: Windows x64 (Linux x64/arm64, macOS x64/arm64 coming soon)
1934
+ - **Platforms**: Windows x64, Linux x64 (macOS x64/arm64 coming soon)
796
1935
  - **Server**: Certchip Signer API compatible server
797
1936
 
798
- > **Note:** The current npm package includes Windows x64 binaries only. Linux and macOS binaries will be added in a future release.
799
-
800
1937
  ## License
801
1938
 
802
- Copyright (c) 2025 Certchip. All rights reserved.
1939
+ Copyright (c) 2026 Certchip. All rights reserved.
803
1940
 
804
1941
  ## Links
805
1942
 
806
1943
  - [Homepage](https://certchip.com/signer)
807
1944
  - [Documentation](https://certchip.com/signer/help)
808
1945
  - [Issues](https://github.com/certchip/signer-cli/issues)
1946
+
1947
+ ## Additional Documentation
1948
+
1949
+ - [Configuration File Guide](docs/CONFIG-FILE-GUIDE.md) - Profile and config file options
1950
+ - [cert-dist Guide](docs/cert-dist-guide.md) - Let's Encrypt certificate distribution
1951
+ - [Server API Key Auth Guide](docs/SERVER-API-KEY-AUTH-GUIDE.md) - Server-side API key implementation
1952
+ - [Server Cert API Endpoints](docs/SERVER-CERT-API-ENDPOINTS.md) - Certificate API specification