コンテンツへスキップ
HexaTransfer
ブログへ戻る
技術詳解

ファイル転送におけるエンドツーエンド暗号化の仕組み

エンドツーエンド暗号化が転送中のファイルをどう保護するか、暗号プロトコルと実装の技術的な詳細を深掘りして解説します。

ファイル転送におけるエンドツーエンド暗号化とは、デバイスを離れるバイト列がサーバーに触れることのない鍵で暗号化され、意図した受信者だけが復号できることを意味する。サーバーは暗号文を保存し、意味のある内容を見ることができず、侵害されてもファイルの内容は露出しない。個人情報保護委員会(PPC)が定める安全管理措置の観点からも、クライアントサイド暗号化は技術的保護措置の核心に位置する。暗号化の手順はほぼ必ずAES-256-GCMまたはXChaCha20-Poly1305のような対称暗号でファイル本体を暗号化し、X25519 ECDHやRSA-OAEP 2048/4096のような鍵交換で鍵素材をラップする構成になっている。

E2EEが実際に守るものと守らないもの

E2EEが防ぐのは次の脅威だ。転送プロバイダーへのハッキング、サブポーナ(令状)、悪意ある内部行為。プロキシでTLSを復号するネットワーク攻撃者。ストレージバケットのバックアップスナップショットの漏洩。サービス従業員によるインサイダーアクセス。守らないのは送信者・受信者のデバイス上のマルウェア、復号リンクを取得するフィッシング、受信者アカウントの侵害だ。「暗号化済み」という言葉がしばしば「TLS転送中 + サーバーサイドAES保存」を意味するだけで、プロバイダーが鍵を持っている状態を指す場合があるため、脅威モデルの理解が重要になる。

ファイルペイロードの対称暗号化

ファイルは対称アルゴリズムで暗号化される。公開鍵暗号はバルクデータには遅すぎるからだ。現代の選択肢はNIST SP 800-38Dで定義されたAES-256-GCMであり、1回のパスで機密性と認証済みの整合性の両方を提供する。ランダムな256ビットの鍵と、同じ鍵と絶対に再使用しない固有の96ビットノンスが各ファイルを保護する。XChaCha20-Poly1305(RFC 8439およびRFC 8103で定義)は、AES-NIハードウェアアクセラレーションを持たない古いARMプロセッサなどのデバイスで高速な代替手段だ。どちらも暗号文と128ビット認証タグを生成し、改ざんを検出する。

パスワードからの鍵導出

E2EEがパスワードを使う場合、パスワード自体は暗号化鍵にならない。ブルートフォースに対して脆弱すぎるからだ。代わりに、PBKDF2-HMAC-SHA256(OWASPの2025年ガイダンスで60万回以上のイテレーション)、Argon2id(m=19 MiB、t=2、RFC 9106)、またはscrypt(RFC 7914)のような鍵導出関数がパスワードを強い鍵に伸長する。ランダムな128ビットまたは256ビットのソルトがレインボーテーブル攻撃を防ぐ。導出された鍵でファイルを暗号化する。ソルトとイテレーション回数は暗号文とともに保存されるため、受信者がパスワードを入力すると鍵を再構築できる。

アカウントベース転送における公開鍵ラッピング

受信者が公開鍵を公開しているアカウントを持つ場合、パスワード入力は不要になる。送信者はランダムなファイル暗号化鍵(FEK)を生成し、AES-256-GCMでFEKを使ってファイルを暗号化し、次にRFC 7748に基づくX25519 ECDH鍵合意とRFC 5869に基づくHKDF-SHA256を組み合わせるか、PKCS#1 v2.2のRSA-OAEPとSHA-256を使って各受信者の公開鍵でFEKを暗号化する。ラップされたFEKは暗号文の隣に置かれる。受信者の秘密鍵の保有者だけがFEKをアンラップしてファイルを復号できる。これはSignalやWhatsAppがメッセージに使うモデルをファイルペイロードに応用したものだ。

URLフラグメントを使ったリンクベースE2EE

