@certchip/signer 0.1.15 → 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,11 +54,14 @@ 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 using Windows signtool.exe
52
- signtool sign /n "Your Certificate CN" /fd sha256 /tr http://timestamp.digicert.com /td sha256 myapp.exe
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
60
+ signer myapp.exe -o myapp_signed.exe # Specify output file
61
+ signer myapp.exe -file-upload -save-signed # Upload file, save with _signed suffix
53
62
 
54
- # Or sign directly with signer
55
- signer myapp.exe
63
+ # Or use Windows signtool.exe (after login)
64
+ signtool sign /n "Your Certificate CN" /fd sha256 /tr http://timestamp.digicert.com /td sha256 myapp.exe
56
65
 
57
66
  # Logout (removes certificate from store)
58
67
  signer -logout
@@ -72,25 +81,100 @@ npx signer myapp.exe
72
81
 
73
82
  ## CLI Commands
74
83
 
75
- This package provides two CLI tools with different purposes:
84
+ This package provides two CLI tools with different capabilities:
85
+
86
+ ### Tool Comparison Overview
76
87
 
77
88
  | | signercli | signer |
78
89
  |---|-----------|--------|
79
- | **Purpose** | Direct file signing | Windows signtool integration |
90
+ | **Purpose** | Full-featured signing and certificate management | Windows signtool.exe integration + direct signing |
80
91
  | **Platform** | Windows, Linux, macOS | Windows only |
81
- | **How it works** | Signs files directly via server API | Provides certificates to Windows crypto system |
82
- | **Best for** | CI/CD, cross-platform, simple signing | Windows developers using signtool.exe |
83
-
84
- ### When to use which tool?
85
-
86
- | Scenario | Recommended |
87
- |----------|-------------|
88
- | CI/CD pipeline (any platform) | signercli |
89
- | Linux/macOS development | signercli |
90
- | Simple file signing | signercli |
91
- | Using Windows signtool.exe | signer |
92
- | Windows certificate store integration | signer |
93
- | 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 |
94
178
 
95
179
  ---
96
180
 
@@ -127,10 +211,12 @@ signercli -logout [url]
127
211
 
128
212
  ```bash
129
213
  # Basic signing (default: hash-only mode)
130
- signercli <file>
214
+ signercli <file> # Implicit form
215
+ signercli -sign <file> # Explicit form (same result)
131
216
 
132
217
  # Signing options
133
218
  signercli <file> -o <output> # Specify output file
219
+ signercli -sign <file> -o <output> # Explicit form
134
220
  signercli <file> -save-signed # Save with _signed suffix (preserve original)
135
221
  signercli <file> -hash-only # Hash-based signing (default)
136
222
  signercli <file> -file-upload # Upload entire file to server
@@ -139,6 +225,8 @@ signercli <file> -timestamp-url <url> # Timestamp server URL
139
225
  signercli <file> -profile <name> # Use config profile
140
226
  ```
141
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
+
142
230
  > **Note:** Hash-only signing is the default mode. Only the file hash is sent to the server, not the entire file.
143
231
 
144
232
  #### Signature Verification
@@ -172,9 +260,17 @@ signercli -codesign-set <password>
172
260
 
173
261
  ```bash
174
262
  # List certificates (with purpose filter)
175
- signercli -cert -list # List all certificates
176
- signercli -cert -list codesign # List code signing certificates
177
- 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
178
274
 
179
275
  # Get/Set certificate ID
180
276
  signercli -cert -id # Show current configuration
@@ -192,37 +288,151 @@ signercli -cert -password <password>
192
288
 
193
289
  #### Configuration
194
290
 
195
- 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:**
196
337
 
197
338
  ```bash
198
339
  # View configuration
199
- signercli -config # Show config file
340
+ signercli -config # Show entire config file
200
341
  signercli -config list # List all profiles
201
- signercli -config show <name> # Show profile details
342
+ signercli -config show <name> # Show specific profile details
202
343
 
203
- # Create/Update profile
204
- signercli -config set <name> [options]
344
+ # Create/Update profile (profile name defaults to 'default' if omitted)
345
+ signercli -config set [name] [options]
205
346
 
206
- # Delete profile
347
+ # Remove specific settings from profile
348
+ signercli -config unset [name] <options>
349
+
350
+ # Delete entire profile
207
351
  signercli -config delete <name>
208
352
  ```
209
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
+
210
389
  **Profile Inheritance Example:**
211
390
 
212
391
  ```bash
213
- # Set common settings in 'default' profile
214
- 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
215
397
 
216
- # Create 'production' profile (inherits host and username from default)
398
+ # Create production profile (inherits host, api_key, hash-algorithm)
217
399
  signercli -config set production -cert-id prod-cert-001
218
400
 
219
- # Create 'staging' profile with different host (overrides default)
220
- 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
221
405
 
222
406
  # Usage
