|
1
|
# Signing Check-ins |
|
2
|
|
|
3
|
Fossil can sign check-in manifests. A basic concept in public-key |
|
4
|
cryptography, signing can bring some advantages such as authentication and |
|
5
|
non-repudiation. In practice, a serious obstacle is the public key |
|
6
|
infrastructure – that is, the problem of reliably verifying that a given |
|
7
|
public key belongs to its supposed owner (also known as _"signing is easy, |
|
8
|
verifying is hard"_). |
|
9
|
|
|
10
|
Fossil neither creates nor verifies signatures by itself, instead relying on |
|
11
|
external tools that have to be installed side-by-side. Historically, the tool |
|
12
|
most employed for this task was [GnuPG](https://gnupg.org); recently, there has |
|
13
|
been an increase in the usage of [OpenSSH](https://openssh.com) (the minimum |
|
14
|
required version is 8.1, released on 2019-10-09). |
|
15
|
|
|
16
|
## Signing a check-in |
|
17
|
|
|
18
|
The `clearsign` setting must be on; this will cause every check-in to be signed |
|
19
|
(unless you provide the `--nosign` flag to `fossil commit`). To this end, |
|
20
|
Fossil calls the command given by the `pgp-command` setting. |
|
21
|
|
|
22
|
Fossil needs a non-detached signature that includes the rest of the usual |
|
23
|
manifest. For GnuPG, this is no problem, but as of 2025 (version 9.9p1) OpenSSH |
|
24
|
can create **and verify** only detached signatures; Fossil itself must |
|
25
|
attach this signature to the manifest prior to committing. This makes the |
|
26
|
verification more complex, as additional steps are needed to extract the |
|
27
|
signature and feed it into OpenSSH. |
|
28
|
|
|
29
|
### GnuPG |
|
30
|
|
|
31
|
The `pgp-command` setting defaults to |
|
32
|
`gpg --clearsign -o`. |
|
33
|
(A possible interesting option to `gpg --clearsign` is `-u`, to specify the |
|
34
|
user to be used for signing.) |
|
35
|
|
|
36
|
### OpenSSH |
|
37
|
|
|
38
|
A reasonable value for `pgp-command` is |
|
39
|
|
|
40
|
``` |
|
41
|
ssh-keygen -q -Y sign -n fossilscm -f ~/.ssh/id_ed25519 |
|
42
|
``` |
|
43
|
|
|
44
|
for Linux, and |
|
45
|
|
|
46
|
``` |
|
47
|
ssh-keygen -q -Y sign -n fossilscm -f %USERPROFILE%/.ssh/id_ed25519 |
|
48
|
``` |
|
49
|
|
|
50
|
for Windows, changing as appropriate `-f` to the path of the private key to be |
|
51
|
used. |
|
52
|
|
|
53
|
The value for `-n` (the _namespace_) can be changed at will, but care has to be |
|
54
|
taken to use the same value when verifying the signature. |
|
55
|
|
|
56
|
Fossil versions prior to 2.26 do not understand SSH signatures and |
|
57
|
will treat artifacts signed this way as opaque blobs, not Fossil |
|
58
|
artifacts. |
|
59
|
|
|
60
|
|
|
61
|
## Verifying a signature |
|
62
|
|
|
63
|
Fossil does not provide an internal method for verifying signatures and |
|
64
|
relies – like it does for signing – on external tools. |
|
65
|
|
|
66
|
### GnuPG |
|
67
|
|
|
68
|
Assuming you used the |
|
69
|
default GPG command for signing, one can verify the signature using |
|
70
|
|
|
71
|
``` |
|
72
|
fossil artifact <CHECK-IN> | gpg --verify |
|
73
|
``` |
|
74
|
|
|
75
|
### OpenSSH |
|
76
|
|
|
77
|
The user and the key that was used to create the signature must be listed |
|
78
|
together in the `ALLOWED_SIGNERS` file (see |
|
79
|
[documentation](https://man.openbsd.org/ssh-keygen#ALLOWED_SIGNERS)). |
|
80
|
Note that in that file, the "@DOMAIN" bit for the principal is only a |
|
81
|
recommendation; you can (or even _should_) simply use your Fossil user name. |
|
82
|
|
|
83
|
As mentioned, for lack of an OpenSSH built-in non-detached signature mechanism, |
|
84
|
the burden of extracting the relevant part of the signed check-in is on the |
|
85
|
user. |
|
86
|
|
|
87
|
The following recipes are provided only as examples and can be easily extended |
|
88
|
to fully-fledged scripts. |
|
89
|
|
|
90
|
#### For Linux: |
|
91
|
|
|
92
|
```bash |
|
93
|
fsig=$(mktemp /tmp/__fsig.XXXXXX) && \ |
|
94
|
fusr=$(fossil artifact tip \ |
|
95
|
| awk -v m="${fsig}" -v s="${fsig}.sig" \ |
|
96
|
'/^-----BEGIN SSH SIGNED/{of=m;next} \ |
|
97
|
/^-----BEGIN SSH SIGNATURE/{of=s} \ |
|
98
|
/^U /{usr=$2} \ |
|
99
|
/./{if(!of){exit 42};print >> of} END{print usr}') && \ |
|
100
|
ssh-keygen -Y verify -f ~/.ssh/allowed_signers -I ${fusr} -n fossilscm \ |
|
101
|
-s "${fsig}.sig" < "${fsig}" || echo "No SSH signed check-in" && \ |
|
102
|
rm -f "${fsig}.sig" "${fsig}" && \ |
|
103
|
unset -v fsig fusr |
|
104
|
``` |
|
105
|
|
|
106
|
#### For Windows (cmd): |
|
107
|
|
|
108
|
The following incantation makes use of `awk` and `dos2unix`, standard Unix |
|
109
|
tools but requiring separate installation on Windows (for example,using |
|
110
|
[BusyBox](https://frippery.org/busybox/#downloads)). The usage of `awk` can be |
|
111
|
replaced with the Windows basic tool `findstr`, leading to a longer recipe. |
|
112
|
|
|
113
|
```bat |
|
114
|
fossil artifact <CHECK-IN> | awk -v m="__fsig" -v s="__fsig.sig" ^ |
|
115
|
"/^-----BEGIN SSH SIGNED/{of=m;next} /^-----BEGIN SSH SIGNATURE/{of=s} /./{if(!of){exit 42};print >> of}" |
|
116
|
if %errorlevel% equ 42 (echo No SSH signed check-in) |
|
117
|
REM ---Skip remaining lines if no SSH signed message--- |
|
118
|
for /f "tokens=2" %i in ('findstr /b "U " __fsig') do set fusr=%i |
|
119
|
dos2unix __fsig __fsig.sig |
|
120
|
ssh-keygen -Y verify -f %USERPROFILE%\.ssh\allowed_signers -I "%fusr%" ^ |
|
121
|
-n fossilscm -s __fsig.sig < __fsig |
|
122
|
del __fsig __fsig.sig 2>nul & set "fusr=" |
|
123
|
``` |
|
124
|
|
|
125
|
|