web-dev-qa-db-ja.com

どこにも保存されておらず、所有者しか知らないキーを使用して、フロントエンド/バックエンドのデータを暗号化する方法は?

主に Javascript暗号化が有害と見なされる の記事にリストされている多くの理由により、クライアント側の暗号化がどのように良い考えではないかについて、たくさんの回答とチュートリアルを読みました。いくつかの事実

  1. アプリはHTTPSを使用します
  2. サーバー側とクライアント側の検証があります
  3. ユーザーのパスワードと次のシナリオの間にリンクはありません
  4. サーバー側はRESTful Webサービスです(セッションは一切ありません)
  5. バックエンドはユーザーにJWTを発行します
  6. バックエンドは、ユーザー/パスワードとoauth(つまり、fb、Twitterなど)の両方を許可する場合があります。

クライアント側で何を暗号化したいですか?

ユーザーは、フロントエンドアプリ(Vue.js、Angular、Reactなど)を介して個人情報(名前、住所、電話番号など)を入力します。

これがうまくいくとどう思いますか?

ユーザーはフィールド(個人情報の断片など)を選択し、[暗号化]をクリックします。ユーザーは暗号化キーを提供します。フロントエンドはjs crypto libraryを使用して情報を暗号化し、DOMでそれらを置き換えて、暗号化キーをバックアップするようユーザーに通知します。

この情報をサーバーに伝えるにはどうすればよいですか?

フロントエンドは、個人情報(プレーン/テキストまたは意味不明)を含むHTTP PUTまたはPOSTリクエストをサーバーに送信します。サーバーは受信データ(SQLや他の形式の注入を除く)を気にせず、すぐにデータベースに格納します。このリクエストにはencryption keyは含まれませんが、暗号化されたフィールドを指定するフラグが含まれる場合があります。

解読する方法は?

ユーザーが情報を要求すると、バックエンドはサーバーにあるものをそのまま返します。暗号化されている場合、情報はgibberishとしてユーザーに表示されます。フラグを使用して、システムはそれらにdecryptオプションを与え、それをクリックするとencryption keyを入力するように求め、ローカルで復号化を行います。

究極の目的は?

まず第一に、そのサーバーとデータベースおよびすべてが防弾であるようにあらゆる努力が払われますが、何らかの理由でサーバーがハッキングされた場合、ハッカーは意味不明な個人情報に結び付けられた大量の情報を取得することになります。

究極の質問

インターネット経由で読む場合、Javascriptでの暗号化は推奨されないため、私の質問

  1. 上記のシナリオと要件を考慮して、上記の実装を課すリスクは何ですか?
  2. ユーザーのみがキーを制御し、どこにも保存されない、推奨されるアプローチはありますか?
  3. この情報をバックエンドで暗号化する場合、encrypt keyをユーザーと安全に通信するにはどうすればよいですか?キーxyzを使用して情報を暗号化し、xyz暗号化キーをクリックして表示するための安全なリンクをユーザーに提供します。
  4. フロントエンド、バックエンドベースの暗号化について、他にどのような提案がありますか?

私は、ユーザーだけがキーを復号化する方法を知っているという信頼をユーザーに与えたいと思います。より効率的な方法でそれをどのように達成できますか?暗号化キーを保存して管理する必要はありませんか?

2018年7月17日更新

受け入れられた答えに基づいて、私がここでソリューションを実装する方法について中程度の投稿を書きました https://medium.com/@rhamedy/encryption-decryption-of-data-based-on-users- password-using-pbkdf2-aes-algorithms-592f8c1bb79a

7
Raf

最初のユーザー登録時に、暗号で保護された疑似乱数ジェネレータを使用して強力な暗号化キーを生成します。このキーは、ユーザーのデータを暗号化するためのデータ暗号化キー(DEK)として機能します。しかし、DEKをどこかに、少なくともプレーンテキスト形式で保存する必要はありません。 PBKDF2などの鍵導出関数を使用して、ユーザーのパスワードから暗号鍵を導出したい。ユーザーのパスワードから導出した鍵(Key Encryption Key、またはKEK)を使用して、DEKを暗号化します。次に、そのDEKのciphertextをデータベースに安全に格納できます。

その後ユーザーがログインするたびに、ユーザーを認証するだけでなく、パスワードからKEKをすべて導出し、その派生キーを使用してDEKの暗号文を復号化する必要があります。 DEK セッション内をクライアントではなくサーバーに保存します。今、あなたは仕事をしています。 DEKを使用して、セッションがアクティブである限りサーバー側の情報を復号化できますが、セッションの有効期限が切れた後は復号化できません。これには、ユーザーがいくつかのgobbledegook暗号文を凝視する必要がないという利点があります。代わりに、「暗号化された」などのプレースホルダーコンテナーDOM要素を用意し、その要素のクリックをリッスンして、データベースから暗号文を取得するAPIエンドポイントの呼び出しを呼び出し、サーバー上でDEKを使用して暗号化を解除できます。セッションに保存したものを、その場でプレーンテキストとしてクライアントに返します。そこでユーザーが見ることができるように、UIに挿入できます。機密データをクライアントに保存する必要はなく、クライアントで暗号化操作を実行する必要もありません。このアプローチには、DEKが長期にわたって一定であるという追加の利点もあります。ユーザーが自分のパスワードを変更する場合は、新しいパスワードからKEKを導出し、新しいKEKで以前と同じDEKを再暗号化し、以前と同じようにデータベースにDEKの新しい暗号文を保存します。

6
vrtjason