223
- signercli -login # Uses 'default' profile
224
- signercli -login -profile production # Uses 'production' (inherits from default)
225
- 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)
226
436
  ```
227
437
 
228
438
  **Profile Options:**
@@ -232,14 +442,15 @@ signercli -login -profile staging # Uses 'staging' (overrides host)
232
442
  | `-host <url>` | Server URL |
233
443
  | `-ssh-key-path <path>` | SSH private key path |
234
444
  | `-username <name>` | SSH username |
235
- | `-user <id>` | Password auth user ID |
445
+ | `-user <id>` | User ID for password auth |
446
+ | `-api-key <key>` | API key (bypasses login) |
236
447
  | `-cert-id <id>` | Default certificate ID |
237
448
  | `-cert-serial <sn>` | Certificate serial number |
238
449
  | `-expires <time>` | Token expiration (24h, 7d, 1w) |
239
450
  | `-include-chain` | Include certificate chain |
240
451
  | `-timestamp-url <url>` | Timestamp server URL |
241
- | `-hash-algorithm <alg>` | Default hash algorithm |
242
- | `-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) |
243
454
 
244
455
  **Document Signing Options:**
245
456
 
@@ -248,9 +459,34 @@ signercli -login -profile staging # Uses 'staging' (overrides host)
248
459
  | `-doc-style <style>` | watermark, box, barcode, qrcode |
249
460
  | `-doc-position <pos>` | bottom-right, bottom-left, top-right, top-left, center |
250
461
  | `-doc-sig-position <pos>` | left, center, right (for barcode/qrcode) |
251
- | `-doc-font-size <size>` | Font size for signature |
462
+ | `-doc-font-size <size>` | Signature font size |
252
463
  | `-doc-opacity <value>` | Opacity (0.0-1.0 or 0-100) |
253
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
+
254
490
  #### Windows DLL Installation
255
491
 
256
492
  ```bash
@@ -273,6 +509,33 @@ signercli <file> LOG_INF # Info output
273
509
  # Available: LOG_NON, LOG_ERR, LOG_WRN, LOG_DBG, LOG_INF
274
510
  ```
275
511
 
512
+ **Version Output:**
513
+
514
+ The `-version` command displays comprehensive version information:
515
+
516
+ ```
517
+ # signercli -version
518
+ Certchip Signer CLI v0.1.27
519
+ Cross-platform code and document signing tool
520
+ Copyright (c) 2025 Certchip. All rights reserved.
521
+
522
+ DLL Versions (Local):
523
+ otpkey.dll: 0.1.27.0
524
+ Certchip.dll: 0.1.27.0
525
+
526
+ DLL Versions (System32):
527
+ otpkey.dll: 0.1.27.0
528
+ Certchip.dll: 0.1.27.0
529
+ ```
530
+
531
+ | Information | Description |
532
+ |-------------|-------------|
533
+ | CLI Version | signercli/signer executable version |
534
+ | Local DLL | DLL versions in the same directory as the executable |
535
+ | System32 DLL | DLL versions installed in Windows System32 folder |
536
+
537
+ > **Note:** DLL version information is Windows-only. On Linux/macOS, only the CLI version is displayed.
538
+
276
539
  #### Output Format
277
540
 
278
541
  Both `signercli` and `signer` support structured output formats for scripting and automation.
@@ -361,19 +624,25 @@ $ signercli -login https://signer.example.com admin -pw secret -format json
361
624
 
362
625
  ### signer (Windows only)
363
626
 
364
- Windows-specific tool that integrates with the Windows cryptographic system via KSP (Key Storage Provider). Instead of signing files directly, it registers certificates in the Windows certificate store, allowing you to use standard Windows tools like `signtool.exe`.
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`.
365
628
 
366
- **How it works:**
367
- 1. Login fetches your certificate from the server
368
- 2. Certificate is registered in Windows certificate store
369
- 3. KSP provider enables private key operations via the server
370
- 4. Use `signtool.exe` or other Windows signing tools normally
629
+ **Two signing methods:**
630
+ 1. **Direct signing** - Sign files directly with `signer <file>` or `signer -sign <file>` (same as signercli)
631
+ 2. **signtool integration** - Login to register certificate, then use Windows signtool.exe
371
632
 
372
633
  ```bash
373
634
  # Authentication (fetches certificate to Windows store)
374
635
  signer -login <url> [username] # Login and register certificate
375
636
  signer -logout # Logout and remove certificate
376
- signer -list # List available certificates
637
+
638
+ # File Signing (direct - same options as signercli)
639
+ signer <file> [options] # Sign a file (implicit form)
640
+ signer -sign <file> [options] # Sign a file (explicit form)
641
+ -o <path> # Output file path
642
+ -hash-only # Hash-based signing (default)
643
+ -file-upload # Upload entire file to server
644
+ -save-signed # Save with _signed suffix
645
+ -profile <name> # Use specific signing profile
377
646
 
378
647
  # Certificate Management
379
648
  signer -cert -list # List available certificates
@@ -393,11 +662,889 @@ signer -container # List key containers
393
662
  signer -install # Install DLLs to System32
394
663
  signer -uninstall # Remove DLLs from System32
