The engine behind SilentSilo: the cryptography, the persisted formats, the operation log, sync against storage the user controls, and the standalone extraction tool. AGPL-3.0.
Nothing here knows about a user interface. The desktop application lives in silentsilo/desktop and pins a tag from this repository. Mobile clients will do the same.
No independent security audit has been done. Nobody outside this project has been paid to attack it. The cryptography is specified in
docs/CRYPTO.md, the formats inFORMATS.md, and all of this is readable here. That makes the design reviewable; it is not the same as an audit, and a serious flaw could sit in code that looks right and passes its tests.
| Crate | Role |
|---|---|
silentsilo-core |
Shared types and errors |
silentsilo-crypto |
AES-GCM streaming, envelope encryption, blob format |
silentsilo-vault |
Silo provisioning, keys on disk, the index sealed at rest and ciphered while open |
silentsilo-vfs |
Operation log, folder and file tree, name resolution, snapshots |
silentsilo-sync |
Bucket layout and the transport half of a sync pass |
silentsilo-store |
Backup storage: bucket, folder, WebDAV or SFTP |
silentsilo-s3 |
S3-compatible object storage client |
silentsilo-fido |
FIDO2 security keys and Windows Hello |
silentsilo-extract |
Standalone recovery binary, no interface, no hardware key |
silentsilo-fixture |
Format compatibility corpus |
silentsilo-testkit |
Dev-only: hostile conditions, skip detector |
silentsilo-extract is the answer to "what if the project disappears". It
takes a silo folder or a bucket and a recovery code, and writes out the
files, the trash to one side, the passwords as CSV and the attachments. No
interface, no security key, one source that builds on Windows, Linux and
macOS.
Binaries for all three ship with every desktop release, on the
silentsilo/desktop releases page,
built from the core tag that release pins and signed with the same minisign
key the updater checks. The public half is in
SIGNING-PUBKEY.txt. This repository publishes tags,
not releases.
Files over 16 MiB go up to S3 in parts. If the app is killed mid-upload, the parts already sent stay in the bucket, billed, and no object listing shows them. SilentSilo aborts them when it uploads that file again, and its daily sweep aborts any older than 24 hours. As a second line of defence, add a lifecycle rule to the bucket with the action "AbortIncompleteMultipartUpload" (7 days is a sensible value). Most S3-compatible providers accept the same rule.
cargo test --allThe sync and storage tests run against real servers, and skip themselves
unless one is configured. scripts/test-local.ps1 brings up MinIO (built
from source, which needs Go), WebDAV and SFTP (in containers), points the tests at them, and runs the whole CI
sequence:
./scripts/test-local.ps1It sets SILENTSILO_TEST_REQUIRE_BACKENDS, which turns a suite that skips
itself into a failure: asking for those tests and getting a silent pass is
how they went a development cycle without running. -Stop takes the
containers down again.
To point the tests at a server you already have, set the endpoint yourself:
SILENTSILO_TEST_S3_ENDPOINT=http://127.0.0.1:9000 cargo test -p silentsilo-s3 -p silentsilo-synccargo test -p silentsilo-fixture rebuilds a silo written by a past release
from its storage, using only a recovery code, and compares what comes out. A
fixture whose output changes means released data no longer reads the same
way. The fix goes in the code, never in the fixture.
The fixture corpus has file names long enough that a clone into a deeply
nested directory can hit the 260-character path limit. If git clone reports
"Filename too long", enable long paths once:
git config --global core.longpaths trueSQLCipher builds a vendored OpenSSL, which needs Perl. Git Bash's own Perl
does not work: install Strawberry Perl, and from Git Bash point at it with
PERL=/c/Strawberry/perl/bin/perl.exe. OpenSSL's configure also fails when a
path under the target directory passes 260 characters, so keep the checkout,
or CARGO_TARGET_DIR, short. The first build takes several minutes longer.
Cross-building for Android from Windows needs a Unix-style Perl with its
full module set (MSYS2's /c/msys64/usr/bin/perl.exe, not Git's), make on
the path, and the NDK's clang.exe as CC_aarch64_linux_android with
CFLAGS_aarch64_linux_android=--target=aarch64-linux-android31: OpenSSL's
build runs under sh, which loses the backslash in the .cmd wrapper's path.
S3 and WebDAV check certificates with Android's own verifier
(rustls-platform-verifier), which calls into the JVM. An app linking these
crates has to do three things, or every HTTPS handshake fails with "secure
connections are not set up":
- Call
silentsilo_store::init_android_tls(env, context)once from its JNI entry point, before any sync, with the rawJNIEnvpointer and a raw reference to the applicationContext. Raw pointers, so the app can use anyjnirelease. - Ship the verifier's Kotlin half. It comes inside the
rustls-platform-verifier-androidcrate as a local Maven repository: add that crate'smavenfolder as a repository (find it withcargo metadata --filter-platform aarch64-linux-android) and depend onrustls:rustls-platform-verifier:latest.release. The crate's README has the Gradle snippet. - Keep the class from shrinking:
-keep, includedescriptorclasses class org.rustls.platformverifier.** { *; }
Persisted formats, their versions, and what an older build does when it meets
a newer one: FORMATS.md
Cryptography specification: docs/CRYPTO.md
How the pieces fit and which invariants a change must preserve:
docs/ARCHITECTURE.md