BASALT · JOURNAL
Reproducible redaction, and why a byte-identical result matters
Run the same redaction twice on the same document with most PDF tools and you get two different files. Same visible result, different bytes, different hash. That is normally harmless and occasionally it is the difference between a checkable claim and an argument.
Reproducible redaction means the opposite: the same input file plus the same set of marks produces a byte identical output every time, on any machine, at any date. This post covers why PDF output is normally nondeterministic, what has to change to make it deterministic, and what that buys you in an actual dispute.
Why PDF writers are normally nondeterministic
A PDF writer makes dozens of arbitrary choices that have no effect on rendering and every effect on the bytes.
Timestamps. The document information dictionary carries /CreationDate and /ModDate. The XMP packet carries xmp:CreateDate, xmp:ModifyDate, and xmp:MetadataDate. Every one of these is written from the system clock at save time, so two saves one second apart differ.
Identifiers. The trailer /ID array is a pair of byte strings meant to identify the file and its revision. Writers generate the first element from a hash of the content plus the time, or from a random source. The XMP packet also carries xmpMM:DocumentID and xmpMM:InstanceID, typically fresh UUIDs.
Object numbering. The order in which objects are allocated numbers depends on the order the writer walks the document graph, which in many implementations depends on hash table iteration order. Hash seeds are frequently randomized per process, so the same document serialized twice gets different object numbers, different cross reference offsets, and a completely different byte layout.
Compression. Deflate output depends on the compression level, the library version, and the window and strategy settings. Two zlib versions produce different valid compressed streams for the same input. Object streams add another layer: which objects are packed together, and in what order, is a writer choice.
Font subsetting. When a writer subsets a font it picks a six letter tag prefix, often randomly, and chooses which glyphs to retain based on a set that may be iterated in nondeterministic order.
None of these change what the page looks like. All of them change the hash.
What determinism requires
Making the output byte identical means eliminating every source of variation above, deliberately, at each point.
Timestamps have to be derived from something stable rather than the clock. Either they are omitted entirely, which is the correct choice for a redacted output where creation metadata is being stripped anyway, or they are derived from the input document's own values.
The trailer /ID has to be computed as a function of the content rather than drawn from a random source or the clock. A hash over the serialized body is the natural choice, and it is compatible with the spec's requirement that the value be reasonably unique per file.
Object numbering has to follow a defined traversal order: a canonical walk over the document structure, with any collections sorted by a stable key rather than iterated in hash order. This is the single largest source of nondeterminism in most writers and the one that requires the most discipline to remove, because it means every internal container has to be ordered.
Compression settings have to be pinned, and the compression implementation has to be treated as part of the specification of the output. In practice that means a fixed level and a fixed library, and it means output can change across a version upgrade unless the writer holds the encoder stable.
Font subsetting tags have to be derived from the retained glyph set rather than generated randomly, and the retained set has to be ordered.
What it buys you
Independent confirmation of a production. This is the main one. If you produce a redacted document and record the marks that were applied, another party can take the original, apply the same marks, and compare hashes. A match proves the produced file is exactly what those marks yield from that original. Nothing else was changed, added, or removed along the way.
Without determinism the same exercise proves nothing, because a mismatch is expected even when both parties did the identical thing. You are left comparing rendered pages by eye, which does not detect changes to metadata, attachments, or the update chain.
A meaningful certificate. A certificate of redaction records the SHA-256 of the output. With a nondeterministic writer that hash is only an identity check: it tells you whether the file changed since it was signed. With a deterministic writer the hash becomes something a reviewer can independently recreate from the inputs, which is a much stronger form of evidence.
Regression safety in your own process. If you re-run a set of productions after upgrading your tooling and the hashes all match, you know the upgrade changed nothing about the output. If some change, you know exactly which documents to look at. Firms that produce in volume can hash a corpus and re-verify it periodically, which turns "did anything drift" from a review project into a comparison.
Detecting silent alteration. Documents get re-saved by review platforms, email systems, and PDF viewers, often without anyone intending it. Any of those touches changes the bytes. If the hash of the file in the record does not match the hash you recorded, you know something re-wrote it, and you can produce your copy.
What reproducibility does not claim
It does not mean two different tools produce the same file. Determinism is per implementation. Basalt's output is byte identical to Basalt's output; it is not byte identical to anything else's, and it should not be expected to be.
It does not mean the redaction is correct. A deterministic writer that misses an OCR text layer will miss it deterministically. Reproducibility is a property of the serialization, and correctness is a property of the redaction engine. They are independent, and you need both. The correctness side is covered in how to check whether a PDF was really redacted.
It also does not survive re-processing. Once someone opens your file in another application and saves it, the bytes are that application's, and the hash chain is broken from that point. This is a reason to keep an unmodified copy of what you produced alongside the certificate.
Marks as a portable artifact
Determinism only helps if the marks themselves can be transmitted. "We redacted the addresses" is not reproducible; a mark list with page numbers and rectangles is.
That implies marks should be recorded in a stable format, tied to the original file's hash so it is unambiguous which document they apply to. Then the reproduction procedure is mechanical: take the original, load the marks, run, hash, compare. A reviewer who does not trust your tool can still confirm that your tool applied exactly those marks and nothing else.
There is a related benefit for repeated work. A large production where the same categories of information are redacted across many documents becomes a defined procedure rather than a series of individually judged operations, which is both faster and easier to audit. That is discussed in PDF redaction for law firms.
Frequently asked questions
What is reproducible redaction?
Reproducible redaction means that the same input file plus the same set of marks produces a byte identical output file every time, on any machine and at any date. That lets a third party take the original, apply the recorded marks, and compare hashes to confirm exactly what was filed. Most PDF writers cannot do this because their output varies on every save.
Why do two identical redactions produce different files?
Because PDF writers embed values that change on every run: creation and modification timestamps, the trailer /ID array, XMP document and instance identifiers, and randomly generated font subset tags. Object numbering often depends on hash table iteration order, which many runtimes randomize per process. None of this affects how the page looks, and all of it changes the hash.
How does byte-identical output help in a dispute?
It converts a claim into a checkable fact. If opposing counsel has the original and the mark list, they can re-run the redaction and compare their hash to the produced file, and a match proves nothing else was added, removed, or altered. Without determinism a mismatch is expected even when both sides did the identical thing, so the comparison proves nothing.
Does reproducible output mean the redaction is correct?
No. Determinism is a property of how the file is serialized, and correctness is a property of the redaction engine, so a tool that misses an OCR text layer will miss it identically every time. You need both, which is why the output should be verified against the written bytes by an independent parser as well as being reproducible.
Will two different PDF tools produce the same bytes for the same redaction?
No, and they are not expected to. Determinism is per implementation: one tool's output is byte identical to its own output on the same inputs, not to another vendor's. Reproduction has to be performed with the same tool that produced the original file.
What breaks the hash after a document is produced?
Any application that re-saves the file, which includes review platforms, some email gateways, and PDF viewers that write on close. Once that happens the bytes belong to that application and the recorded hash will not match. Keep an unmodified copy of exactly what you produced, alongside the certificate, so you can show the original.
Do I need to record the marks separately for this to work?
Yes. Determinism only helps if the marks can be transmitted, since "we redacted the addresses" is not reproducible while a list of pages and rectangles is. The mark record should be tied to the hash of the original file so there is no ambiguity about which document it applies to.
Can I use reproducibility to check my own work over time?
Yes, and it is one of the more practical uses. Re-run a corpus of past productions after a tooling upgrade and compare hashes: if they all match, nothing about the output changed, and if some differ you know exactly which documents to examine. That turns drift detection into a comparison instead of a review project.
Doing it in Basalt
Basalt writes byte reproducible output: the same file plus the same marks produces a byte identical result, so opposing counsel or an auditor can re-run the marks and confirm what was filed. Timestamps, identifiers, object ordering, and compression settings are all made deterministic rather than left to the clock and the allocator.
The hash of that output is recorded in a signed certificate of redaction using Ed25519, verifiable with shasum and openssl alone. Before any file is written, a built in verifier re-opens the bytes with an independent parser and proves the redaction, and if it cannot prove it, nothing is saved.
The engine runs as a separate process with no network entitlement, enforced by macOS at the code signature level. Basalt is $29 once for up to three Macs, free for 24 hours, and a 17 MB download.
Redaction that proves itself
Basalt destroys the content you mark, then re-opens the file it wrote and proves the content is gone before it saves anything. Your documents never leave your Mac.