Original post written by Ahmar Wolf
Category: Blog
-

Software Assurance & That Warm and Fuzzy Feeling
If I were to recommend you use a piece of cryptography-relevant software that I created, how would you actually know if it was any good?

Art: Wayward Mutt Trust is, first and foremost, a social problem. If I told you a furry designed a core piece of Internet infrastructure, the reception to this would be mixed, to say the least.
If you’re familiar with the deep lore about furries and the Internet, this probably wouldn’t surprise you.

Screenshot from this old tweet. (We all need hobbies, after all.)
But if you weren’t in the know, you might recoil in horror at the thought. “Hell nah, those cringey people on TikTok?”
Software assurance is chiefly concerned with reliability, safety, and security, which is deeply connected to how trustworthy a piece of software is.
(Trustworthy doesn’t necessarily mean trusted. Everyone is free to choose what they trust, and what they don’t.)
But if you were to approach my work with an open mind, how might someone make an informed decision about whether or not the software I’m writing is trustworthy enough for their use cases?

Art by ScruffKerfluff Cryptography Audits and Other Thought-Terminating Clichés
If you weren’t around for Is TrueCrypt Audited Yet?, you might think this subheading is clickbait.
Cryptography audits and penetration testing in general are valuable work. Audits are essential in avoiding worse outcomes for security in multiple domains (network, software, hardware, physical, etc.).
However, they’re not a panacea, and an audit status should not be viewed as a simple binary “YES / NO” matter.
Some “audit reports” are utterly worthless.
Unfortunately, you basically have to be qualified to do the same kind of work to accurately distinguish between the trash and treasure.
However, this is usually one of the first questions I get from some technologists: “Was it audited? And is the report public?”
Audits are not cheap. Hiring a team of qualified and reputable experts to review the entirety of a nontrivial project can easily run into the six digits.
Let’s be real: I don’t have that kind of money just lying around, and random gay furries aren’t exactly a good fit for a non-profit like OSTIF.
So, no, I don’t have an audit for any of my projects.
If not having an audit is a dealbreaker for you, that’s fine. I would rather you be disappointed with an unchecked box than go out of my way to pay an unqualified company to give me a rubber stamp audit report just to satisfy your request (an act which I consider dishonest).
Audits aside, I’d like to talk about some of the mechanisms I’m employing to make my projects as trustworthy as any mere mortal can hope to achieve.
Art: CMYKat
Towards Furry-Grade Assurance
Let’s not mince words: The rest of this blog post is me nerding out about software testing methodologies, how I’m applying them, and the gap between practice and theory (i.e., formal methods).
The project in scope for this blog post is my Public Key Directory project, which offers an essential building block for making E2EE possible on the Fediverse.
If you want more background about this project, I recommend starting here.
Specification-First Development
Before any code was ever written, I started writing a specification. You can read it online at
fedi-e2ee/public-key-directory-specificationon GitHub.This document covers:
- The motivation for its own existence
- Important concepts relevant to the design
- A threat model which includes:
- Assumptions that must be true in order for the software to be secure. These might seem obvious, but it’s better to be explicit.
- Assets in scope for the threat model.
- Actors with specific roles, privileges, and motivations.
- The actual risks being considered, including many that are not mitigated by design.
- The actual definitions, algorithms, steps, etc.
- Security considerations for implementors of the spec
I started writing this in June 2024, and I continue to make revisions as I develop the reference implementations of the specification. This process will continue until the first major version has been tagged.
By starting with a specification, every party can agree on what the software does, what it doesn’t do, what are its security goals, and why specific trade-offs were chosen in favor of others. Unlike source code, specifications do not carry the quirks of particular programming language runtimes or package ecosystems.
However, put a pin in this, because there’s more to talk about later.
Unit Testing: Table Stakes
Once you have a reference implementation, you need it to pass unit tests in CI. If you’re writing software in 2026 and don’t have working unit tests, your life is harder than it needs to be.
Whenever you bring up unit testing, the next thing that usually comes up is code coverage.
I do not use code coverage reports in any of my projects. To understand why, you should be familiar with Goodhart’s Law: When a measure becomes a target, it ceases to be a good measure.
Code coverage reports can lie to you with pretty green squares, and this leads to overconfidence.
Instead, I actually rely on two distinct additional testing methodologies.
Mutation Testing: Code Coverage That Cannot Lie
Mutation testing is simple enough to understand.
First, run your full unit test suite and keep track of which unit tests touch which parts of the source code. Then, mutate the source code and study how the test suite behaves.
If the tests still pass when a line of code was changed, then either the change was benign (to the point of being meaningless), or your unit tests don’t really cover it.
The ratio of mutants that survive your test suite to the total number of mutants created is often represented as a percentage. The framework I’m using (Infection) calls this percentage MSI (Mutation Score Indicator).
How I’m Using Mutation Testing
The cryptography code present in the Public Key Directory project lives in its own repository: pkd-crypto. As I write this, I have an open pull request that kills 89% of mutants in the codebase. I aim for over 90% before I merge it, and over 95% before I tag a stable v1.0.0 release.
The cryptography code is used by both the client and server-side reference software. The server-side software currently has a minimum MSI of 80%, though I will be ratcheting that up higher as well.
“Why not aim for a 100% MSI?”
Not all mutants are bugs. For example, some of the code I write is meant to avoid side-channels. So the original code, which works on integers in the range of 0 to 255, might look like:
$isCR = ((($char ^ 0x0d) - 1) >> 8) & 1);
But then the mutation testing framework will try:
$isCR = ((($char ^ 0x0d) - 1) >> 9) & 1);
Does this mutant escape? Yes.
But is there any possible value in the range for
$charthat will lead to an incorrect output? No.-1 >> 8 == -1 >> 9.Now, I could extract these bitwise operators out into functions that I can externally test in isolation (rather than as part of a larger algorithm). That would let me get a higher MSI out of this library.
However, the PHP language doesn’t support macros (at least as of 8.5). Aiming for a 100% score would introduce function call overhead in a critical loop that could negatively impact performance.
Fuzz Testing
(Sorry, I couldn’t decide on a “furry” pun for this subheading.)
Fuzz testing (or “fuzzing”) is an automated testing technique that involves generating many invalid inputs in order to study a program’s behavior.
There’s a little more to fuzz-testing than “throw everything at the wall and see what sticks”. A sophisticated fuzzer such as afl (or afl++, its successor) can reliably learn to invent JPEGs as part of its generation algorithm.
Y’know those jokes about QA engineers?
A software QA engineer walks into a bar.
He orders a beer. Orders 0 beers. Orders 99999999999 beers. Orders a lizard. Orders -1 beers. Orders a ueicbksjdhd.
First real customer walks in and asks where the bathroom is. The bar bursts into flames, killing everyone.
I do not know who originally told this joke. If anyone knows, I will update this with a link to credit the original source. Too many joke thieves online.
That’s basically fuzzing.
Currently, for my projects, PHP-Fuzzer runs on every push and pull request against the main branch for some reasonable number of runs, and then a lot more whenever a release is tagged.
- pkd-crypto fuzzes every significant component that parses or (de)serializes data
- pkd-server-php goes a bit deeper and fuzzes the HTTP request handlers as well
Separately (though this is less visible from the CI config), I run it in the background without limits to see if any interesting behaviors emerge.
The combination of fuzzing and mutation testing provides a deeper and broader level of assurance than any PHPUnit-derived code coverage report ever could on its own. But why stop there?
Static Analysis
I actually employ multiple tools here. Psalm and PHPStan are both useful for identifying a wide range of problems in PHP code, ranging from “what the hell even is this variable’s type?” linting to full on “yeah this is a SQL injection vuln” taint analysis.
However, I also added a security-focused static anaylsis tool called Semgrep to the mix. Semgrep runs with rules specifically intended to identify unsafe PHP code.
This all runs in CI, on every commit, and complains loudly if anything is amiss.
Property-Based Testing
This comes up a lot in discussions about testing methodologies, so it bears mentioning here.
Property-based testing is a complementary approach to fuzzing that emphasizes logical correctness rather than security properties.
This can all sound kind of vague and abstract, so here’s a clear example:
If you encrypt a field, then decrypt the corresponding ciphertext, you should always get the same input.
This property should hold true for random inputs and random keys, as long as they’re used correctly (i.e., the same key is used for both operations).
In addition to what was mentioned above, the pkd-crypto project uses a PHPUnit-compatible tool called Eris for property-based testing.
Integration Testing
I’ve talked a lot about pkd-crypto (the common cryptography components for both client- and server-side code) as well as pkd-server-php (the actual server-side software implementation of the spec).
If you’re wondering, “What is about the client-side software?” you’ve activated my nerd-snipe card.
The client-side software I’m developing is deliberately very dumb in scope: It’s mostly a thin HTTP Client wrapper that talks to pkd-crypto to generate/validate things.
But that’s also where a deeper integration test resides. The client-side software does the following with each build:
- Clones the pkd-server-php repository and configures it to run locally.
- Clones a miniature Fediverse server implementation I wrote for the purpose of test orchestration.
- Tests the client against the local PKD server and mini-fedi-server.
The client library is still being developed, but this integration testing setup will allow me to create contrived scenarios and test their behavior thoroughly in a reproducible way.
What Is Left To Do
As cool as all this stuff is, there are still gaps left to fill that could undermine the security or reliability of this project. Of course, I’m actively working on addressing these.
Formal Verification
What if I could give you a machine-verifiable mathematical proof that my design is secure?
That’s what formal verification is all about.
My current plan is to write ProVerif models of the PKD specification. I intend to cover the core algorithms, the state machine that runs atop the Transparency Log, and the risks covered by the threat model.
There are other tools I’m considering as well. Using hacspec for a future Rust implementation is a tantalizing prospect.
Requirements Traceability
Towards the top of this blog post, I’d said to put a pin in the specification. It’s time to unpin that.
Requirements traceability tools allow you to tie your implementation and testing framework into the requirements from a formal specification.
AWS released a tool for this purpose called Duvet, which supports parsing RFC-style specification documents to obtain a corpus of requirements. You can then instrument your code and tests to cover these requirements (e.g.,
fooMUST be set tobar), and Duvet will report on any gaps you still have.Requirements traceability is the critical last mile of providing high assurance for this project:
Formally verifying the specification is almost useless without a mechanism to ensure the actual implementation adheres to the spec.
Unfortunately, Duvet doesn’t currently support the ProVerif comment syntax, so I cannot even get started on this work.
On that note!
From what I understand talking with ex-employees, Amazon has a culture of so-called “customer obsession”.
What this means in practice is, unless you have an enterprise customer literally asking for a specific feature, the demand for it might as well not even exist.
They don’t pay much attention to reactji on GitHub issues.
They do pay attention to what their big customers are asking their technical account managers about when planning to spend tens of millions of dollars on compute.
If anyone reading this works for a company that spends a lot of money on cloud services, ask about their investment into assurance tools like Duvet.
The more interest there is, the better these tools will become.
Isochronic Verification
Put simply: How do you know if your code is actually constant-time?
Many cryptographers and security engineers consider this property a losing battle against compilers and hardware optimizations.
Others are developing standardized constant-time support into mainstream compilers in order to ensure the mitigations never get optimized away.
This might not matter much for the reference implementation in PHP (which cannot guarantee its own runtime is side-channel free). But, as that matures and I look towards implementations in Go and/or Rust, I do plan to identify mechanisms for ensuring the compiled code is free of side-channels.

