zpaqfranz 65.19 update can be trusted (more or less)
IMPORTANT: A DIGITAL SIGNATURE IS NOT A WARRANTY OF ANY KIND
My digital signature does not make me responsible for whether this software works, fails, or meets your expectations. zpaqfranz is open-source software, provided free of charge, which you are entirely free to use or not to use, at your own discretion.
The signature is simply a security measure designed to reduce the risk of installing an update from an untrusted source. It helps you verify that an update really comes from me and has not been tampered with.
This isn't a perfect solution (after all, nothing is), but it should be seen as an improvement: a way to mitigate a potential risk. In short, a service.
The best approach (and I've made all the necessary technical information available) is to compile the program from source. This is standard practice in the non-Windows world (although binary packages and even containers are also very common). In short, I hope you can see my commitment to the highest possible level of transparency.
And one more thing: YOU are always in control. YOU decide whether to run the update command. zpaqfranz NEVER updates itself automatically without an explicit command from YOU. No hidden "Windows update" here 😄
Ok, going back...
update downloads a new zpaqfranz from my site and replaces the one you have.
What makes the new exe "good" is my digital signature: an Italian qualified
electronic signature. In 65.19, that check
has become stricter: zpaqfranz knows my certificate, byte by byte, and accepts
nothing else. On Windows, BTW, downloads now use HTTPS, made by Windows itself
(urlmon, then WinINet), with its own certificates.
Not a big improvement (the signature is what counts), but better than nothing.
zpaqfranz update is there a newer one? (the signature is checked)
zpaqfranz update -force if there is, install it
zpaqfranz update -paranoid check my signature yourself (openssl, or a web site)
zpaqfranz update -force -kill install it regardless (and, if the signature cannot
be verified, only after you type its URL)
My signature: take it or leave it
The certificate is an Italian qualified electronic signature, on a SIM.
In Italy it has full legal value but outside Italy it is not widely used.
I use it because I already pay for it, instead of paying for one more
certificate to some "friend" of Microsoft. So, dear user: if you're comfortable
with it, use it. If you are not... don't.
Downloading an executable from the Internet always requires some care, no matter
where it comes from: it is a common problem, not specific to zpaqfranz. If you
have doubts, take zpaqfranz from GitHub or SourceForge, or compile it
yourself: I made a tool for that, zpaqbuilder.
I cannot do much more than this (and it is already much more than 99.99% of the
software on the Internet).
BTW: if you are willing to pay for the M$ certificate for me, I'll adopt one :)
And:
updateon Windows uses HTTPS, and falls back to HTTP by itself where HTTPS
cannot work (an old Windows Server, zpaqfranz32.exe on XP): the signature is checked anyway.updateis only for zpaqfranz.exe, zpaqfranzhw.exe and zpaqfranz32.exe:
zpaqfranz-full and the XP build refuse it (see the final note).- When my certificate expires (2028-12-24), the zpaqfranz you have cannot know
the next one, and refuses it, as it must refuse a fake.update -force -kill
can install it all the same, after a captcha: the URL of the exe, typed
exactly. Or download it by hand, once.
Other "things"
- The replacement of the exe is safe: if anything goes wrong, the old
zpaqfranz is kept. A user folder whose name contains accented characters now works. - Bugfix, with data loss:
d -forcecould delete the original file and
keep a link to it (very uncommon... but...). Nowdalso works on multiple folders at once. - Extraction on Linux, BSD, macOS: permissions are now handled as
tardoes. l -attrnow has its header.- Bugfix:
-stdin -longpathstored the stream as a folder (issue 355); an
a -verifythat detected a wrong CRC-32 still ended with "all OK".
Part one, what is new, for the user
update, in two words- My signature, an Italian qualified signature
- How it was hardened
- https on Windows
- When my certificate expires:
-force -kill - The replacement of the exe
- A word on downloading executables
d: never the original, and more folders- Extraction on *nix: permissions as
tar l -attr- Bugfix
1. update, in two words
On my site, next to each exe, there is a small file with the same name and
.sha256.p7m (zpaqfranz.sha256.p7m, zpaqfranzhw.sha256.p7m,
zpaqfranz32.sha256.p7m). It contains a single line: the executable's SHA-256
hash, version and date.
7f6b9b2acefe53781c8e3a161b6907d92e10004c3845dd6fcb3654607ed94d0f *65.18r_(2026-11-07)
That line is signed by me. update:
- downloads the
.p7mand checks my signature; - reads the version: is it newer than yours?
- with
-force, downloads the exe and computes its SHA-256; - if it matches the one in the signed line, replaces your zpaqfranz.
The exe itself is not signed: its SHA-256 is. Change one byte in the exe,
and the hash is not the one I signed. Change one byte in the .p7m, and the
signature does not hold.
On Linux, the BSDs and macOS, update checks whether a newer version is available,
but does not replace anything (so there is very little to worry about).
On Windows, only zpaqfranz.exe, zpaqfranzhw.exe and zpaqfranz32.exe update
themselves: see the final note.
2. My signature, an Italian qualified signature
In Italy there is the firma elettronica qualificata (FEQ). It is issued by a
qualified trust service provider (mine: ArubaPEC), after verifying your identity
in person. The private key is stored in a chip (a SIM card) and cannot be
extracted.
The format is CAdES: a .p7m file (PKCS#7), with my certificate inside. Mine:
Subject FRANCO CORBELLI, serialNumber=TINIT-CRBFNC72T25H294X (my tax code)
Issuer ArubaPEC EU Qualified Certificates CA G1
Valid 2025-12-24 => 2028-12-24
Key RSA 2048 bit, SHA-256
It is not widely used outside Italy: few people know about it, and few programs can
verify it. That is not a problem here, because zpaqfranz checks it by itself.
Why this one, and not a "code signing" certificate? Because I already pay
for this one. A code signing certificate is one more yearly fee, paid to one of the
companies Microsoft likes. I do not see why. If my signature is fine for you, use
update. If it is not, do not use it: point 7
says what else you can do.
3. How it was hardened
Now (65.19) zpaqfranz checks my certificate:
- The certificate is pinned. zpaqfranz has the SHA-256 of my certificate
written in its source, computed over the whole certificate: every byte of it (the key,
the dates, the issuer, the extensions). The.p7mmust contain that one, and only
that one. No chain of authorities, no "any certificate with that name". - Every field in the envelope is checked, one by one. A
.p7mhas parts that the
signature does not cover: the versions, the algorithms, the type of the content, who
the signer is. Each one must be exactly what it should be, each container must end
where its parent ends, and nothing may come after the signature. - The signature itself: RSA PKCS#1 v1.5 with SHA-256, with the padding checked
to the last byte (the hash exactly at the end: no room for the forgeries
known since Bleichenbacher). - A broken file cannot crash it: a length field claiming 2 GB inside the
.p7m
could make zpaqfranz read beyond its buffer and crash; 100 bytes of garbage after
the end were accepted. Both are now rejected. - The expiry is shown: an Italian qualified certificate lasts exactly 3 years. From
180 days before the date,updatesays so in yellow, with the date. The clock
of your PC changes only the words, never the verdict: anyone can move a clock.
How thoroughly was it tested? Every byte of the actual .p7m file on my site
(2,831 bytes) was modified individually, twice (XOR 01 and XOR 80): FULL SCAN.
All 5,662 modified files were refused.
Check it yourself: update -paranoid downloads the .p7m, copies its path
to the clipboard and tells you how to check it: with openssl, or with the
verification site of the Italian notaries (https://vol.ca.notariato.it, it opens
it for you). AgID, the Italian agency, lists the other programs that can do it.
One more thing. The check is made by the zpaqfranz you already have. A
65.18 that updates itself still checks with the code of 65.18. The hardening
protects the updates made by 65.19 and later.
4. https on Windows
update, and every other download from my site (the DLLs, WinFsp...), now uses
HTTPS, with the certificates of Windows.- If HTTPS is unavailable (zpaqfranz32.exe on XP, a Windows Server 2008 never updated, old root
certificates, a clock far off), zpaqfranz displays a yellow warning and
automatically falls back to HTTP. Is it safe? Yes: what makes a file good is
not the channel, it is the check after it. The SHA-256 signed by me forupdate,
the SHA-256 written in zpaqfranz for the DLLs and WinFsp. -nohttps: HTTP straight away.- Windows (WinINet) errors are now displayed as readable messages: "cannot connect",
"certificate authority not trusted (old root certificates?)", and so on, not a
bare number.
On Linux, the BSDs and macOS, zpaqfranz speaks plain HTTP with its own small
client (rewritten: the status of the server, the announced size and the received
size are checked, with a 30-second timeout). The signature is checked in the same
way.
5. When my certificate expires: -force -kill
My certificate expires on 2028-12-24. Then I'll get a new SIM card, with a new key.
An older version of zpaqfranz cannot know about it: for that version, a signature
with the new key is exactly like a fake, and it is refused (it must be). The same
happens if one day Aruba changes the format of its signatures: my check is strict,
and refuses.
Two ways out:
- Download zpaqfranz by hand, once (my site, GitHub, SourceForge). The new
one knows the new certificate, and updates by itself again. update -force -kill(new in 65.19o). With a signature that cannot be
verified, zpaqfranz says so in red, shows the URL the exe comes from, and asks
you to type it exactly (a captcha). It is better than nothing:
00552! P7M signature verification FAILED: good signature, but with a certificate this zpaqfranz does not know (...)
03858! THE SIGNATURE IS NOT VERIFIED: this zpaqfranz cannot tell the exe from a FAKE
03859! -force -kill: it is installed all the same, ONLY if you type EXACTLY the URL it comes from
03860! Do it only if you trust that URL (with https, the certificate of the site is all that is left)
To confirm a dangerous command
>>> update with a signature NOT verified: the URL of the exe
Captcha to continue: https://www.francocorbelli.it/zpaqfranz/win64/zpaqfranz.exe
- The captcha is always required, also with
-nocaptcha. It is read from what
you type: with nothing there (a scheduled task), nothing is done. A script can
write the URL in it, on purpose: that is a choice, not an accident. - The exe comes from that URL only: no fallback to HTTP if HTTPS fails.
Without my signature, the website's TLS certificate is all that remains. - If the
.p7mstill states which SHA-256 the exe has (not verified), the download
is checked against it: that protects from a broken download, not from a fake.
If not, the executable is accepted as downloaded. - In both cases its SHA-256 is printed: compare it with the one on GitHub, if
you want.
Without -kill it is refused, as before, with one line saying that this way
exists.
6. The replacement of the exe
A running exe cannot be overwritten on Windows: update writes a small batch file,
which closes zpaqfranz and puts the new one in its place. That batch was rewritten.
Before: it deleted the exe, then copied the new one. A delete that worked and
a copy that did not = no zpaqfranz at all. If the exe could not be deleted, the
result was an endless, invisible loop. When run with its full path (a scheduled
task), zpaqfranz was not even found by taskkill: endless loop again. A user
folder with an accent (C:\Users\Niccolò) was not found: the batch is read by cmd
in the code page of the console, while the path was written in UTF-8.
Now:
- before downloading anything,
updatechecks that the folder of the exe can be
written to (Program Fileswithout administrator rights, a read-only share): if
not, it stops, with nothing changed; - the old exe is renamed to
.old(it works on NTFS, FAT32, exFAT), the new
one is copied and compared byte by byte, and the.oldis deleted only at the
end. If anything goes wrong, the old executable is restored; - the batch is plain ASCII, and the paths are passed in the environment: accents,
%,&in a path are just characters; - it runs in your console: its messages are visible.
A TEMP folder whose path contained accented characters caused zpaqfranz to crash
immediately, in update and elsewhere (x, work...). Fixed.
7. A word on downloading executables
Any executable downloaded from the Internet requires some care. It is not a problem
specific to zpaqfranz: it is the same for every program, from anywhere.
If you have doubts:
- GitHub: https://github.com/fcorbelli/zpaqfranz/releases
- SourceForge: https://sourceforge.net/projects/zpaqfranz/files/
- Compile it yourself. The source is one file,
zpaqfranz.cpp.- Windows: zpaqbuilder,
https://github.com/fcorbelli/zpaqfranz-stuff/releases/tag/V03. Run it as
administrator on a 64-bit Windows (better: an empty virtual machine): it
installs MSYS2 and the 32-bit and 64-bit GCC compilers. Put the current
zpaqfranz.cppinC:\zpaqfranz, runrella.bat: six exes. - Linux, the BSDs, macOS: one line; the build commands for each system are at the top
ofzpaqfranz.cppor at https://github.com/fcorbelli/zpaqfranz/blob/main/NONWINDOWS/NIX.md - NAS: https://github.com/fcorbelli/zpaqfranz/blob/main/NONWINDOWS/NAS.md
- Windows: zpaqbuilder,
I cannot do much more than this.
8. d: never the original, and more folders
Bugfix, with data loss. d -force deletes the duplicate files and keeps the
first file by name. If the first one was a symbolic link to a file (Windows),
or the file seen through a bind mount (Linux), the link was kept and the
original deleted, with "all OK". The link then pointed to nothing. Now a name
that is the same file as the one that stays is never deleted. For the same reason,
the hard links of the file that stays are no longer removed: they freed nothing.
Multiple folders: one copy of each file across all of them.
zpaqfranz d c:\video\ d:\film\ -force
- each folder must end with
\(or/): a typo must not become something to
search for; - the first folder takes priority, followed by the first filename;
- the same folder twice, or one inside the other: refused (exit code 2).
9. Extraction on *nix: permissions as tar
Previously, x restored the permissions stored in the archive exactly, regardless
of the user: 0777 stayed 0777, a setuid file stayed setuid, even for a non-root
user. Now permissions are handled as tar does:
- a non-root user: archive permissions, adjusted by the
umask, without
setuid, setgid, sticky; root: exactly as stored;-sameperms: exactly as stored, for a non-root user too.
Archives made on Windows: as before (the umask).
10. l -attr
l -attr had no header, and its columns were shifted by one position. Now there is
a header, with Attr, aligned with the numbers, and the width of Size is computed
as without -attr. -terse is the same as before, byte by byte.
11. Bugfix
-stdin -longpath(issue 355, Windows): the name of the stream became the
current folder (C:/Users/x/) and was stored as a folder: the name was lost, andx
created a folder. With-stdinthe name is a label, not a file:-longpathis
now ignored, with a line that says so.a -verify/a -collision: a file whose stored fragments did not give
the CRC-32 of the data read was reported (SOMETHING WRONG,GURU-C), and then
"all OK" was printed, with exit code 0. Now it is an error, with exit code 2.updatewithout the signature file (not downloaded): exit code 2. Before,
-paranoidexplained how to check a file that did not exist, and printed "all OK".- A
TEMPwith an accent (see point 6).
Part two, the details, for power users
1. The checks of the .p7m, one by one
verify_p7m_bytes, in this order; the first that fails is the error (00552!):
- the whole file is one DER SEQUENCE, and nothing follows it;
pkcs7-signedData, SignedData version 1, digest algorithms: SHA-256 only;- the content is
id-data, and it is present (not detached); - one certificate, and only one, with my tax code in its subject; its SHA-256
must be ing_p7mchiavi
(c3294652aaf8d9d30a06ec7033289b72e2072f8d507fadb925c8239406274b30); - one SignerInfo, version 1,
sid= issuer and serial of that certificate,
digest SHA-256; - signed attributes:
contentType=id-data,messageDigest= SHA-256 of the
content; - RSA, a signature of 256 bytes, and nothing after it (no unsigned attributes:
nobody would check them); - PKCS#1 v1.5:
00 01 FF..FF 00, DigestInfo SHA-256, the hash, and the end
of the block; - each container ends where its parent ends.
A good signature with a certificate that is not mine is refused at the end
(good signature, but with a certificate this zpaqfranz does not know, with its
SHA-256): this distinguishes "a new certificate (or a fake)" from "a broken file".
To add my next certificate: its SHA-256 and its expiry go in g_p7mchiavi, next
to the old one (the commands are written above the table).
2. The switches
| Switch | What |
|---|---|
-nohttps
| Windows: HTTP straight away (default: HTTPS, then HTTP by itself) |
-force -kill
| update: install even if not newer; with a signature that cannot be verified, after the captcha
|
-sameperms
| *nix, x: the permissions exactly as stored, also for a non-root user
|
Not in the help, for the tests: -updatefake YYYYMMDD (the expiry as on that
day), -signfake byte[:xor],... (the .p7m changed on disk after the
download, as someone in the middle would do), -httpsfake (HTTPS fails, as on
an old Windows).
3. What can change for a script
update: no signature file, exit code 2. On Windows, HTTPS first. The batch
prints nothing when all goes well (nozpaqfranz updated). During the update,
the old exe is<name>.old.updateon zpaqfranz-full and on the XP build: refused, exit code 2, with
any switch (-force -killtoo, the two URLs too). A scheduled
zpaqfranz-full update -force -killnow fails.- *
xon nix, as a non-root user:umaskapplied, no setuid, setgid, sticky.
-samepermsfor the old behaviour. d: multiple folders only if each ends with\or/; a second argument that
is a folder without it, a folder that does not exist, the same folder twice, or one
inside the other: exit code 2. A name that is the same file as the one that
stays is never deleted.l -attr: a header line (not with-terse).a -verify/a -collision: a CRC-32 that does not match gives exit code 2.a -stdin -longpath: the name as written.
4. The messages
| Code | When |
|---|---|
00534
| the signature is good (green), with the expiry of the certificate |
00551!
| the signature file cannot be downloaded (exit code 2) |
00552!
| the signature is not verified, and why (exit code 2, unless -force -kill and the captcha)
|
03826
| HTTPS failed, now HTTP (yellow) |
03835!
| the folder of the exe cannot be written to: nothing done |
03838 / 03839!
| (no taskkill, XP Home) the exe is, or is not, the new one
|
03840-03850
| the box about the expiry of my certificate |
03855
| -longpath ignored with -stdin
|
03856!
| files stored with fragments that do not give their CRC-32 (exit code 2) |
03857
| update: the line saying that -force -kill exists
|
03858!-03861
| update -force -kill: the warning, the captcha, nothing done
|
03862, 03863$
| the SHA-256 of the .p7m (not verified) was used, or none
|
03864-03866
| the version unknown, the candidate, the SHA-256 downloaded |
03867
| zpaqfranz closes, the batch replaces it |
03868!, 03869
| update on zpaqfranz-full or on the XP build: refused (exit code 2), update it by hand
|
65944-65950
| d with multiple folders: refused
|
Part three, for developers
1. Known limits and open points
- The hardening protects the updates made by 65.19 and later (see the end of
point 3 of part one). - If Aruba changes the format of its signatures (a chain of certificates, a
timestamp),updaterefuses until a new zpaqfranz knows it: I tryupdate
after every publication. - XP: the batch has not been run on a real XP. I lost all my old VMs. Investigation is underway.
l -csvstill prints the header with fixed columns: it is not CSV.work,external,maxcpuandautotestrun their own batches: with a
TEMPcontaining accented characters they still fail. Please stick to ASCII characters: it's a feature, not a bug :)
A FINAL TECHNICAL NOTE
Just a reminder: the main source file is always available here:
https://www.francocorbelli.it/zpaqfranz/win64/zpaqfranz.cpp
Also, automatic updating is supported only by these Windows executables:
zpaqfranz.exe (64-bit) => https://www.francocorbelli.it/zpaqfranz/win64/zpaqfranz.exe
zpaqfranzhw.exe (64-bit) => https://www.francocorbelli.it/zpaqfranz/win64hw/zpaqfranzhw.exe
zpaqfranz32.exe (32-bit) => https://www.francocorbelli.it/zpaqfranz/win32/zpaqfranz32.exe
zpaqfranz-full.exe and the Windows XP-compatible version do not update themselves:
update refuses (exit code 2), because it would put zpaqfranz.exe or zpaqfranz32.exe
in their place. Neither do the open version (it has no update) and the Linux, BSD
and macOS builds (update only says whether a newer one exists). For these builds,
download or compile new versions manually.
Careful: a Windows build you compile yourself does update, and becomes my
zpaqfranz.exe (or zpaqfranzhw.exe, if compiled with -DHWSHA1). If you compile it
so as to trust only the source, do not use update.