これはよく悪い考えだと言われています。最初に動機を述べましょう-これについては遠慮なく批評してください。
セキュリティに過度に関心を持つ傾向がある業界向けの製品を作成する。製品はユーザーファイルを格納して返す必要がありますが、サーバー側で読み取り可能である必要はありません。
クライアント側を暗号化することで、クライアントからの信頼を減らすことができると思います。彼らの機密データは、JavaScriptによってのみ影響を受け、検査および監視できます。また、保存されたデータへのアクセスを許可するサーバー側のセキュリティの問題が原因でクライアントドキュメントが利用可能にならないことも意味します(提供されたJSを変更できる場合を除く)。
私の理想的な解決策は-
- Key generated and injected to all clients users by clients IT team.
- JavaScript uses key to encrypt documents client side. These are then sent to the server and stored.
- On retrieval documents are decrypted again client side.
クライアント側の暗号をサポートするいくつかのライブラリがあるようです。しかし、現在、ユーザーのキーを永続的に保存する方法はありません。理想的には、これはブラウザストアに証明書を追加するのと同様の方法で行われます。つまり、証明書を1回挿入することができます。
誰か提案はありますか?
(明確に言うと、これは、攻撃者が読み取り専用アクセスしか取得できない状況でのみユーザーを保護し、攻撃者がJavaScriptを悪意のあるバージョンに置き換えてからサイトを使用していないユーザーを保護します。悪意のあるユーザーからユーザーを保護しません。最初から、ユーザーがサイトが提供するすべてのJavaScriptを入念に検証または記録しない限り。その最後の部分が重要な場合は、ServiceWorkersを使用して、サイトのJavaScriptの新しいバージョンが実行されるたびにユーザーに警告する方法があるかもしれません。 、しかしそれは別の質問です。)
暗号化キーは、localStorageまたはIndexedDBを使用してクライアントにローカルに保存できます。暗号化キーは、クライアントのJavaScriptが使用する文字列にすることができます。
サポートするブラウザでは、セキュリティを強化するために、代わりにWeb Crypto API(+ IndexedDB)を使用できます。 Web Crypto APIを使用すると、JavaScriptでキーを生成し、それらを暗号化/復号化に使用できますが、JavaScriptコードは生のキーマテリアルにアクセスできません。つまり、攻撃者が1日サーバーにアクセスしてJavaScriptを悪意のあるバージョンに置き換えたとしても、ユーザーのキーを漏らすバージョンに置き換えることはできません。 (ただし、クライアントが自分のファイルをダウンロードして復号化し、次にサイトにアクセスしたときにバックグラウンドでサーバーにアップロードするバージョンに置き換えることもできます。これには時間がかかり、ユーザーが気付く可能性がありますおよび/またはあなた、すべてのユーザーデータがリークされる前に問題を修正するのに十分な時間を与えるかもしれません)
Openpgp.jsからの非対称暗号化を使用する場合、秘密鍵はデフォルトで暗号化されて格納され、ユーザーのパスフレーズでメッセージを復号化または署名するために簡単に復号化されます。
暗号化されて保存されることはなく、ユーザーがキーペアの作成に使用したパスフレーズを覚えている必要があります。
この場合、ハッカーが秘密鍵を見つけたとしても、それらはパスフレーズなしでは役に立たない。
欠点は、パスフレーズを安全にどこかに保存するようにユーザーをトレーニングする必要があることです。
サーバー側のソースコードを制御する場合:
私の提案は、ローテーションするバックエンドに少なくとも4つのキーを保存し、ユーザー対称暗号化サーバー側ですべての暗号化および復号化サーバー側を実行することです。
私のワークフローが(fernet暗号化を使用する)である同様のユースケースがありました:
ユーザーがデータをアップロードし、10個のうち1個の(ローテーション)キーで暗号化してからデータベースに保存
私がDBから取得した後のクエリで、それを復号化してフロントエンドに送信しました
利点:
より安全になり、フロントエンドのすべてのキーを処理します
SQLインジェクションを介してデータベースが悪用された場合、それはプレーンテキストではありません
短所:
プロセスが遅くなるため、サーバー側のリソースがさらに必要
キーは依然としてプレーンテキストのサーバー側であるため、ホストマシンが危険にさらされた場合でも、データを取得するための1つのステップとして攻撃者は依然として助けになります。
サーバー側のコードを制御しない場合:
できる最善の方法は、対称キーをデータベースに保存し、ユーザー登録時にそれぞれに1つ生成することです。ログイン後、そのユーザーのセッションとしてCookieに保存します
利点:
実装が簡単
1つのユーザーアカウントが侵害された場合、各ユーザーは独自の対称鍵を持ち、他のユーザーのデータは復号化できません
短所:
Cookieが盗まれる可能性があるため、iframeヘッダーは必須ではありません
HTTPSおよびHSTS mitm攻撃を使用しない場合、データを簡単に取得できます
しかし、聖杯を待って、より多くの情報源を調査するので、私の提案を受け入れないでください。 ;)
クライアント側を暗号化することで、クライアントからの信頼を減らすことができると思います。彼らの機密データは、JavaScriptによってのみ影響を受け、検査および監視できます。
これは本当ではありません。ブラウザがサイトからダウンロードするJavaScriptを実際に検査および監視することはできません。サーバー/サーバー管理者/サーバーソフトウェアの開発者がバックドア付きのJavaScriptを送信しないと信じるほど信頼できる場合は、私のファイルを保存することを信頼してください。
これは追加のセキュリティ層であることに同意しますが、簡単に取り除くことができるので、実装してもほとんど意味がないようです。これは、いくつかの脅威シナリオから保護します。たとえば、ワイプされていないバックアップまたは古いハードディスクを保護して顧客のデータの漏洩を防止しますが、実際には、クライアントがサービスプロバイダーに入力する必要がある信頼を大幅に減らすことはありません。
しかし、現在、ユーザーのキーを永続的に保存する方法はありません。
クライアント側のブラウザストレージに保存したくない場合は、
a)ユーザーにクライアントのJavaScriptにパスフレーズを提供し、パスフレーズと強力な対称暗号を使用して鍵を対称的に暗号化し、サーバーに保存してそこに保存する
b)キーをQRコードとして表示し、ユーザーに携帯電話で写真を撮らせます。キーを戻す必要がある場合、ユーザーはQRコードが解決するキー文字列をコピーしてクライアント側のJavaScriptアプリに貼り付けることができます。しかし、それは非常に面倒です。