対話者に暗号化されたメッセージを送信するよりも簡単なことは何ですか?
公開鍵、秘密鍵を取得し、Diffie-Hellmanを検討し、KDF後の結果をAESに導きます。これで完了です。 ただし、秘密鍵の1つが盗まれた場合、すべて、これより前に傍受されたすべてのトラフィックは問題なく復号化されます。
最新のメッセンジャーとトランスポートプロトコルがこれにどのように取り組んでいるかを説明し、製品にPFSを実装するためのツールを提供します。
PFSを理解するために、キーポイントは一時的なキーペアです。以降、簡単にするために、 一時的な公開キーと呼びます 。 一時キーペアは、セッションがセットアップされる直前に生成され、接続セットアッププロセス( ハンドシェイク )の終了までのみ存続し、使用後すぐに破棄されます。 これにより、ハンドシェイク後に使用されるセッション対称キーの一意性が保証されます。 非対称キーが対称に変わる方法については、少し後で説明します。
一時キーの使用に関していくつかの質問がすぐに発生します。
- 一時キーを信頼する方法は?
- 対談者に一時キーを転送する方法は?
それらをより詳細に検討しましょう。
エフェメラルキーの信頼性
とにかく、どのキーが受け入れられないかは、それがワイヤーの反対側の対談者に結び付けられていないためです。 キーを認証する必要があり、いくつかの方法でこれを行うことができます。
- 一時キーに署名します。 TLSも同様です。
- 異なるキー間で複数のDiffie Hellman操作を使用します。 Noiseプロトコルも同様です。
- 複合アプローチ(信号、Whatsapp)。
最初のケースでは、すべてが明確であるため、接続する前に一時的なキーペアを生成し、証明書などの秘密キーで署名します。 クライアントは、キーが「必要な場所」にあると確信し、それを使用します。
場合によっては、デジタル署名なしで行うことができます。 ノイズプロトコルは、特定のパターンに応じて、一時キーと静的キーとの間でDH結果を「混合」して一般状態にします。 このようにして、メインの静的キーとはかない間の接続が実現されます。
シグナル開発者はもう少し進んでいます。 彼らは、デジタル署名をほぼ放棄し、複数のDHに置き換えることを決定しました。DHは、異なる静的キーと一時キーの間でも発生します。 存続期間の短い一時キーの1つだけが署名されるため、スキームは結合と呼ばれます。 次のようになります。
X3DHと呼ばれます 。
いくつかのタイプのキーを使用します。
- IK -IDキー。 これらは、一度生成される永続的な静的キーです。
- EKは、セッションの前に送信者によって生成される一時キーです。
- SPkは、Identity Keyによって署名された一時キーで、平均寿命は約1週間です。
- OPKは一時的な一時キーです。
また、4つのDH操作があります。そのうちの1つは、ワンタイムキーを使用するオプションです。
DHは、短命と静的の両方の異なるタイプのキーの間に保持されます。 異なるDHの組み合わせにより、相互認証と、主要な静的(ID)秘密キーの盗難の結果に対する保護の両方が可能になります。
次に、2種類の一時キーが必要な理由について説明します。
一時キー配信
最も簡単な方法は、ハンドシェイク中に一時キーを直接転送できるオンライン接続です。 TLS、NoiseSocketはまさにそれを行います。 しかし、対談者がオフラインで、メッセージを送信する必要がある場合はどうでしょうか?
ECIESスキームを使用してみてください。
ただし、PFSは送信者によってのみ提供されます。 一時的なペアを生成し、各メッセージとともに一時的なキーを送信します。 受信者のプライマリ秘密キーを盗むと、すべての保護が役に立たなくなります。
ネットワーク上の場所に関係なく、受信者の一時キーの送信者を配信するための信頼できるメカニズムが必要です!
クライアントに、たとえば100回の一時キーを生成してサーバーに配置するように依頼できます。 対話者が新しいセッションを開始する場合、サーバーにクライアントキーを要求し、クライアントキーを提供してすぐに削除します。
送信者はこのワンタイムキーを取得し、エフェメラルペアを生成し、上の図に示すようにいくつかのDHを実行します。
しかし、1回限りの一時キーが不足し、クライアントに新しいキーをリロードする時間がない場合はどうでしょうか? この極端な場合には、 2番目の再利用可能な一時キーがあります 。 また、PFSも提供しますが、1つのセッション内ではなく、複数のセッション内でのみです。
これを行うために使用されるシグナルとWhatsApp。 そして今、誰でもそれを行うことができます 。
ヴァージルPF
ワンタイムキーをサーバーにプリロードするというアイデアが気に入ったため、Signalの場合と同様に、すべてのユーザーに対してユニバーサルPFSを作成することが決定されました。 すでにヴァージルカードを持っているので、これを行うのは難しくありませんでした。 PFSはどの部分で構成されていますか?
ヴァージルカードサービス
これは通常のカードサービスです。 長期的な身分証明書を保存します。
PFSサービス
彼は、IDカードの秘密鍵で署名された使い捨てで再利用可能な一時カードの保管と発行を担当しています。
PFSプロトコル
上記のX3DH +セッション対称キーの形成+個々のメッセージを暗号化するためのキーの形成。
SDK
iOS、Android、C#(+ Xamarin)でサポートされています。 SDKは、一時キー、セッション、およびメッセージの暗号化と復号化のライフサイクルの管理を担当します。 すべてのSDKは相互に互換性があります。
プロトコルについてもう少し説明します。これは、サーバーからワンタイムキーを受信する機能に加えて、これが情報保護の主要なコンポーネントだからです。
Virgil PFSプロトコル
Signalと同じ原理でX3DHから始まります。 DHを実行した後、対応する一時的な秘密キーを破棄します。
2つの違いがあります。
- 裸のキーが使用されるだけでなく、Virgil Cards
- すべての一時キーは、プライベートIDキーで署名されます。
関連するヴァージルカード:
- IC -IDカード。 ユーザーまたはデバイスのメインマップ。
- OTC-ワンタイムカード。 使い捨ての一時カード。
- LTC-長期カード、再利用可能な一時カード。
- EK-最初のメッセージで送信される一時キー。
ユーザーは、Virgilサービスを信頼する必要がないように、すべてのキーに署名する必要があります。 結局のところ、私たちはメッセージングではなく、暗号化のみに従事しています。
セッションのセットアップ
アリスはボブとチャットしたい。 彼女の行動:
- Virgil Cards Service Identityでボブのカードを取得し、アプリケーションのデジタル署名を確認します。 これは一度行われます。
- PFSサービスから一時カードのバンドルを取得します。 LTC + OTC、またはOTCがない場合はLTCのみ。
- はかないキーペアを生成します。
- 上記のスキームに従ってすべてのDHをカウントします。
- これらのDHをセッションに変換します。
その後、アリスはボブに次のデータを含む最初のメッセージを送信します。
- アリスの身分証明書ID
- ボブの身分証明書ID(ボブは複数の身分証明書を持っている場合があります)
- ボブの長期カードID
- ボブのワンタイムカードID(ある場合)
- エフェメラルキー
- 一時キー署名
このメッセージを受け取ったボブは、対応するプライベートOTC、LTC、IDキーを取り出し、上記のスキームに従ってDHを繰り返します。 この直後に、OTC秘密キーは破棄されます。
さらに、DHの結果を直接使用することはできません;これは安全ではありません。 したがって、キー導出、つまりHKDFを介して実行します。 これは、HMAC-Hashを使用して「弱いキー情報」、この場合はDHの結果を「強力なキー情報」に変換する特別な機能です。
最初のHKDFから、それぞれ32バイトの4つの値を取得します。
- スカ送信者シークレット
- 秘密の受信者SKb
- セッションIDキー
- 追加データキー
次に、HKDFを介して毎回セッションIDキーと追加データキーを実行することにより、セッションIDと追加データを取得します。 これは、追加のサービスデータに対するキーデータの依存関係を削除するために必要です。
したがって、セッションは4つの値で構成されます。
メッセージを送受信するための2つの異なるシークレット、一意のセッションID、およびダイレクトメッセージ暗号化用のAEAD暗号化スキームの追加データとして参加する追加の32バイト。
先ほど言ったように、Virgilはメッセージを送信しません。 したがって、SDKがどのキーでどのメッセージを復号化するかを理解できるように、それぞれにセッションIDを追加する必要があります。
セッションシークレットの最初の2つの値を理由で呼び出しました。 メッセージを暗号化するときに直接使用されるわけではありませんが、HKDFを介して毎回実行されます。 メッセージ暗号化アルゴリズムは次のとおりです。
- 16バイトのランダムなソルトを生成します。
- HKDFを介して対応するSecretをsaltで送信することにより、メッセージを暗号化するための個別のキーとノンスを取得します。
- 受信したキーnonceでメッセージを暗号化します。 追加データとして、セッションから値を渡します。
- セッションID、ソルト、暗号文を送信します。
したがって、各メッセージは一意のキーで暗号化されます。
一時キーおよびセッション管理
これが最も難しい瞬間であることが判明しました。 ほとんどの潜在的な開発者に適した汎用オプションを見つける必要がありました。 最後に、私たちは成功したようです。
2つの問題がありました。 1つ目は、使用されていないが使用された一時カードの処理方法です。 すぐには削除しませんが、サーバー上にないことがわかってからしばらくしてから削除します。 これにより、まだ到着していないがすぐに届くメッセージにチャンスが与えられます。
2番目はセッションの更新です。 セキュリティを強化するために、同じ対話者で新しいセッションを定期的に作成し、古いセッションを削除する必要があります。 セッションが「リーク」した場合、攻撃者は少量のデータのみを復号化できます。 すべてを透過的にするために、古いセッションを永久に削除する前に時間を与えます。
コード!
PFSを学び、それをアプリケーションに統合するのに役立つ素晴らしいチュートリアルを作成しました。
楽しんでいただけましたでしょうか。 ご質問は?