As I read about cryptographic tools, such as GnuPG and age, there was one that people recommended for signing files, or rather, a couple of them: signify and minisign.
Now, I’m not a strong user of these tools, as I don’t regularly release software or any other sort of files that must be verified for potential tampering, but I was still curious about this use case, and most of the recommendations I’ve read treated both tools as somewhat interchangeable: “just use signify or minisign, whatever you want”. They are nigh identical tools, based around the same principle and with similar user interfaces, but as it turns out, they’re not compatible with each other.
This write-up serves as a possible source of clarification for any confused user searching why they can’t sign files with keys made in the other program. I know I was one of them.
Keep in mind that I am using Debian Testing, so the packages might be different from the releases you’re using. In fact, all mentions of the signify
command refer to signify-openbsd
due to a name clash with an email signature generator.
Generation
Before signing your files, you need to create a key pair; the secret key creates the signature, and the public key verifies said signature. Skimming the man pages, we can see how the key creation commands are not the same:
signify -G [-n] [-c comment] -p pubkey -s seckey minisign -G [-p pubkey_file] [-s seckey_file] [-W]
Signify’s -c
option defines a comment for your key (the “untrusted comment” line) at generation-time, while minisign does this at signature-time. The -n
and -W
flags do the same: avoid using a password to encrypt the key file.
Notice how -p
and -s
are optional in minisign. Unlike signify, which needs specific paths to store the key pair, minisign stores the secret key by default on ~/.minisign/minisign.key
. The public key is stored as minisign.pub
in the current directory.
Signature
signify -S [-enz] [-x sigfile] -s seckey -m message minisign -S [-H] [-x sig_file] [-s seckey_file] [-c untrusted_comment] [-t trusted_comment] -m file [file ...]
Here we can see how minisign not only lets you assign an untrusted comment when signing a file with -c
, but it also lets you assign a custom trusted comment with t
, which no one can modify without invalidating the signature. Conversely, while missing signature-time comments, signify is able to embed the message in the signature file it creates by using the -e
flag, as well as embed the signature in the header of a gzip file with the -z
flag. I have no idea what -H
(“Requires the input to be prehashed”) does, and apparently it will be removed in the future anyway.
Let’s do a test:
mkdir -p signikeys && signify -G -p signikeys/key.pub -s signikeys/key.sec -n mkdir -p minikeys && minisign -G -p minikeys/key.pub -s minikeys/key.sec -W echo 'This is a test' > test.txt signify -S -s signikeys/key.sec -m test.txt -x test.txt.signify minisign -S -s minikeys/key.sec -m test.txt -x test.txt.minisign
There’s no output from the signature operation, so everything’s normal. Now let’s sign with the opposite keys:
signify -S -s minikeys/key.sec -m test.txt -x test.txt.signify-minikeys # signify-openbsd: unable to parse minikeys/key.sec minisign -S -s signikeys/key.sec -m test.txt -x test.txt.minisign-signikeys # base64 conversion failed - was an actual secret key given?
Each program can’t read the other’s keys. If you look at the secret keys, you can see the minisign one is slightly longer. They’re fundamentally not the same, and this is true even if we use a password for either of them or both.
$ cat signikeys/key.sec untrusted comment: signify secret key RWRCSwAAAABSXFgEHTEe8MaWRd2VhnhaiNX7SEKnRX1HpKzOd/7Rr2AGt6Ti+scwJECiC3Zo+Vp/mMmhpHMTbBT+qt6F1cUvmEJD5/DVgS1rOr3sM1J4I+zsdXN7tja2c4CT68uyvvg= $ cat minikeys/key.sec untrusted comment: minisign encrypted secret key RWQAAEIyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7WDMerTVfXdRVEOpd6Ejq95Jp8DBvH0La1KvAMoS8p/qOP3ujDeXNp42ES4vNFHgvey9vEkdTMfio9GOlS3h5b6o8HkU+rwbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
It goes without saying that you should not use these keys, ever. They are not secret anymore.
Verification
signify -V [-eqz] [-p pubkey] [-t keytype] [-x sigfile] -m message minisign -V [-x sig_file] [-p pubkey_file | -P pubkey] [-o] [-q] -m file
The verification stage is straightforward and pretty much the same in both programs: -V
sets the verify mode, -x
is the signature file generated in the previous step, -p
is the public key file, and -m
is the message, i.e. the file whose integrity we’re checking. We have a -q
flag for suppressing output, as well.
As for signify-exclusive options, we have -e
to verify signatures with an embeded message (as in signify -e -x signature_with_embed -p key.pub -m new_file
, which will create new_file with the contents of the original file.), -z
as the same thing for signed gzip files, -t
for deducing a key type or something (don’t ask me what this does, it matches a key on /etc/signify/*-keytype.pub, and I don’t have that directory since I use the Debian version). For minisign, -o
prints the message file to the standard output, and -P
allows you to use the base64 string representation of a key instead of a file, as in minisign -V -P RWRHpKzOd/7Rr5hCQ+fw1YEtazq97DNSeCPs7HVze7Y2tnOAk+vLsr74 -m test.txt -x test.txt.minisign
.
Well, we may not be able to sign files with keys generated by another program, but what about verification?
$ signify-openbsd -V -x test.txt.signify -p signikeys/key.pub -m test.txt Signature Verified $ minisign -V -x test.txt.minisign -p minikeys/key.pub -m test.txt Signature and comment signature verified Trusted comment: timestamp:1699600567 file:test.txt hashed $ signify-openbsd -V -x test.txt.minisign -p minikeys/key.pub -m test.txt signify-openbsd: unsupported file test.txt.minisign $ minisign -V -x test.txt.signify -p signikeys/key.pub -m test.txt Trusted comment not present
So, not only the secret key structure is different, but also the signatures they generate:
$ cat test.txt.signify untrusted comment: verify with key.pub RWRHpKzOd/7Rryg60iRfonpDvuFq40qPJn9XiEsuHh2kWmXwyZNJ+/YhB/7KgFuLN6pXdsXBJj+7AJA1kkWkwOPJG8fN821ZJAs= $ cat test.txt.minisign untrusted comment: signature from minisign secret key RUTtYMx6tNV9dwXgHep+70+uZy4mDwEMmdNwapL4/Nlpt3i8gwI1VG++3fjm/ImPAOxBft7FCGyWoD7nOJvcHJYZJx3nZwCcPw8= trusted comment: timestamp:1699600567 file:test.txt hashed 3/rMchyZllQfWMx0OU8MSfxSCBYXydlhG9ZlBrRIJhfRsAMkrazWjJDDdO7AtKx6q++y5R1w2FxJuhOj9P7hAQ==
As hinted at in the signature section, we have a trusted comment on the minisign signature, a comment that no one can tamper with as it would invalidate the signature. Meanwhile, the signify signature only has an untrusted comment, which can be modified freely. In other words, they generate files with a different structure, even if they look similar to each other.
Miscellaneous
Signify can verify a list of SHA-256 checksums and automatically check the integrity of each file on the list with the -C
option. However, you must use the BSD version of sha256
to generate the checksum or use GNU’s sha256sum
with the --tag
option.
Minisign uses the -C
option to change the password for a secret key, as well as to remove it with the -W
flag. It also has a -R
option, which recreates the public key in case you only have the secret key, for example, if you have it in the ~/.minisign
directory and don’t remember where you stored the public key.
Which one should I use?
Hard to say. They solve the same problem in almost the same way, but implementation differences make them unable to serve as drop-in replacements for each other.
Use signify if…
- …you use OpenBSD.
- …your distro uses signify.
- …you want to create files with an embedded signature.
Use minisign if…
- …you want to use trusted comments.
- …you use Windows or WebAssembly.
- …you prefer to leverage your crypto to libsodium.
- …you want to compile using zig.
Use either if…
- …you want to verify files signed with one or another.
Use none if…
- …you still believe PGP is the way to go.
- …you don’t know what this whole “digital signature” mumbo jumbo is all about.
To be fair, me neither. I don’t know a thing about crypto, so don’t take my opinions too seriously.