ブラウザベースの転送では巧みな手法が使われる。URLフラグメント(#の後の部分)に復号鍵を格納する。フラグメントはHTTPリクエストでサーバーに送られることがない。https://example.com/d/abc123#k=B9kZtR...のようなリンクはサーバーサイドのファイルIDとクライアントサイドの鍵を運ぶ。ブラウザは暗号文をダウンロードし、JavaScriptでフラグメントを読み込み、ローカルで復号する。サービスは鍵を見ることができない。ただし、ログ、スクリーンショット、メッセージアプリのプレビューなどでリンクが漏洩すると鍵も漏洩する点に注意が必要だ。

AEADとハッシュによる整合性確保

AES-GCMやChaCha20-Poly1305のようなAEAD(認証付き暗号)モードは改ざんを防ぐ。暗号文の1ビットを変えるだけで認証タグの検証が失敗し、復号関数はゴミのような平文ではなくエラーを返す。AEADに加えて、多くの実装は平文のSHA-256またはBLAKE3ハッシュをマニフェストエントリーとして計算し、受信者が復号後にファイルが送信者の意図したものと一致するか検証できるようにする。これはチャンクで転送される大きなファイルにとって重要で、部分的な配信が一部は成功し末尾で無音で失敗するケースを防ぐ。

大きなファイルのチャンク暗号化

10GBのファイルを1回のAES-GCM操作で暗号化するには10GBの状態を保持する必要があり、ブラウザでは非現実的だ。実際の実装ではファイルを通常1MB〜16MBのチャンクに分割し、各チャンクを導出されたサブキーとカウンターベースのノンスで独立して暗号化する。age(age-encryption.org)はChaCha20-Poly1305で64KBチャンクを使う。Magic Wormholeプロトコルはストリーミング構造を使う。チャンク境界により、ブラウザはStreams APIを通じてファイル全体が届く前にディスクへのダウンロードを開始でき、ネットワーク中断時の再開可能アップロードもサポートする。

E2EEの上に乗せるトランスポートセキュリティ

RFC 8446で定義されたTLS 1.3はE2EEの上に依然として重要だ。ペイロードの機密性(すでに暗号化済み)のためではなく、ファイル名、サイズ、タイミングなどのメタデータのプライバシーのためだ。X25519のような前方秘匿性のある鍵交換によるTLS 1.3は、サーバーの長期鍵が後から侵害されても記録されたセッションを復号できない。証明書ピニングまたはHSTS事前登録はダウングレード攻撃を防ぐ。E2EEにTLS 1.3を組み合わせることで、ファイルの内容と誰が何を誰に送っているかという行動パターンの両方を保護する。

よくある実装の落とし穴

3つのミスが繰り返される。第一に、AES-GCMで同じ鍵とノンスを再使用すると機密性が破壊的に壊れる。常に新しいランダムノンスか繰り返さないカウンターを使う。第二に、libsodium、Web Crypto API(SubtleCrypto)、BoringSSLのような監査済みライブラリの代わりに自作の暗号処理を実装する。タイミング攻撃を防ぐために定数時間操作が重要だ。第三に、ファイルのメタデータをコンテンツと一緒に認証しない。送信者のID、ファイル名、受信者リストがAAD(関連認証データ)に含まれていなければ、攻撃者がメタデータを検出されずに入れ替えられる。HexaTransferはこれらの問題に対し、レビューされたパターンでクライアントサイドの標準Web Crypto プリミティブを使うことで対処している。

サービスが本当にE2EEを実施しているか確認する

マーケティングの主張は懐疑的に読む。真のE2EEとは、裁判所命令があってもプロバイダーがファイルを復号できないことを意味する。正確なアルゴリズム(AES-256-GCM、X25519、HKDF、PBKDF2イテレーション回数)を説明した技術文書、監査可能なオープンソースのクライアントコード、E2EEが守るものと守らないものを認めた脅威モデルを確認する。暗号化ファイルのサーバーサイドのパスワードリカバリーを提供するサービスは真のE2EEを実施していない。「ゼロ知識」を主張するサービスは、単なるスローガンではなく暗号プロトコルの説明で裏付けるべきだ。

https://hexatransfer.com — 無料、アカウント不要、最大10GB。

エンドツーエンド暗号化で大容量ファイルを安全に送信

エンドツーエンド暗号化で最大10GBのファイルを無料で転送。アカウント不要。ファイルはアップロード前にブラウザで暗号化されるため、他の誰にも読まれません。

ファイルを送信