ファイルはデバイスを離れる前に暗号化されます。デバイス同士が直接同期するほか、バイト列を置けるものなら何でも中継に使えます。S3 バケット、ローカルフォルダ、iCloud や Dropbox が運ぶディレクトリ。どれもファイル名や内容を見ることはなく、ロックやアトミック更新も必要ありません。
Rust で実装。CLI、FUSE マウント、Web UI、C / Python / Go バインディングを提供。
i/d7a1…/000412-9f3c…-18204 i/2b90…/000098-71e0…-6112 p/3f/3f8a…-6291456 p/c2/c2d4…-5833728 n/0007-e41b…-2097152 r/d7a1…-epoch3
docs/ contract-2026.pdf 2 バージョン notes.md 競合 2 photos/ 2026-09/IMG_4471.heic 読み取り時に取得 projects/cipherfs/ README.md ゴミ箱: old-drafts/ (14 ファイル)
左はオブジェクト名で、デバイス ID、連番、長さ、暗号文のハッシュから成ります。右はデバイスが復号して表示するファイルツリーで、バージョン数、競合、ゴミ箱を含みます。両者の間にサーバーはありません。
内容、ファイル名、機密メタデータはデバイスを離れる前に暗号化されます。読み取り時に完全性を検証し、誤ったパスワード、改ざん、破損は明確に失敗します。鍵と平文はログにもストアにも届きません。
オフラインでの編集は接続回復後に同期されます。中断した転送は再試行され、重複した転送が古いバージョンを再適用したり復活させたりすることはありません。同時編集は一つの規則で現在のバージョンを決め、他のバージョンはすべて保持されます。
小さなファイルは軽量なまま。大きなファイルはチャンク化、ストリーム処理され、バイト範囲で取得されます。利用者がモードを選ぶことはなく、サイズの境界を越えても意味は変わりません。
暗号化、ファイルモデル、ストレージのトランザクション、同期規則はコアにあります。CLI、マウント、Web UI、言語バインディングはアクセス手段を適合させるだけで、独自のデータベースや規則を持ちません。
すべてのデバイスが共有インデックス全体を保持します。内容は既定ですべてのデバイスに同期されますが、容量の少ないスマートフォンやノート PC は部分デバイスとして、固定したフォルダと最近読んだものだけを保持できます。
デバイスはピアツーピアで接続します。ストアは暗号文オブジェクトだけを保持します。履歴、ゴミ箱、競合は一つの共有バージョンチェーンの見え方であり、すべてのデバイスから見えます。各デバイスは固有の身元を持ち、失効させられます。
すべてのファイルは安定した身元を持ち、パスは属性にすぎません。各デバイスは自身の署名付きログに追記し、他のデバイスはメンバーシップ、ハッシュチェーン、因果依存を検証してからマージします。削除は tombstone バージョン、移動は新しいパスを持つバージョン、競合は因果順序のない複数の head です。
ディレクトリとマウントは現在のバージョンだけを表示し、競合コピーは作りません。バージョンが共有履歴から外れるのは、明示的な消去かリポジトリの保持ポリシー(既定 365 日)によってのみです。まず 30 日間は保留状態となり、その間はどのデバイスからでも取り消せます。
リポジトリの鍵を持ち、平文を読めるクライアント。長期の鍵ペア、人が読める名前、フル / 部分の役割を持ちます。新しいデバイスは短いコードか QR コードでペアリングし、既存デバイスがいない場合は復旧鍵で参加します。
必要な操作は四つだけ。不変オブジェクトの書き込み、名前による読み取り、プレフィックスによる一覧、削除。オブジェクトは内容アドレスで追記のみ、4〜8 MiB にまとめられます。まだ届いていないオブジェクトは「未着」であり、「破損」ではありません。
内容の鍵は鍵エポックから導出されます。デバイスを失効させると新しいエポックが開き、その鍵は残ったデバイスにだけラップされます。パスワードはローカル機だけを守り、忘れた場合は復旧鍵で再設定でき、デバイスの身元は変わりません。
常時稼働の機械をフルデバイスにし、Mac をマウント付きの部分デバイスにします。Mac には固定フォルダと最近読んだ内容だけが残り、それ以外も Finder には表示され、開いたときにフルデバイスかストアから取得されます。キャッシュ予算を超えると、他所に存在すると確認済みの内容は自動的に解放されます。未同期のローカル書き込みと開いているファイルは解放されません。
macOS 27 と FUSE-T で検証済み。マウントは .metadata_never_index を持ち、Time Machine から除外され、Finder で全フォルダを閲覧してもキャッシュは変わらず、オフライン時に未取得ファイルを読むと固まらずに即座に失敗します。
安定版としてはまだです。確認済みの要件は実装され、それぞれに受け入れの証拠がありますが、ディスク上のフォーマットと API はまだ変更が許されており、第三者によるセキュリティ監査はなく、互換性の約束も一度もしていません。現時点では作者と、フォーマット変更を受け入れられる少数の人に向いています。
2026 年 10 月 12 日時点の検証結果。件数は feature の組み合わせごとの実行回数です。
| 検証 | 結果 | |
|---|---|---|
| ホスト Rust テスト、既定 feature | 672 合格 / 0 失敗 | 合格 |
| ホスト Rust テスト、全 feature | 700 合格 / 0 失敗 | 合格 |
| コンテナ実行、Rust | 754 合格 / 0 失敗 / 2 無視 | 合格 |
| C ランタイム / Python / Go race | 15 / 10 / パッケージ全体 | 合格 |
| フロントエンドのビルド、Web スモークテスト | 24 項目 | 合格 |
| 実機 FUSE-T 部分マウント、Finder 閲覧 | キャッシュ 54,288 → 54,288 B | 合格 |
| 要件受け入れ表 | R01–R62 をテストに対応付け | 完了 |
パスワードは CIPHERFS_PASSWORD か対話入力から読み取ります。S3 の認証情報は環境変数から読み、共有インデックスには書き込みません。
cipherfs init --path ~/vault cipherfs put --vault ~/vault --source ./notes.txt --target docs/notes.txt cipherfs store add directory --vault ~/vault --dir ~/Library/CloudStorage/Dropbox/cfs cipherfs sync directory --vault ~/vault --store-dir ~/Library/CloudStorage/Dropbox/cfs cipherfs role set partial --vault ~/vault --read-cache-bytes 2147483648 cipherfs pin add --vault ~/vault --path docs cipherfs mount --vault ~/vault --mount-point ~/CipherFS --background cipherfs devices list --vault ~/vault cipherfs safe-to-remove --vault ~/vault cipherfs history --vault ~/vault --path docs/notes.txt cipherfs export --vault ~/vault --target ~/plain-copy --history
Rust アプリケーションは SyncedVault を使います。put、put_from_reader、get、get_to_writer、get_range、delete、list。書き込み成功はローカルで永続化されたことを意味し、同期、再接続、再試行はバックグラウンドが担います。メモリ使用量はオブジェクトの大きさに依存しません。
| 用途 | アルゴリズム |
|---|---|
| 内容の AEAD | XChaCha20-Poly1305(任意で AES-256-GCM、ChaCha20-Poly1305) |
| チャンク化 | FastCDC、min/avg/max 1 / 4 / 8 MiB、ユニット上限 16 MiB |
| 内容アドレス | BLAKE3 |
| デバイスの身元 | ed25519 署名、X25519 ラップ、P2P ノード ID を兼ねる |
| ローカルパスワード | Argon2id でローカル鍵素材をラップ。同期されない |
| 転送 | QUIC(Iroh)。ストアへは必要に応じて HTTPS |