395
664
 
396
- # After login, use standard Windows signing tools
665
+ # Version & Help
666
+ signer -version # Show version and DLL info
667
+ signer -help # Show usage help
668
+
669
+ # After login, use standard Windows signing tools (signtool integration)
397
670
  signtool sign /n "Certificate Name" /fd sha256 myapp.exe
398
671
  signtool sign /sha1 <thumbprint> /fd sha256 /tr http://timestamp.digicert.com myapp.exe
399
672
  ```
400
673
 
674
+ **Examples:**
675
+ ```bash
676
+ # Direct signing with output path (two equivalent forms)
677
+ signer myapp.exe -o myapp_signed.exe
678
+ signer -sign myapp.exe -o myapp_signed.exe
679
+
680
+ # Upload entire file for signing
681
+ signer myapp.exe -file-upload -o myapp_signed.exe
682
+
683
+ # Hash-only signing with _signed suffix
684
+ signer myapp.exe -save-signed
685
+ signer -sign myapp.exe -save-signed
686
+ ```
687
+
688
+ **Version Output:**
689
+
690
+ ```
691
+ # signer -version
692
+ Certchip Signer v0.1.27
693
+ Windows Key Storage Provider and Code Signing Tool
694
+ Copyright (c) 2025 Certchip. All rights reserved.
695
+
696
+ DLL Versions (Local):
697
+ otpkey.dll: 0.1.27.0
698
+ Certchip.dll: 0.1.27.0
699
+
700
+ DLL Versions (System32):
701
+ otpkey.dll: 0.1.27.0
702
+ Certchip.dll: 0.1.27.0
703
+ ```
704
+
705
+ The version output helps diagnose DLL version mismatches between local and system-wide installations.
706
+
707
+ ---
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
+
401
1548
  ---
402
1549
 
403
1550
  ### DLL System Installation (Windows)
@@ -492,11 +1639,22 @@ signercli -config set automation \
492
1639
  -host https://signer.example.com \
493
1640
  -output-format json
494
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
+
495
1647
  # Use the profile
496
1648
  signercli -login -profile production
497
- signercli myapp.exe -profile production
1649
+ signercli myapp.exe -profile production # Implicit form
1650
+ signercli -sign myapp.exe -profile production # Explicit form (same result)
498
1651
  signercli document.pdf -profile pdf-signing
499
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
500
1658
  ```
501
1659
 
502
1660
  ## Supported File Types
@@ -519,11 +1677,13 @@ signercli -verify myapp.exe -profile automation # Outputs JSON automatically
519
1677
  └── bin/
520
1678
  ├── signercli.js # Cross-platform wrapper
521
1679
  ├── signer.js # Windows KSP wrapper
1680
+ ├── linux-x64/
1681
+ │ └── signercli # Fully static binary (no dynamic dependencies)
522
1682
  └── win32-x64/
523
- ├── signercli.exe # 9.3 MB (static build)
524
- ├── signer.exe # 420 KB (static build)
525
- ├── otpkey.dll # 6.2 MB (static linked)
526
- └── 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
527
1687
  ```
528
1688
 
529
1689
  ### Binary Comparison
@@ -533,7 +1693,7 @@ signercli -verify myapp.exe -profile automation # Outputs JSON automatically
533
1693
  | **Platform** | Windows, Linux, macOS | Windows only |
534
1694
  | **Dependencies** | None (static build) | otpkey.dll, Certchip.dll |
535
1695
  | **Size** | 9.3 MB | 420 KB + 6.9 MB DLLs |
536
- | **Signing method** | Direct (via server API) | Indirect (via Windows crypto) |
1696
+ | **Signing method** | Direct (via server API) | Direct OR via Windows crypto (signtool) |
537
1697
  | **Windows KSP** | No | Yes |
538
1698
  | **signtool compatible** | No | Yes |
539
1699
  | **UAC auto-elevation** | Yes | Yes |
@@ -719,14 +1879,59 @@ On Linux/macOS, ensure the binary is executable:
719
1879
  chmod +x node_modules/@certchip/signer/bin/*/signercli
720
1880
  ```
721
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
+
722
1929
  ## Requirements
723
1930
 
724
1931
  - **Node.js** >= 14.0.0
725
- - **Platforms**: Windows x64 (Linux x64/arm64, macOS x64/arm64 coming soon)
1932
+ - **Platforms**: Windows x64, Linux x64 (macOS x64/arm64 coming soon)
726
1933
  - **Server**: Certchip Signer API compatible server
727
1934
 
728
- > **Note:** The current npm package includes Windows x64 binaries only. Linux and macOS binaries will be added in a future release.
729
-
730
1935
  ## License
731
1936
 
732
1937
  Copyright (c) 2025 Certchip. All rights reserved.
@@ -736,3 +1941,10 @@ Copyright (c) 2025 Certchip. All rights reserved.
736
1941
  - [Homepage](https://certchip.com/signer)
737
1942
  - [Documentation](https://certchip.com/signer/help)
738
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