Tales from the jar side: Signing an ebook, AI agents, GPT-4.1 token limits, and the usual toots and skeets
You know what you call a series of bunnies hopping backwards? A receding hareline (rimshot)
Welcome, fellow jarheads, to Tales from the jar side, the Kousen IT newsletter, for the week of April 13 - 20, 2025. This week I taught my Managing Your Manager course on the O’Reilly Learning Platform, and my regular schedule at Trinity College (Hartford).
Sure, I’ll sign your ebook
I’ve written six books, and every once in a while somebody approaches me about signing one. My first book, Making Java Groovy, came out in late 2013, and in those days as often as not there was a physical book involved. My publisher (Manning), gave me twenty copies to give away during my talks. Sometimes the person who got a book would want me to sign it.
In the technology world, however, things have changed. Over time more and more developers favored ebooks, either in pdf form or on a Kindle. Occasionally someone would joke about me signing an ebook, but other than a few chuckles, nothing ever came of it.
I could never quite leave that alone, however. As a Java technical trainer, one of the courses I used to teach included a whole unit on JCA, the Java Cryptography API. JCA contains all the necessary classes and interfaces for public and private keys, certificates, and digital signatures. It occurred to me that while I can’t physically sign an ebook (other than using a felt marker on a Kindle, I guess), maybe I could digitally sign an ebook.
What does that even mean? A digital signature is an encrypted hash added to a document, which proves that the signer was the only person who could have done so. What does all that mean? It comes down to PKI, Public Key Infrastructure, which basically powers the internet.
Some basic cryptography
It all comes from cryptography. From the time of Julius Caesar all the way through to roughly the 1970s, cryptography was based on shared keys. I use a key to encrypt my data and sent it to you, and you use the same key to decrypt it. For example, imagine encrypting a message by shifting all the letters forward by a number of places, which is a simple version of the Caesar cipher, supposedly used by Julius Caesar to communicate with his generals in Gaul. You, in the role of one of his generals, would shift each letter backward again by the same number of places, thus decrypting the message.

This scheme is pretty easy to crack (if you only use capital letters in English, there are only 26 possible shifts), but Caesar was dealing with a largely illiterate population, so his approach was reasonable. You can even make a code wheel out of it.
Shared key cryptography is the idea of using that same shared key to do both encryption and decryption, and the history of cryptography for centuries relied on it, just with increasingly complex and time-limited keys.
The rise of the internet changed all that. Amazon can’t create a different shared key for each customer and ask you to remember it or update it on a regular basis, but they have to do something or nobody would be willing to send them their credit card information.
Enter asymmetric, or public-key, cryptography. In that approach, you generate two keys. You use either key to encrypt a message, and the other key to decrypt it. One key is called public, and shared with the world, and the other is called private, and is never given to anyone.

