-
-
Notifications
You must be signed in to change notification settings - Fork 118
/
Copy pathindex.html
1145 lines (927 loc) · 51.1 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8' />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="description" content="Jsign : Authenticode signing tool in Java for signing Windows executable files, Microsoft Installers (MSI), Cabinet files (CAB), Catalog files (CAT), Windows packages (APPX/MSIX), Microsoft Dynamics 365 extension packages, NuGet packages and scripts (PowerShell, VBScript, JScript, WSF)" />
<meta name="google-site-verification" content="p912kgAnTBOzVbswrU43k3FXUbPnxLHdeW6xsVcq1uU" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="scripts/prettify/run_prettify.js"></script>
<link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
<title>Jsign - Versatile code signing tool for Windows executable files, installers and scripts</title>
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
<a id="forkme_banner" href="https://github.com/ebourg/jsign">View on GitHub</a>
<h1 id="project_title">Jsign</h1>
<h2 id="project_tagline">Versatile code signing tool for Windows executable files, installers and scripts</h2>
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
<p>Jsign is a versatile code signing tool that allows you to sign and timestamp
Windows executable files, installer packages and scripts. Jsign is platform
independent and provides an alternative to native tools like signtool on Windows
or the Mono development tools on Unix systems. It's particularly well-suited for
signing executable wrappers and installers generated by tools such as
<a href="http://nsis.sourceforge.net">NSIS</a>, <a href="https://wiki.gnome.org/msitools">msitools</a>,
<a href="https://www.ej-technologies.com/products/install4j/overview.html">install4j</a>,
<a href="https://www.ej-technologies.com/download/exe4j/files">exe4j</a>
or <a href="http://launch4j.sourceforge.net">launch4j</a>. It emphasizes on seamless
integration with cloud key management systems and hardware tokens.</p>
<p>Jsign is available as a <a href="#cli">command line tool</a> for Linux, macOS and Windows, as a task/plugin
for various build systems (<a href="#maven">Maven</a>, <a href="#gradle">Gradle</a>, <a href="#ant">Ant</a>,
<a href="#github-actions">GitHub Actions</a>), and as a <a href="#api">Java library</a>.</p>
<p>Jsign is free to use and licensed under the Apache License version 2.0.</p>
<h3 id="features">Features</h3>
<ul>
<li>Platform independent signing of Windows executables, DLLs, Microsoft Installers (MSI), Cabinet files (CAB), Catalog files (CAT), Windows packages (APPX/MSIX), Microsoft Dynamics 365 extension packages, NuGet packages and scripts (PowerShell, VBScript, JScript, WSF)</li>
<li>Timestamping with retries and fallback on alternative servers (RFC 3161 and Authenticode protocols supported)</li>
<li>Supports multiple signatures per file, for all file types</li>
<li>Extracts and embeds detached signatures to support <a href="https://reproducible-builds.org/docs/embedded-signatures/">reproducible builds</a></li>
<li>Certificate chain completion</li>
<li>Hashing algorithms: MD5, SHA-1, SHA-256, SHA-384 and SHA-512</li>
<li>Keystores supported:
<ul>
<li>PKCS#12, JKS and JCEKS files</li>
<li>PKCS#11 hardware tokens (<a href="https://www.yubico.com">YubiKey</a>, <a href="https://www.nitrokey.com">Nitrokey</a>, <a href="https://cpl.thalesgroup.com/access-management/authenticators/pki-usb-authentication">SafeNet eToken</a>, etc)</li>
<li>Cloud key management systems:
<ul>
<li><a href="https://aws.amazon.com/kms/">AWS KMS</a></li>
<li><a href="https://azure.microsoft.com/services/key-vault/">Azure Key Vault</a></li>
<li><a href="https://learn.microsoft.com/en-us/azure/trusted-signing/">Azure Trusted Signing</a></li>
<li><a href="https://www.digicert.com/digicert-one">DigiCert ONE</a> / <a href="https://docs.digicert.com/en/digicert-keylocker.html">DigiCert KeyLocker</a></li>
<li><a href="https://garantir.io/garasign/">GaraSign</a></li>
<li><a href="https://cloud.google.com/security-key-management">Google Cloud KMS</a></li>
<li><a href="https://www.vaultproject.io">HashiCorp Vault</a></li>
<li><a href="https://www.signserver.org">Keyfactor SignServer</a></li>
<li><a href="https://www.oracle.com/security/cloud-security/key-management/">Oracle Cloud KMS</a></li>
<li><a href="https://signpath.io">SignPath</a></li>
<li><a href="https://www.ssl.com/esigner/">SSL.com eSigner</a></li>
</ul>
</li>
</ul>
<li>Private key formats: PVK and PEM (PKCS#1 and PKCS#8), encrypted or not</li>
<li>Certificates: PKCS#7 in PEM and DER format</li>
<li>Automatic download of the intermediate certificates</li>
<li>Build tools integration (<a href="#maven">Maven</a>, <a href="#gradle">Gradle</a>, <a href="#ant">Ant</a>, <a href="#github-actions">GitHub Actions</a>)</li>
<li>Command line signing tool</li>
<li>Authenticode signing API (<a href="https://javadoc.io/doc/net.jsign/jsign-core">Javadoc</a>)</li>
<li>JCA security provider to use the keystores supported by Jsign with other tools such as jarsigner or apksigner</li>
</ul>
<h3 id="files">Downloads</h3>
<ul>
<li><a href="https://github.com/ebourg/jsign/releases/download/7.1/jsign_7.1_all.deb">DEB package</a> (Debian/Ubuntu)</li>
<li><a href="https://github.com/ebourg/jsign/releases/download/7.1/jsign-7.1-1.noarch.rpm">RPM package</a> (RedHat/Fedora)</li>
<li><a href="https://community.chocolatey.org/packages/jsign/">Chocolatey package</a> (Windows)</li>
<li><a href="https://scoop.sh/#/apps?q=jsign&id=48a014807579e3b45a673676f26a17fff1f8e961">Scoop package</a> (Windows)</li>
<li><a href="https://formulae.brew.sh/formula/jsign">Homebrew package</a> (macOS/Linux)</li>
<li><a href="https://github.com/ebourg/jsign/releases/download/7.1/jsign-7.1.jar">All-in-one JAR</a> (Other systems, Ant task, JCA provider)</li>
</ul>
<h3 id="ant">Ant Task</h3>
<p>Here is an example showing how the signing works with Ant, using a Java keystore:</p>
<pre class="prettyprint lang-xml">
<taskdef name="jsign" classname="net.jsign.JsignTask" classpath="jsign-7.1.jar"/>
<jsign file="application.exe"
name="My Application"
url="http://www.example.com"
keystore="keystore.jks"
storepass="password"
alias="test"
tsaurl="http://timestamp.sectigo.com"/>
</pre>
<br>
<p>Another example with <code>SPC</code> and <code>PVK</code> files commonly used with <code>signcode.exe</code>:</p>
<pre class="prettyprint lang-xml">
<jsign file="application.exe"
certfile="certificate.spc"
keyfile="key.pvk"
keypass="password"
tsaurl="http://timestamp.digicert.com"/>
</pre>
<br>
<p>The task also accepts a fileset to sign multiple files:</p>
<pre class="prettyprint lang-xml">
<jsign keystore="keystore.p12"
storepass="password"
alias="test">
<fileset dir="build/binaries" includes="*.exe"/>
</jsign>
</pre>
<br>
<p>The <code>sign</code> command is used by default, but other commands can be specified with the <code>command</code>
attribute. For example for <a href="#tagging">tagging</a> a signed file with user identification data without
invalidating the signature:</p>
<pre class="prettyprint lang-xml">
<jsign command="tag" value="userid:1234-ABCD-5678-EFGH" file="application.exe"/>
</pre>
<br><br>
<h4 id="attributes" class="mobile-only">Attributes</h4>
<table style="border-collapse: collapse; width: 100%">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
<th align="center" width="25%">Required</th>
</tr>
</thead>
<tbody>
<tr>
<td class="attribute">file</td>
<td class="description">
The file to be signed. The supported files are Windows executables (EXE), DLLs, Microsoft Installers (MSI),
Cabinet files (CAB), Catalog files (CAT), Windows packages (APPX/MSIX), Microsoft Dynamics 365 extension
packages, NuGet packages and scripts (PowerShell, VBScript, JScript, WSF)</td>
<td class="required">Yes, unless a fileset is specified.</td>
</tr>
<tr>
<td class="attribute">name</td>
<td class="description">The name of the application</td>
<td class="required">No</td>
</tr>
<tr>
<td class="attribute">url</td>
<td class="description">The URL of the application</td>
<td class="required">No</td>
</tr>
<tr>
<td class="attribute">keystore</td>
<td class="description">
The keystore file, the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html#Config">SunPKCS11 configuration file</a>,
the cloud keystore name, or the smart card or hardware token name.
</td>
<td class="required">Yes for file based keystores, PKCS#11 and cloud signing services. Optional for cards/tokens.
No when <code>certfile</code> and <code>keyfile</code> are specified.</td>
</tr>
<tr>
<td class="attribute">storepass</td>
<td class="description">
The password to open the keystore. The password can be loaded from a file by using the <code>file:</code> prefix
followed by the path of the file, or from an environment variable by using the <code>env:</code> prefix followed
by the name of the variable.
</td>
<td class="required">No</td>
</tr>
<tr>
<td class="attribute">storetype</td>
<td class="description">
The type of the keystore.
<p>File based:</p>
<ul>
<li><code>JKS</code>: Java keystore (<code>.jks</code> files)</li>
<li><code>JCEKS</code>: SunJCE keystore (<code>.jceks</code> files)</li>
<li><code>PKCS12</code>: Standard PKCS#12 keystore (<code>.p12</code> or <code>.pfx</code> files)</li>
</ul>
<p>Hardware tokens:</p>
<ul>
<li><code>PKCS11</code>: PKCS#11 hardware token</li>
<li><code>ETOKEN</code>: SafeNet eToken</li>
<li><code>NITROKEY</code>: Nitrokey HSM</li>
<li><code>OPENPGP</code>: OpenPGP card</li>
<li><code>OPENSC</code>: Smart card</li>
<li><code>PIV</code>: PIV card</li>
<li><code>YUBIKEY</code>: YubiKey security key (requires ykcs11)</li>
</ul>
<p>Cloud key management systems:</p>
<ul>
<li><code>AWS</code>: AWS Key Management Service</li>
<li><code>AZUREKEYVAULT</code>: Azure Key Vault key management system</li>
<li><code>DIGICERTONE</code>: DigiCert ONE Secure Software Manager</li>
<li><code>ESIGNER</code>: SSL.com eSigner</li>
<li><code>GARASIGN</code>: Garantir Remote Signing</li>
<li><code>GOOGLECLOUD</code>: Google Cloud KMS</li>
<li><code>HASHICORPVAULT</code>: HashiCorp Vault</li>
<li><code>ORACLECLOUD</code>: Oracle Cloud Key Management Service</li>
<li><code>SIGNPATH</code>: SignPath</li>
<li><code>SIGNSERVER</code>: Keyfactor SignServer</li>
<li><code>TRUSTEDSIGNING</code>: Azure Trusted Signing</li>
</ul>
</td>
<td class="required">No, automatically detected for file based keystores.</td>
</tr>
<tr>
<td class="attribute">alias</td>
<td class="description">The alias of the certificate used for signing in the keystore.</td>
<td class="required">Yes, if <code>keystore</code> is specified and more than one alias exist</td>
</tr>
<tr>
<td class="attribute">certfile</td>
<td class="description">
The file containing the PKCS#7 certificate chain, in PEM or DER format (<code>.p7b</code> or <code>.spc</code>
files). This parameter is required if <code>keystore</code> isn't specified, or if the keystore used contains
only the key and not the certificate chain. It may be specified if the keystore holds only the signing
certificate and not the full certificate chain, otherwise Jsign will attempt to download the missing
certificates from the URL specified in the Authority Information Access field of the certificates.
This parameter can also be used to replace the certificate chain from the keystore.
</td>
<td class="required" rowspan="2">No, depends on the keystore used.</td>
</tr>
<tr>
<td class="attribute">keyfile</td>
<td class="description">
The file containing the private key. <code>PEM</code> and <code>PVK</code> files are supported.
</td>
</tr>
<tr>
<td class="attribute">keypass</td>
<td class="description">
The password of the private key. When using a keystore, this parameter can be omitted if the keystore shares
the same password. The password can be loaded from a file by using the <code>file:</code> prefix followed by
the path of the file, or from an environment variable by using the <code>env:</code> prefix followed by the
name of the variable.
</td>
<td class="required">No</td>
</tr>
<tr>
<td class="attribute">alg</td>
<td class="description">
The digest algorithm (SHA-1, SHA-256, SHA-384 or SHA-512).
</td>
<td class="required">No; defaults to SHA-256 or a format specific value</td>
</tr>
<tr>
<td class="attribute">tsaurl</td>
<td class="description">
The URL of the timestamping authority, either RFC 3161 or Authenticode services.
You can use for example the Sectigo (http://timestamp.sectigo.com)
or the DigiCert (http://timestamp.digicert.com) services.<br>
Several URLs separated by a comma can be specified to fallback on alternative servers.
</td>
<td class="required">No</td>
</tr>
<tr>
<td class="attribute">tsmode</td>
<td class="description">The timestamping mode (RFC3161 or Authenticode)</td>
<td class="required">No; defaults to Authenticode</td>
</tr>
<tr>
<td class="attribute">tsretries</td>
<td class="description">The number of retries for timestamping</td>
<td class="required">No; defaults to 3</td>
</tr>
<tr>
<td class="attribute">tsretrywait</td>
<td class="description">The number of seconds to wait between timestamping retries</td>
<td class="required">No; defaults to 10 seconds</td>
</tr>
<tr>
<td class="attribute">replace</td>
<td class="description">Tells if previous signatures should be replaced.</td>
<td class="required">No; defaults to "false"</td>
</tr>
<tr>
<td class="attribute">encoding</td>
<td class="description">The encoding of the script to be signed (if it doesn't contain a byte order mark).</td>
<td class="required">No; defaults to "UTF-8"</td>
</tr>
<tr>
<td class="attribute">detached</td>
<td class="description">
Tells if a detached signature should be generated or reused. The detached signature
is a file in the same directory using the name of the file signed with the <code>.sig</code>
suffix added (for example <code>application.exe.sig</code>).
<ul>
<li>If the signature doesn't exist, the file is signed as usual and the detached signature is generated.</li>
<li>If the signature exists it is attached to the file, replacing any existing signature (in this case
the private key isn't used for signing and no timestamping is performed).</li>
</ul>
</td>
<td class="required">No; defaults to "false"</td>
</tr>
<tr>
<td class="attribute">value</td>
<td class="description">
The value of the unsigned attribute when tagging a file. The value is either:
<ul>
<li>a string (such as a user id, a license key or a JWT token)</li>
<li>the name of the file to include, prefixed with <code>file:</code>
<li>a binary value in hexadecimal format, prefixed with <code>0x</code>
</ul>
<p>If no value is specified a default 1KB template is used, filled with zeros and delimited by
<code style="white-space: nowrap">-----BEGIN TAG-----</code> and
<code style="white-space: nowrap">-----END TAG-----</code> markers.</p>
</td>
<td class="required">No; defaults to 1KB template</td>
</tr>
</tbody>
</table>
<h3 id="maven">Maven plugin</h3>
<p>Here is an example showing how the signing works with Maven. The parameters
are the same as those described above for the Ant task. The execution is bound
by default to the <code>package</code> phase.</p>
<pre class="prettyprint lang-xml">
<build>
<plugins>
<plugin>
<groupId>net.jsign</groupId>
<artifactId>jsign-maven-plugin</artifactId>
<version>7.1</version>
<executions>
<execution>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<file>application.exe</file>
<name>My Application</name>
<url>http://www.example.com</url>
<keystore>keystore.jks</keystore>
<alias>test</alias>
<storepass>password</storepass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</pre>
<p>It's possible to sign multiple files by using a <code>fileset</code> element instead of <code>file</code>:</p>
<pre class="prettyprint lang-xml">
...
<configuration>
<fileset>
<directory>target</directory>
<includes>
<include>*.exe</include>
</includes>
</fileset>
<keystore>keystore.jks</keystore>
<alias>test</alias>
<storepass>password</storepass>
</configuration>
...
</pre>
<p>The value of the <code>storepass</code> and <code>keypass</code> elements can be encrypted using the
<a href="https://maven.apache.org/guides/mini/guide-encryption.html">Maven master password</a>:</p>
<pre class="prettyprint lang-xml">
<configuration>
<file>application.exe</file>
<keystore>keystore.jks</keystore>
<storepass>{COQLCE6DU6GtcS5P=}</storepass>
</configuration>
</pre>
<p>The <code>storepass</code> and <code>keypass</code> elements may also reference a password defined
in the <a href="https://maven.apache.org/settings.html">Maven settings file</a>.</p>
<p>In <code> ${user.home}/.m2/settings.xml</code> a server is defined with the password of the keystore:</p>
<pre class="prettyprint lang-xml">
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
...
<servers>
<server>
<id>keystore</id>
<password>password</password>
</server>
</servers>
...
</settings>
</pre>
<p>And in the Maven project file, the password element references the server id prefixed with <code>mvn:</code>:</p>
<pre class="prettyprint lang-xml">
<configuration>
<file>application.exe</file>
<keystore>keystore.jks</keystore>
<storepass>mvn:keystore</storepass>
</configuration>
</pre>
<h3 id="gradle">Gradle plugin</h3>
<p>Here is an example showing how to use Jsign with Gradle. The parameters
are the same as those described above for the Ant task.</p>
<p>With the Groovy syntax:</p>
<pre class="prettyprint lang-groovy">
plugins {
id 'net.jsign' version '7.1'
}
task sign {
doLast {
jsign(file : 'application.exe',
name : 'My Application',
url : 'http://www.example.com',
keystore : 'keystore.p12',
alias : 'test',
storepass : 'secret',
tsaurl : 'http://timestamp.sectigo.com')
}
}
</pre>
<p>With the Kotlin syntax:</p>
<pre class="prettyprint lang-kotlin">
plugins {
id("net.jsign") version "7.1"
}
task("sign") {
doLast {
val jsign = project.extensions.getByName("jsign") as groovy.lang.Closure<*>
jsign("file" to "application.exe",
"name" to "My Application",
"url" to "http://www.example.com",
"keystore" to "keystore.p12",
"alias" to "test",
"storepass" to "secret",
"tsaurl" to "http://timestamp.sectigo.com")
}
}
</pre>
<h3 id="github-actions">GitHub Actions</h3>
<p>Jsign can be used in GitHub Actions by inserting the following steps in the workflow:</p>
<pre class="prettyprint lang-yaml">
steps:
[...]
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'temurin'
- name: Download Jsign
run: wget https://github.com/ebourg/jsign/releases/download/7.1/jsign-7.1.jar
- name: Sign
run: >
java -jar jsign-7.1.jar --storetype TRUSTEDSIGNING
--keystore weu.codesigning.azure.net
--storepass ${{ secrets.AZURE_ACCESS_TOKEN }}
--alias <account>/<profile>
${{ github.workspace }}/dist/application.exe
</pre>
<h3 id="cli">Command Line Tool</h3>
<p>On systems with an <a href="#files">installation package</a> available the command line is invoked with:</p>
<pre> jsign [OPTIONS] [FILE]...</pre>
<p>On other systems the command line is invoked by running the jar with:</p>
<pre> java -jar jsign-7.1.jar [OPTIONS] [FILE]...</pre>
<p>The parameters expected are the same as those used by the Ant task:</p>
<pre>
usage: jsign [COMMAND] [OPTIONS] [FILE] [PATTERN] [@FILELIST]...
Sign and timestamp Windows executable files, Microsoft Installers (MSI), Cabinet
files (CAB), Catalog files (CAT), Windows packages (APPX/MSIX), Microsoft Dynamics
365 extension packages, NuGet packages and scripts (PowerShell, VBScript, JScript, WSF)
commands: sign (default), timestamp, extract, remove, tag
sign:
-s,--keystore <FILE> The keystore file, the SunPKCS11 configuration file,
the cloud keystore name, or the card/token name
--storepass <PASSWORD> The password to open the keystore
--storetype <TYPE> The type of the keystore
File based:
- JKS: Java keystore (.jks files)
- JCEKS: SunJCE keystore (.jceks files)
- PKCS12: Standard PKCS#12 keystore (.p12 or .pfx files)
Hardware tokens:
- PKCS11: PKCS#11 hardware token
- ETOKEN: SafeNet eToken
- NITROKEY: Nitrokey HSM
- OPENPGP: OpenPGP card
- OPENSC: Smart card
- PIV: PIV card
- YUBIKEY: YubiKey security key
Cloud key management systems:
- AWS: AWS Key Management Service
- AZUREKEYVAULT: Azure Key Vault key management system
- DIGICERTONE: DigiCert ONE Secure Software Manager
- ESIGNER: SSL.com eSigner
- GARASIGN: Garantir Remote Signing
- GOOGLECLOUD: Google Cloud KMS
- HASHICORPVAULT: HashiCorp Vault
- ORACLECLOUD: Oracle Cloud Key Management Service
- SIGNPATH: SignPath
- SIGNSERVER: Keyfactor SignServer
- TRUSTEDSIGNING: Azure Trusted Signing
-a,--alias <NAME> The alias of the certificate used for signing in the keystore
--keypass <PASSWORD> The password of the private key. When using a keystore,
this parameter can be omitted if the keystore shares the
same password
--keyfile <FILE> The file containing the private key (supports PEM & PVK files)
-c,--certfile <FILE> The file containing the PKCS#7 certificate chain
(.p7b or .spc files).
-d,--alg <ALGORITHM> The digest algorithm (SHA-1, SHA-256, SHA-384 or SHA-512)
-t,--tsaurl <URL> The URL of the timestamping authority
-m,--tsmode <MODE> The timestamping mode (RFC3161 or Authenticode)
-r,--tsretries <NUMBER> The number of retries for timestamping
-w,--tsretrywait <SECONDS> The number of seconds to wait between timestamping retries
-n,--name <NAME> The name of the application
-u,--url <URL> The URL of the application
--proxyUrl <URL> The URL of the HTTP proxy
--proxyUser <NAME> The user for the HTTP proxy. If a user is needed
--proxyPass <PASSWORD> The password for the HTTP proxy user. If a user is needed
--replace Tells if the previous signatures should be replaced
-e,--encoding <ENCODING> The encoding of the script to be signed (UTF-8 by default,
or the encoding specified by the byte order mark if there is one)
--detached Tells if a detached signature should be generated or reused
--quiet Print only error messages
--verbose Print more information
--debug Print debugging information
-h,--help Print the help
timestamp:
-t,--tsaurl <URL> The URL of the timestamping authority
-m,--tsmode <MODE> The timestamping mode (RFC3161 or Authenticode)
-r,--tsretries <NUMBER> The number of retries for timestamping
-w,--tsretrywait <SECONDS> The number of seconds to wait between timestamping retries
--proxyUrl <URL> The URL of the HTTP proxy
--proxyUser <NAME> The user for the HTTP proxy. If a user is needed
--proxyPass <PASSWORD> The password for the HTTP proxy user. If a user is needed
--replace Tells if the previous timestamps should be replaced
extract:
--format <FORMAT> The output format of the signature (DER or PEM)
tag:
--value <VALUE> The value of the unsigned attribute
</pre>
<p>After the options Jsign accepts one or more files to sign as arguments. The arguments may contain <code>'*'</code>
or <code>'**'</code> wildcards to match multiple files and scan through directories recursively. For example using
<code>build/*.exe</code> will sign the executables in the build directory, and <code>installdir/**/*.dll</code> will
scan the installdir directory recursively and sign all the DLLs found. If an argument starts with @ it is considered
as a text file containing a list of files to sign, one per line.</p>
<h3 id="examples">Examples</h3>
<h4 id="example-jks">Signing with a Java keystore</h4>
<pre>
jsign --keystore keystore.jks --storepass password --alias test \
--tsaurl http://timestamp.sectigo.com application.exe
</pre>
<h4 id="example-spc-pkv">Signing with a SPC certificate and a PVK key</h4>
<pre>
jsign --certfile certificate.spc --keyfile key.pvk --keypass password application.exe
</pre>
<h4 id="example-yubikey">Signing with a YubiKey</h4>
<p>When using a Yubikey, the alias is required only if the device contains more than one certificate.
The certificate is specified by its name (typically <em>X.509 Certificate for Digital Signature</em> for
the slot 9c, or <em>X.509 Certificate for PIV Authentication</em> for the slot 9a). The ykcs11 library
from the <a href="https://developers.yubico.com/yubico-piv-tool/">Yubico PIV Tool</a> must
be installed on the system at the default location.</p>
<pre>
jsign --storetype YUBIKEY --storepass 123456 application.exe
</pre>
<p>Alternatively, the PIV storetype can also be used to sign with a Yubikey and doesn't require the ykcs11 library.</p>
<h4 id="example-nitrokey">Signing with a Nitrokey HSM</h4>
<p>Signing with a Nitrokey HSM requires the installation of <a href="https://github.com/OpenSC/OpenSC">OpenSC</a>.</p>
<pre>
jsign --storetype NITROKEY --storepass 123456 --alias test \
--certfile full-chain.pem application.exe
</pre>
<p>Other Nitrokeys based on the OpenPGP card standard are also supported with this storetype, but an X.509 certificate
must be imported into the Nitrokey (using the gnupg <a href="https://www.gnupg.org/documentation/manuals/gnupg/gpg_002dcard.html">writecert</a>
command). Keys without certificates are ignored. Alternatively, the OPENPGP storetype can also be used, it doesn't
require OpenSC and any key can be used by providing an external certificate.</p>
<h4 id="example-etoken">Signing with a SafeNet eToken</h4>
<p>Signing with a SafeNet eToken requires the installation of the
<a href="https://knowledge.digicert.com/general-information/how-to-download-safenet-authentication-client">SafeNet Authentication Client</a>.</p>
<pre>
jsign --storetype ETOKEN --storepass <PIN> application.exe
</pre>
<h4 id="example-smart-card">Signing with a smart card</h4>
<p>Signing with a smart card requires the installation of <a href="https://github.com/OpenSC/OpenSC">OpenSC</a>.</p>
<pre>
jsign --storetype OPENSC --storepass 123456 --alias test \
--certfile full-chain.pem application.exe
</pre>
<p>If multiple devices are connected, the <code>keystore</code> parameter can be used to specify
the name of the one to use.</p>
<h4 id="example-openpgp">Signing with an OpenPGP card</h4>
<p>OpenPGP cards contain up to 3 keys, one for signing, one for encryption, and one for authentication. All of them
can be used for code signing (except encryption keys based on an elliptic curve). The alias to select the key is either,
<code>SIGNATURE</code>, <code>ENCRYPTION</code> or <code>AUTHENTICATION</code>. The OPENPGP storetype can be used with
a Nitrokey (non-HSM models) or a Yubikey.</p>
<pre>
jsign --storetype OPENPGP --storepass 123456 --alias SIGNATURE \
--certfile full-chain.pem application.exe
</pre>
<p>The <code>certfile</code> parameter is only required if no X.509 certificate is stored on the card for the key used.</p>
<p>If multiple devices are connected, the <code>keystore</code> parameter can be used to specify
the name of the one to use.</p>
<h4 id="example-piv">Signing with a PIV card</h4>
<p>PIV cards contain up to 24 keys and certificates. The alias to select the key is either <code>AUTHENTICATION</code>,
<code>SIGNATURE</code>, <code>KEY_MANAGEMENT</code>, <code>CARD_AUTHENTICATION</code>, or <code>RETIRED<1-20></code>.
Slot numbers are also accepted (for example <code>9c</code> for the digital signature key).
<pre>
jsign --storetype PIV --storepass 123456 --alias SIGNATURE application.exe
</pre>
<p>If multiple devices are connected, the <code>keystore</code> parameter can be used to specify
the name of the one to use.</p>
<h4 id="example-awskms">Signing with AWS Key Management Service</h4>
<p><a href="https://aws.amazon.com/kms/">AWS Key Management Service</a> (KMS) stores only the private key,
the certificate must be provided separately. The <code>keystore</code> parameter references the AWS region.
Setting the <code>AWS_USE_FIPS_ENDPOINT</code> environment variable to <code>true</code> will ensure the FIPS
endpoint is used.</p>
<p>The AWS access key, secret key, and optionally the session token, are concatenated
and used as the <code>storepass</code> parameter; if the latter is not provided, Jsign attempts to fetch the credentials
from the environment variables (<code>AWS_ACCESS_KEY_ID</code>, <code>AWS_SECRET_ACCESS_KEY</code> and <code>AWS_SESSION_TOKEN</code>),
from the <a href="https://docs.aws.amazon.com/sdkref/latest/guide/feature-container-credentials.html">ECS container credentials endpoint</a>,
or from the <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html">IMDSv2</a> service
when running on an AWS EC2 instance.</p>
<p>In any case, the credentials must allow the following actions:
<code>kms:ListKeys</code>, <code>kms:DescribeKey</code> and <code>kms:Sign</code>.</p>
<p>The <code>alias</code> parameter can specify either the key id or an alias.</p>
<pre>
jsign --storetype AWS \
--keystore eu-west-3 \
--storepass "<access-key>|<secret-key>|<session-token>" \
--alias 12345678-abcd-1234-cdef-1234567890ab \
--certfile full-chain.pem application.exe
</pre>
<h4 id="example-azurekeyvault">Signing with Azure Key Vault</h4>
<p>Certificates and keys stored in the <a href="https://azure.microsoft.com/services/key-vault/">Azure Key Vault</a>
key management system can be used with:</p>
<pre>
jsign --storetype AZUREKEYVAULT \
--keystore vaultname \
--storepass <api-access-token> \
--alias test application.exe
</pre>
<p>The access token can be obtained with the <a href="https://learn.microsoft.com/en-us/cli/azure/">Azure CLI</a>:</p>
<pre>
az account get-access-token --resource "https://vault.azure.net"
</pre>
<p>The Azure account used must have the <em>"Key Vault Crypto User"</em> and <em>"Key Vault Certificate User"</em> roles.</p>
<h4 id="example-trustedsigning">Signing with Azure Trusted Signing</h4>
<p>With the Azure <a href="https://learn.microsoft.com/en-us/azure/trusted-signing/overview">Trusted Signing</a> service
the <code>keystore</code> parameter specifies the endpoint URI, and the <code>alias</code> combines the account name and
the certificate profile. The Azure API access token is used as the keystore password.</p>
<pre>
jsign --storetype TRUSTEDSIGNING \
--keystore weu.codesigning.azure.net \
--storepass <api-access-token> \
--alias <account>/<profile> application.exe
</pre>
<p>The access token can be obtained with the <a href="https://learn.microsoft.com/en-us/cli/azure/">Azure CLI</a>:</p>
<pre>
az account get-access-token --resource https://codesigning.azure.net
</pre>
<p>The Azure account used must have the <em>"Code Signing Certificate Profile Signer"</em> role.</p>
<p>The certificates issued by Azure Trusted Signing have a lifetime of 3 days only, and timestamping is necessary to
ensure the long term validity of the signature. For this reason timestamping is automatically enabled when signing
with this service.</p>
<p>Implementation note: Jsign performs an extra call to the signing API to retrieve the current certificate chain before
signing. When signing multiple files it's recommended to invoke Jsign only once with the list of files to avoid doubling
the quota usage.</p>
<h4 id="example-digicertone">Signing with DigiCert ONE / DigiCert KeyLocker</h4>
<p>Certificates and keys stored in the <a href="https://www.digicert.com/digicert-one">DigiCert ONE</a> Secure Software Manager
can be used directly without installing the DigiCert client tools. It requires an API key and a PKCS#12 keystore holding
a client certificate for the authentication. The US DigiCert ONE host is used by default (https://clientauth.one.digicert.com)
but a different host can be specified with the <code>--keystore</code> parameter.</p>
<pre>
jsign --storetype DIGICERTONE \
--storepass "<api-key>|/path/to/Certificate_pkcs12.p12|<password>" \
--alias test application.exe
</pre>
<h4 id="example-sslcom-esigner">Signing with SSL.com eSigner</h4>
<p>When signing with the <a href="https://www.ssl.com/esigner/">SSL.com eSigner</a> service, the SSL.com username and
password are used as the keystore password, and the base64 encoded TOTP secret is used as the key password:</p>
<pre>
jsign --storetype ESIGNER \
--storepass "<username>|<password>" \
--alias 8b072e22-7685-4771-b5c6-48e46614915f \
--keypass <totp-secret> application.exe
</pre>
<p>SSL.com provides a sandbox environment, to use a test certificate simply add the parameter
<code>--keystore https://cs-try.ssl.com</code>.</p>
<h4 id="example-garasign">Signing with GaraSign</h4>
<p><a href="https://garantir.io/garasign/">GaraSign</a> is a remote signing service provided by Garantir.
The authentication is performed by specifying the username/password or the TLS client certificate in the
<code>storepass</code> parameter. If the TLS client certificate is stored in a password protected keystore,
the password is specified in the <code>keypass</code> parameter. The <code>keystore</code> parameter references
the URL of the GaraSign REST API (https://garasign.com:8443/CodeSigningRestService/ by default).</p>
<p>Authenticating with a username and a password:</p>
<pre>
jsign --storetype GARASIGN \
--storepass "<username>|<password>" \
--alias test \
application.exe
</pre>
<p>Authenticating with a TLS client certificate and a non-default endpoint:</p>
<pre>
jsign --storetype GARASIGN \
--keystore https://demo.garantir.io/CodeSigningRestService \
--storepass "/path/to/client-certificate.p12" \
--keypass <client-certificate-password> \
--alias test \
application.exe
</pre>
<h4 id="example-googlecloud">Signing with Google Cloud KMS</h4>
<p>Google Cloud KMS stores only the private key, the certificate must be provided separately. The keystore parameter
references the path of the keyring. The alias specifies the name and the version of the key:</p>
<pre>
jsign --storetype GOOGLECLOUD \
--keystore projects/first-rain-123/locations/global/keyRings/mykeyring \
--storepass <api-access-token> \
--alias test/cryptoKeyVersions/1 \
--certfile full-chain.pem application.exe
</pre>
<p>The version of the key can be omitted (e.g. <code>--alias test</code>), in this case the most recent version
of the key is picked automatically. This avoids modifying the parameters every time the key is updated, but the signing
process is slightly slower due to an additional API call, and it requires an extra permission.</p>
<p>The access token is typically provided by the <a href="https://cloud.google.com/sdk/docs/install">gcloud tool</a>:</p>
<pre>
gcloud auth print-access-token
</pre>
<p>When creating the key the purpose must be set to "Asymmetric sign", and the algorithm must be either Elliptic Curve
or RSA with PKCS#1 v1.5 padding and SHA digest. Keys with PSS padding or raw RSA mode are not supported.</p>
<p>The Google Cloud account used must have the following permissions:</p>
<ul>
<li><code>cloudkms.cryptoKeyVersions.useToSign</code></li>
<li><code>cloudkms.cryptoKeyVersions.list</code> (required if the version of the key isn't specified)</li>
<li><code>cloudkms.cryptoKeys.list</code> (required to list the keys available when the alias isn't found)</li>
</ul>
<p>These permissions are covered by the <em>Cloud KMS CryptoKey Signer</em> and <em>Cloud KMS Viewer</em>
<a href="https://cloud.google.com/kms/docs/reference/permissions-and-roles#predefined">roles</a>.</p>
<h4 id="example-hashicorpvault">Signing with HashiCorp Vault</h4>
<p><a href="https://developer.hashicorp.com/vault">HashiCorp Vault</a> exposes keys through secrets engines. Jsign
supports the <a href="https://developer.hashicorp.com/vault/docs/secrets/gcpkms">Google Cloud KMS</a> and
<a href="https://developer.hashicorp.com/vault/docs/secrets/transit">Transit</a> secrets engines. The <code>keystore</code>
parameter references the endpoint of the secrets engine, which is typically the Vault server URL and the API version
<code>v1</code> followed by the secrets engine path. The certificate must be provided separately using the
<code>certfile</code> parameter. The <code>alias</code> parameter specifies the name of the key in Vault. For the
Google Cloud KMS secrets engine, the version of the Google Cloud key is appended to the key name, separated by a colon
character.</p>
<pre>
jsign --storetype HASHICORPVAULT \
--keystore https://vault.example.com/v1/gcpkms \
--storepass <vault-token> \
--alias test:1 \
--certfile full-chain.pem application.exe
</pre>
<h4 id="example-signserver">Signing with Keyfactor SignServer</h4>
<p><a href="https://www.signserver.org">SignServer</a> is a cloud/on-premises open source signing service developed by
Keyfactor. SignServer supports various signing operations handled by signer workers. Jsign requires a
<a href="https://doc.primekey.com/signserver/signserver-reference/signserver-workers/signserver-signers/plain-signer">Plain Signer</a>
worker, preferably configured with the <code>CLIENTSIDEHASHING</code> or <code>ALLOW_CLIENTSIDEHASHING_OVERRIDE</code>
properties set to <code>true</code>, and the <code>SIGNATUREALGORITHM</code> property set to <code>NONEwithRSA</code> or
<code>NONEwithECDSA</code>. The worker may be configured with server-side hashing (i.e. with <code>CLIENTSIDEHASHING</code>
and <code>ALLOW_CLIENTSIDEHASHING_OVERRIDE</code> set to <code>false</code>, and a proper
<code>SIGNATUREALGORITHM</code> set), in this case the worker name or id in the alias has to be suffixed with
<code>|serverside</code>.</p>
<p>If necessary the authentication is performed by specifying the username/password or the TLS client certificate in the
<code>storepass</code> parameter. If the TLS client certificate is stored in a password protected keystore, the password
is specified in the <code>keypass</code> parameter. The <code>keystore</code> parameter references the URL of the
SignServer REST API. The <code>alias</code> parameter specifies the id or the name of the worker.</p>
<p>Authenticating with a username and a password:</p>
<pre>
jsign --storetype SIGNSERVER \
--keystore https://example.com/signserver \
--storepass "<username>|<password>" \
--alias test \
application.exe
</pre>
<p>Authenticating with a TLS client certificate:</p>
<pre>
jsign --storetype SIGNSERVER \
--keystore https://example.com/signserver \
--storepass "/path/to/client-certificate.p12" \
--keypass <client-certificate-password> \
--alias test \
application.exe
</pre>
<p>Using server-side hashing, the digest algorithm must match the one configured for the worker:</p>
<pre>
jsign --storetype SIGNSERVER \
--keystore https://example.com/signserver \
--alias "test|serverside" \
--alg SHA-512 \
application.exe
</pre>
<h4 id="example-oraclecloud">Signing with Oracle Cloud Key Management Service</h4>
<p>Signing with the Oracle Cloud Infrastructure Key Management Service requires the
<a href="https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm">configuration file</a> or the
<a href="https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/clienvironmentvariables.htm">environment variables</a>
used by the OCI CLI. The OCI CLI isn't required for signing, but it may be used to initialize the configuration file
with <code>oci setup bootstrap</code>.</p>
<p>The storepass parameter specifies the path to the configuration file (<code>~/.oci/config</code> by default). If the
configuration file contains multiple profiles, the name of the non-default profile to use is appended to the storepass
(for example <code>~/.oci/config|PROFILE</code>). The <code>keypass</code> parameter may be used to specify the
passphrase of the key file used for signing the requests to the OCI API if it isn't set in the configuration file.</p>
<p>The certificate must be provided separately using the <code>certfile</code> parameter. The alias specifies the OCID
of the key.</p>
<p>The general syntax looks like this:</p>
<pre>
jsign --storetype ORACLECLOUD \
--storepass "<oci-config-file>|<profile>" \
--keypass <passphrase> \
--alias ocid1.key.oc1.eu-paris-1.abcdefghijklm.abrwiljrwkhgllb5zfqchmvdkmqnzutqeq5pz7 \
--certfile full-chain.pem application.exe
</pre>
<p>When using the default configuration file and profile, the command is simplified to:</p>
<pre>
jsign --storetype ORACLECLOUD \
--alias ocid1.key.oc1.eu-paris-1.abcdefghijklm.abrwiljrwkhgllb5zfqchmvdkmqnzutqeq5pz7 \
--certfile full-chain.pem application.exe
</pre>
<p>The configuration file can be replaced (or overridden) by environment variables. Here are the variables expected:</p>
<ul>
<li><code>OCI_CLI_USER</code>: OCID of the user (e.g. <code>ocid1.user.oc1..<unique_ID></code>)</li>
<li><code>OCI_CLI_TENANCY</code>: The OCID of the tenancy (e.g. <code>ocid1.tenancy.oc1..<unique_ID></code>)</li>
<li><code>OCI_CLI_REGION</code>: The OCI region (e.g. <code>eu-paris-1</code>)</li>
<li><code>OCI_CLI_KEY_FILE</code>: The path to the private key signing the API requests in PEM format</li>
<li><code>OCI_CLI_PASS_PHRASE</code>: The pass phrase of the private key</li>
</ul>
<h4 id="example-signpath">Signing with SignPath</h4>
<p>Signing with <a href="https://signpath.io">SignPath</a> requires an account entitled to use the code signing gateway
and a signing policy configured for hash signing. The <code>keystore</code> parameter specifies the organization
identifier, and the <code>storepass</code> parameter the API access token. The <code>alias</code> parameter is the
concatenation of the project slug and the signing policy slug, separated by a slash character.</p>
<pre>
jsign --storetype SIGNPATH \
--kesytore <organizationId> \
--storepass <accessToken> \
--alias <projectSlug>/<signingPolicySlug> \
application.exe
</pre>