Art by AJ Closing Thoughts
I hope anyone that reads this blog post walks away with a good understanding of the measures I’ve taken to hedge against my own mortal fallibility as I build the Public Key Directory project, as well as the additional work I plan to do as this project matures.
While there will always be hold-outs that do not trust pseudonymous nerds for whatever personal reason, I do hope that anyone with an open mind walks away feeling like their friend just gave them a big hug in their first freshly-unboxed fursuit.

Credit: CMYKat
Header art: Harubaki and CMYKat
Original post written by Soatok
-

Ibercon (Spain) Sets Attendance Record

We already surpassed last year’s attendance number! Wow, you are all amazing!

With more than 500 attendees already confirmed for this edition and still so many months to go, the more of you there are, the more excited we are to prepare everything!
We’ll keep working hard to live up your trust!

Original post written by Ahmar Wolf
-

Fauntastic Wants You

Hi space groovers!If you would like to host a conference or event about a topic that is close to your heart, now is the time.
What: Whether it is related to this year’s theme or not, we are interested in all types of topics (in accordance with our code of conduct).
How: Use this form (https://pretalx.fauntastic.eu/fauntastic-2026/cfp)
When: From now until January 31stIf you have any questions, please contact @Habaxin.
Thank you for helping us make Fauntastic the event it is now!
See you soon in orbit!
Art by Dragon (@adragonswinging)
Original post written by Ahmar Wolf
-

Wild North Age of Heroes announced 2026 Update

Calling all Adventurers!
Wild North – Age of Heroes
18th – 21st September 2026
Lumley Castle, Chester-le-Street, County Durham, UK
Registration opens soon!
Art by Kitsugambas
Original post written by Ahmar Wolf
-
Carolina Furfare Hotel Block Open
Winter’s chill only sharpens the senses. Book your cozy room now and stay warm while looking for the unknowns!

https://www.carolinafurfare.org/hotel
Original post written by Ahmar Wolf




Art: 










Hi space groovers!
What: Whether it is related to this year’s theme or not, we are interested in all types of topics (in accordance with our code of conduct).
How: Use this form (
When: From now until January 31st