Btw, the cryptographic literature is filled with examples where Alice is trying to communicate with Bob, and Eve (evesdropper) is trying to steal the sent message. Mallory (malicious or malware) is another attacker. Just FYI.
PKI can do more than just encrypting data, though. Say you send me an NDA (non-disclosure agreement) and want me to sign it. The details are boilerplate and don’t need to be secured. You just need to be sure that I signed it.
What I would do is:
Compute a hash of the document, which is a simple summary in a standard form.
Encrypt the hash with my private key.
Send you the document.
You compute the same hash using the same algorithm, and decrypt what I sent you with my public key.
If the results match, you know that (1) the document has not be modified during transit (or the hashes wouldn’t match), and (2) only I could have signed it, because only I have my private key. That’s called integrity (no changes) and non-repudiation (could only come from me).
The encrypted hash is known as a digital signature.
One more step is needed, which is, how do I send you my public key? You need that in order to decrypt the hash, because I encrypted it with my private key. Public keys are sent as part of a digital certificate, which is an electronic document that contains the public key and information about it, as well as information about the identity of the owner.
A valid certificate needs to be verified by a third party, someone we both trust, in order for you to believe it. Otherwise I can just sign the certificate myself, making it what’s known as a self-signed certificate. They’re free, but they don’t have any “trust value,” as the saying goes, because anybody can make one.
Signing a pdf
Returning to the idea of digitally signing one of my books, I don’t really want to sign the full book, because everybody’s copy is the same as every other (other than the fact the publisher might have added your email address to each page), and they can be long, and who wants to deal with passing around all those files?
Given that I practically make a living off of Dad jokes anyway (see the subtitles on my newsletter), it occurred to me that I could do something better. Instead of signing the book, I’ll generate a small pdf for you and sign that. Even better, I can scan my own signature and add it to the page, and then digitally sign the result.
Here’s what you get
That’s a generated pdf file called a Certificate of Ownership that includes my scanned signature, which I then digitally signed. The result is — wait for it — a self-signed certificate (of ownership) signed with my (digital) self-signed certificate (rimshot if there ever was one).
Yeah, that’s a long, long way to go for a gag, but it gets better, or at least there’s more. See that QR code in the bottom left corner? That contains a link to a page that verifies the digital signature.
If you open the document in Adobe Reader, it doesn’t particularly like the signature:
What it doesn’t like, of course, is that I’m using a self-signed certificate and self-signed certificates aren’t trustworthy. But still, the signature is there and it works.
Enter AI, because of course it does
I thought up this entire gag years ago, but I never actually wrote an application to do it. That’s because there are two parts of this project that get long and tedious: One is all that digital signing and verification stuff. The libraries to do it exist, but they’re not simple, and the code gets complicated quickly. The other part is the pdf generation. There are libraries for that too, but they also are not simple or easy to use. While I liked the gag, the amount of work involved to actually implement it was enough of a barrier that I never took the time or put in the effort to do it.
Ever seen the Monty Python skit about the Ministry of Silly Walks?
Here’s the part I want to focus on:
Customer: I have a silly walk, and I’d like to obtain a government grant to help me develop it.
<demonstrates current silly walk>
Minister: It’s not particularly silly, is it?
Customer: I think with government backing, I could make it a lot more silly.
Replace the words “government backing” with AI, and maybe you can see where this is headed: I have a silly gag, and with AI, I could make it a lot more silly.
This week OpenAI released their o3 and o4-mini models, which are reasoning models that are supposed to be good at generating code. At about 4pm on Thursday I didn’t have anything I wanted to do, so I thought I’d explain the gag to o3 and see what it suggested as a possible implementation.
o3 suggested the following tech stack:
Spring Boot, to provide the app as a REST service
Apache PDF Box with Bouncy Castle, to do the digital signing
Flying Saucer, to generate a pdf from XHTML code.
That last choice proved to be problematic and cost me hours, but I didn’t know that at the time. I took the starter code the tool generated, loaded it into IntelliJ IDEA, started up Claude Code in a terminal, and got to work.
I used Canva to design the background, and after fighting with CSS alignment for way too much time, I eventually realized I should just embed the scanned signature onto the background at the right place. After lots of iterations with Claude Code, I eventually realized that Flying Saucer (a library I’d never heard of before) worked on my local machine, but when I tried deploying to Heroku with its virtual file system, it never managed to load my custom fonts correctly. Eventually I realized we could replace it with PDF Box (which was already part of the project), and now it all works.
You can try out the system at https://certificate-service.kousenit.com. There’s a form at the bottom you can fill in to run it, which has a drop-down list containing my six books:
The form generates the pdf and your browser should download the pdf for you. You can then scan the QR code if you like, or not, whatever you choose.
On my local system, I keep a copy of all the generated pdfs, but I’m not doing that on the deployed Heroku site. That’s for version 2, as I tell my students to say when they hit something they haven’t finished yet. If you’re interested in the code, the entire project is in this GitHub repository.
Without the latest generation of AI tools, I don’t think I ever would have done all this. It’s just too silly and the annoying parts are too annoying. But Claude Code did a lot of the tough parts for me, like automatically porting the Flying Saucer code to PDF Box code.
Incidentally, I also tried running the project through the new Junie agent tool built into the latest version of IntelliJ IDEA.
Junie is … okay. It’s very slow, and I’m not sure it’s producing anything all that interesting. Claude Code may cost more, but is much more valuable to me.
GPT-4.1
The other model released this week from OpenAI was GPT-4.1. Wait, 4.1? Aren’t we past that? Didn’t we already do 4.5?
The 4.1 release was highly unusual, because they released it to the API rather than as an option on their website or app. That’s backwards from the way they normally do it, but okay. GPT 4.1 is supposed to be better in a lot of ways, but the interesting feature for me is that its context window has grown to 1 million tokens, like Google’s Gemini.
I tried it out, and it worked, but almost immediately I ran into an unusual problem. In one of my applications, I have a JUnit 5 test where I load up the model and ask it a series of questions about all the data I stuffed into the request. I ran into a problem:
"error": {
"message": "Request too large for gpt-4.1 in organization org-1SttF... on tokens per min (TPM): Limit 30000, Requested 160489. The input or output tokens must be reduced in order to run successfully. Visit https://platform.openai.com/account/rate-limits to learn more.",
"type": "tokens",
"param": null,
"code": "rate_limit_exceeded"
}
Whoa, a tokens-per-minute (TPM) problem. That’s new, and it doesn’t happen when I use Gemini. According to the website in the error message,
My application is about how to take advantage of huge context windows to do prompt stuffing, and (as the error says) my request was over 160K tokens. That’s way beyond the 30K limit of tokens per minute. Heck, if I switch to gpt-4.1-mini, with its 200K TPM limit, I still basically can only ask one question per minute. Also, there does not appear to be any built-in mechanism to do caching of tokens (again, Gemini has a way to do that), in case I want to ask several questions about the same data. They do have a Batch API, and I might be able to use it, but that’s not really the same thing.
That does not appear to me to be terribly well thought out. I might have to make a video about this.
Toots and Skeets
Happy Easter, to those who celebrate
There’s a Westeros joke in there somewhere if you’re not still too damaged by Game of Thrones season 8, but I haven’t found it.
He’s got a point
Come to think of it, yeah.
Is it really good?
I also like this recurring gag:
Awkward.
Make it worthwhile
Speaking of labels
Maybe I should stop now. Okay, just one more.
A line too far
A hotdog is more of a taco, but okay.
Found him!
Actually, I appreciate the lack of effort.
Surprised this doesn’t happen more often
He needs to get used to that.
Speaking of animals:
Memory issues
I suppose it is at that.
We’re all suffering
My new car has both heated seats and a heated steering wheel, which is great. Soon I’ll wish they were cooled instead, but so be it.
Have a great week everybody.
Last week:
Managing Your Manager, on the O’Reilly Learning Platform
My regular schedule at Trinity College (Hartford)
This week:
My regular schedule at Trinity College (Hartford)