CipherFS
開発中 · 未リリース · フォーマット変更の可能性あり

信頼できるサーバーを必要としない、クライアント側暗号化のファイル同期

ファイルはデバイスを離れる前に暗号化されます。デバイス同士が直接同期するほか、バイト列を置けるものなら何でも中継に使えます。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 です。

v1 notes.md デバイス A 09-28 14:02 v2 notes.md デバイス A 10-01 09:15 ← 履歴 v3 notes.md デバイス B 10-03 22:40 ← head(現在) v3' notes.md デバイス C 10-03 22:41 ← head(競合) v4 親 = v3, v3' ← 両方の head を見たデバイスが書き込むと競合は終わる

ディレクトリとマウントは現在のバージョンだけを表示し、競合コピーは作りません。バージョンが共有履歴から外れるのは、明示的な消去かリポジトリの保持ポリシー(既定 365 日)によってのみです。まず 30 日間は保留状態となり、その間はどのデバイスからでも取り消せます。

構成

デバイス、ストア、鍵

デバイス

リポジトリの鍵を持ち、平文を読めるクライアント。長期の鍵ペア、人が読める名前、フル / 部分の役割を持ちます。新しいデバイスは短いコードか QR コードでペアリングし、既存デバイスがいない場合は復旧鍵で参加します。

ストア

必要な操作は四つだけ。不変オブジェクトの書き込み、名前による読み取り、プレフィックスによる一覧、削除。オブジェクトは内容アドレスで追記のみ、4〜8 MiB にまとめられます。まだ届いていないオブジェクトは「未着」であり、「破損」ではありません。

鍵

内容の鍵は鍵エポックから導出されます。デバイスを失効させると新しいエポックが開き、その鍵は残ったデバイスにだけラップされます。パスワードはローカル機だけを守り、忘れた場合は復旧鍵で再設定でき、デバイスの身元は変わりません。

シナリオ

使わないファイルを Mac から追い出す

常時稼働の機械をフルデバイスにし、Mac をマウント付きの部分デバイスにします。Mac には固定フォルダと最近読んだ内容だけが残り、それ以外も Finder には表示され、開いたときにフルデバイスかストアから取得されます。キャッシュ予算を超えると、他所に存在すると確認済みの内容は自動的に解放されます。未同期のローカル書き込みと開いているファイルは解放されません。

macOS 27 と FUSE-T で検証済み。マウントは .metadata_never_index を持ち、Time Machine から除外され、Finder で全フォルダを閲覧してもキャッシュは変わらず、オフライン時に未取得ファイルを読むと固まらずに即座に失敗します。

状況

リリースできるか

安定版としてはまだです。確認済みの要件は実装され、それぞれに受け入れの証拠がありますが、ディスク上のフォーマットと API はまだ変更が許されており、第三者によるセキュリティ監査はなく、互換性の約束も一度もしていません。現時点では作者と、フォーマット変更を受け入れられる少数の人に向いています。

2026 年 10 月 12 日時点の検証結果。件数は feature の組み合わせごとの実行回数です。

検証結果
ホスト Rust テスト、既定 feature672 合格 / 0 失敗合格
ホスト Rust テスト、全 feature700 合格 / 0 失敗合格
コンテナ実行、Rust754 合格 / 0 失敗 / 2 無視合格
C ランタイム / Python / Go race15 / 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。書き込み成功はローカルで永続化されたことを意味し、同期、再接続、再試行はバックグラウンドが担います。メモリ使用量はオブジェクトの大きさに依存しません。

既定

アルゴリズム

用途アルゴリズム
内容の AEADXChaCha20-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