⚠️ WARNING ⚠️
This is an experimental program.
Despite occasional enthusiastic comments, I have yet to see any bug reports, or even any reports from people trying to use it in the wild at all. As such, I reserve the right to change file formats if I decide this is beneficial or convenient, until version 1.0.0 strikes.
As of this moment, this tool is feature complete. Now it needs to become bug-free, so please stress-test and torture it.
Alternatively it could be completely forgotten as most innovations in this hobby are. It's not like radio didn't work without all that before.
TLDR: This is a program that allows you to sign any file with the private key you get when you sign up with the Logbook of the World. It also allows anyone to verify such a signature and determine your callsign.
This is all it does, this is all it should be doing, and if it proves sufficiently reliable, this can open up many opportunities for doing things remotely over the radio.
If you don't know what Logbook of the World is, you probably don't care, feel free to resume your doomscrolling.
Long version: I have noticed that LoTW is the only QSL verification service that permits one to send the logs in without having internet access at all. The process involves cryptographically signing individual records within a specially formulated ADIF-like log file, sticking the public key and signatures in extra fields in the ADIF structure. The resulting .tq8
file is a gzip-compressed ADIF file with extra bits, and thus is legal to send in the clear over the air, if you agree that cryptographic signatures are legal to send over the air when the actual data is unencrypted -- most people do, but to my knowledge this hasn't actually been tested with various regulatory bodies.
And LoTW does accept it over the air: careful reading of the LoTW website indicates that you can email signed files to lotw-logs@arrl.org -- where they will presumably be processed. Assuming you set up Winlink properly, sending email without having Internet access in any way is a solved problem.
You could apply the same trick to other web and email-based services, like, for example, allow people to post in their accounts on your Mastodon instance by sending in signed emails, but you would require a central authority matching people's public keys to their accounts -- or at least callsigns, if you're serious about it. Which is presumably why nobody bothered so far.
Fortunately, we can exploit the existing one: Logbook of the World is the biggest QSL verification service in the world and has many thousands of users who already have public keys. It's just a tooling problem.
This project is an attempt to make that as easy to set up for a service owner as possible, by providing them with a simple, one-executable tool to sign and verify a file. There might be a GUI program to go with it later if necessary, but it should be trivial to cook up something using existing tools layering them over this executable.
Instructions describing how to verify a tq8 file claim that "A Digitally Signed Log file can be used to establish proof of identify" -- which is true, but only to a point. While the steps described are sufficient to verify that the signed file has not been damaged -- that is, that the included public key matches the secret key that was used to sign the records therein -- it does not describe how to verify that the included public key has in fact been issued by LoTW. It is relatively trivial to produce a tq8 file that the above cited procedure will find no fault with, but LoTW proper will reject.
LoTW does not currently publish enough information for us to verify the entire chain independently. It's not that it doesn't exist, but you have to go fishing for it.
To simplify things, a public key infrastructure with a central certificate authority typically works kind of like this:
To verify that a key on layer #3 is what it says it is, you need to follow the chain of signatures to the Big Master Key in #1. Which is trivial, when the public parts of all of these keys are published in well-known locations -- or, as is more common, the public part of the #1 key is published, (usually, it is included with other such keys that come with your browser, hundreds of them) and the public part of #2 key is included with #3 wherever you got the signed piece of data -- that is, arrives as you establish the HTTPS session. This is how most SSL certificates all over the Internet work.
This is not quite so with LoTW, where .tq8
files only include your own public key, that is, layer #3. It is signed with a layer #2 key, but that doesn't do you much good if you don't have a copy to verify against.
The only place where I found the requisite #2 and #1 layer public keys was my own .tq6
file that arrived from LoTW with my certificate -- there is no obvious way it's published on their website.
As a result, if LoTW makes a new layer #2 key after you got your layer #3 key and received the corresponding .tq6
key file, the data you possess will be insufficient to verify the authenticity of a .tq8
file signed by a person who got their .tq6
later than you. The way their layer #2 key expiry times are set, this inevitably happens.
lotw-trust
attempts to work around this by keeping a list of layer #1 and #2 keys known to belong to LoTW, -- that is, I took them from my .tq6
file, check the roots directory -- and, when signing things, packing every public key that comes in your .tq6
file that it hasn't seen before in with the signature. This bloats the signature size, and is best avoided.
To make matters more complicated, the #1 Big Master Key is also not eternal, and has an expiry time measured in decades -- the current one expires in 2025. It isn't signed by the key from the previous decade either, so there's no single big key you can acquire from a well-known location and trust.
It would be a lot smoother if LoTW published their public keys in a central trustworthy place. However, my email with questions on the matter was acknowledged as received and then ignored months ago with no sign anyone gave it any thought, so I can only conclude that LoTW is not interested in their keys being used for independent verification of anything.
Consequently, I anticipate that lotw-trust
will need to be updated on average no less than once a year to keep working, which will be a hassle for service owners.
There is currently no way for us to know if a user's certificate has been revoked or not. LoTW does not expose this information publicly anywhere, so you can only know if it expired, because that's written inside the certificate itself. I doubt they have set up the machinery for revoking certificates at all, in fact.
Similarly, there is no way to prevent someone from using an expired certificate, since they can set the clock to what they want, and we can't really reject files signed in the past because the keys used to sign them have legitimately expired since.
The certificate, as issued by LoTW, embeds the email address you used with LoTW -- I am not certain whether it is the address they had on file at the time they issued your certificate, or the address you registered with initially. While lotw-trust
does not display this information anywhere or even access it, it's there, and anyone sufficiently crafty can extract it from the signature block of a file you signed. There is nothing I can do to prevent this.
I am not a cryptographer, I am a sociologist. Golang is not my best language, it's just the one that got me the result the quickest, while still allowing to easily make a cross-platform tool. As a result, it's rather unpolished.
I am also not certain I fully understand what I am doing. The way I use standard cryptographic primitives could be laughably wrong and I wouldn't know without someone else telling me.
lotw-trust sign <your .p12 file> <input file> <output file>
to produce a signed file.lotw-trust verify <input file> <output file>
to verify a signed file and produce the one without a signature block at the end. Will print the callsign of the signer and the date of signing to stderr.You can get a .p12
file with your private key and all the associated public keys by exporting your certificate from tQSL, the same way you would do it for uploading to clublog.org or QRZ.com
See lotw-trust --help
and lotw-trust <command> --help
for further options.
The signature block tries to be compact, (about ~1500 bytes if it doesn't need to include any extra layer #2 keys, ~1000 bytes compressed, can't be much shorter than that) and is appended to the end of the file by default. For a good number of file formats, extra data tacked onto the end will not have any effect on the way their native programs process them: zip
files unpack just as they did, png
and jpg
files remain viewable, and only plain text formats will suffer from the appearance of a binary blob on the end.
It's possible to save the signature block to a separate file, verify such a signature, as well as read and write data from stdin and to stdout with further command line options.
lotw-trust sign -a <input file> <output file>
will save an abbreviated version of the signature block, that only contains the signature itself and some glue, which saves you about ~1000 bytes of message size. To verify that, the recipient must have previously verified a message signed with that public key -- they get cached for just such an occasion.
If your signing situation results in bundling intermediate certificates, I would very much like to see them. The simplest way to let me do that is to send me the contents of your cache directory -- see the -c
flag.
lotw-trust sign -t
and lotw-trust verify -t
will treat the file as text, resulting in an ASCII-armor style message format that you could, in theory, stick into a pipeline in Winlink to automatically sign messages you send and verify messages. Be aware that text mode signing does not result in a file identical to source upon verification, and is meant for direct human consumption on both ends. Trying to sign binary files with this flag will produce ugly results, but will not necessarily fail.
This is a Go program, so this should be easy enough, provided you have a working Go installation:
go install github.com/Mihara/lotw-trust@latest
The minimum required version of Go is set to be 1.21, though it could conceivably be compiled by 1.18 or later. Binaries for a number of platforms are provided in the releases section. build.sh
will cross-compile binaries for all supported platforms.
See testcases
and test.sh
for simple test cases and a faux-LoTW certification tree structure to play with.
This program is released under the terms of MIT license. See the full text in LICENSE