Theme
How witnessed signed logging works
Every SFTP.cloud component keeps a signed record of what it did, and at intervals hands a short signed summary of that record to somebody else. This page explains the whole arrangement once, so that the Tamper evidence page in the Portal and the Log integrity page on your Connector make sense as two views of one thing.
What is recorded, and where
| Component | What it records | Where the files are |
|---|---|---|
| Storage Connector | Every file operation attempt, allowed and denied: session, user, operation, virtual file system, paths, bytes, duration and outcome | audit/ under the data directory: /opt/Syncplify/sc-conn/audit on Linux, C:\ProgramData\Syncplify\sc-conn\audit on Windows, /data/audit in Docker |
| Transfer service (Head) | Its side of every session: what it asked your Connector to do, for which user, on which storage, at what moment | audit/ under its own data directory, on the server we run for you |
| Portal | A mirror of the audit trail: every action taken in the Portal by your team or by our operators | audit/ under each Portal instance's data directory |
The Connector's record and the Head's record are kept on machines owned by different parties. That is deliberate: neither side can quietly bring the other's record into line with its own, so a disagreement between them is provable.
The signed record is not the ordinary service log. The service log goes wherever you point it (a file, syslog, standard output) and can be as verbose or as quiet as you like. The signed record is always on, always signed, always in its own files, and the only thing about it you configure is how much of it is kept.
Layer 1: every line is chained
Each line of a signed file carries a keyed integrity value (an HMAC) computed over the line and the value of the line before it. Change a line, remove one, insert one or reorder two, and the chain no longer computes.
Each file begins with a start line that names the chain it belongs to, its position in that chain, and the closing value of the file before it. So deleting a whole file is visible too: the next file names a predecessor that is no longer there.
The key for each file is derived from a signing identity that lives on the machine (logid.key in the data directory). It is minted once and survives every upgrade. It is never copied anywhere.
What this layer proves
That nobody without the key altered the record. It proves nothing against whoever holds the key, because verifying a keyed value and producing one are the same capability. On your Connector, that is you. This layer alone makes the record a diary.
Layer 2: commitments
At every file rotation, and every five minutes while the record is growing, the machine signs a commitment: a small statement that says "lines 1 through N of file S in chain C produce this integrity value", signed with the machine's identity key (Ed25519). We call it an anchor in the file format.
Commitments are asymmetric: anyone holding the public key can check one, and nobody without the private key can produce one. A quiet machine signs a heartbeat line every four hours so that silence is itself recorded, and never looks like a stopped log.
What this layer proves
That the machine holding the private key stood behind the record at that moment. It still does not stop that machine's owner from rewriting old history and re-signing all of it.
Layer 3: witnessing
Each commitment is kept in a small local spool and delivered off the machine:
- Your Connector's commitments travel over its existing link to the Head, which relays them to the Portal. The Connector can also post them to the Portal directly over HTTPS if you turn that on in its settings; the relay keeps running either way, and witnessing the same commitment twice costs nothing.
- The Head's own commitments travel over its control link to the Portal.
- The Portal witnesses its own commitments too, and publishes its position openly (see below).
The Portal stores each commitment append only, refuses one that contradicts a commitment it already holds for the same machine and sequence number, records identity changes explicitly, and reports gaps in the numbering. On arrival it countersigns the commitment with its own key together with the time it received it.
Only after the Portal has confirmed a commitment does the machine drop it from its spool. If the Portal is unreachable, the spool grows to a bound of one hundred thousand commitments and then discards the oldest, counting what it discarded; the Connector's Log integrity page shows that count, because the resulting gap is permanent and should be explained rather than left to look like tampering.
What this layer proves
A commitment held by an independent party, at a time that has already passed, cannot be revised afterwards. Matching such a commitment means the record has not been rewritten since that moment, not even by whoever owns the machine and holds every key on it. This is the layer that turns the record into evidence.
How long everything is kept
Logs that grow without bound eventually fill a disk, and a full disk takes a machine down. So every part of this feature is bounded, and the bounds are designed so that retirement never breaks verification.
The signed files are retired from the oldest end only, in chain order, never from the middle. The defaults keep a year of record within 4 GB on a Connector (2 GB on a Head), and you can change both on the Connector under Settings, Logging. The floors are seven days and 256 MB: the record can be made shorter, never switched off. A verifier reads a record whose oldest files are gone as beginning where its oldest kept file begins, and says so as a note, not a failure. A file missing from the middle is still a failure.
The witness store keeps every commitment for at least 400 days, so you can always take a full year of evidence away. Older commitments are retired from the oldest end of each machine's sequence; the point they reached is recorded on the machine's identity and shown on the Tamper evidence page as Holding everything since, and any gap that existed below that point stays recorded as a fact. A copy of the evidence file you downloaded earlier stays valid for everything it contains.
Checking it yourself
The verifier is a public, open source program with no dependencies outside the Go standard library. It reads only: it never writes to the evidence it is given, never creates a key, and cannot produce a log line or a commitment.
sh
go install github.com/syncplify/logverify/cmd/logverify@latestCheck the record on your own Connector, including that the files form one unbroken chain:
sh
logverify verify -dir /opt/Syncplify/sc-conn/audit -identity /opt/Syncplify/sc-connCheck a record against a commitment from your evidence file, which is the check that means something to a third party:
sh
logverify anchor -dir ./audit -anchor ./anchor.json -pubkey @./producer.pub -identity ./producer-data-dirExit codes: 0 verified, 1 did not verify, 2 bad arguments or the evidence could not be read. A note in the output is information, not a finding: where a retention trimmed record begins, or an empty file a rotation left behind. The format is specified in the repository's SPEC.md in enough detail to write your own verifier without reading ours.
Holding us to the same standard
We witness your machines, and nobody witnesses us. So the Portal publishes its own record's position at /api/v1/transparency/log, with no sign in required. Record what it says from time to time and keep that alongside your evidence file: it is the only thing that stops us quietly revising our own history later. A commitment older than our retention window answers retired at that endpoint rather than not found, so a chain you walk from an old pin ends at the horizon instead of at what looks like a hole.
The honest limits
- The record proves what a machine did, and that nobody rewrote it afterwards. It cannot say whether what was written was true when it was written.
- A commitment that never left the machine proves nothing against the machine's owner. The Log integrity page tells you how far the confirmed record reaches, in log time, and how many commitments are still waiting.
- Evidence held only by the party you might one day be in dispute with is not evidence. That includes us. Download the evidence file and keep it somewhere we do not control.