現在、保存する機密データ(個人医療データ)を使用するWebアプリケーションに取り組んでいます。アプリは着想の非常に最初の段階にあり、実際の人々のデータを使用して、非常に限定された規模で、本番環境で使用されるベータ版をすばやく作成します。数か月間のベータテストと改良を経て、アプリはより大規模に製品化されます。
私の目標は、ベータ版が終了したら、専門家を雇ってアプリのセキュリティを確認し、いくつかのペンテストを実行することです。しかし残念ながら、これは現在のところ、ビジネス上および財務上の理由で解決できません。私は主にWeb開発者であり、多少はセキュリティの高度な基本を知っていますが、セキュリティの専門家ではないため、状況は理想とはほど遠いですが、現在、他の選択肢はありません。これらのデータは医療用であるとしても、それほど機密性が高いわけではありませんが、できる限り安全に保護したいと考えています。
ベータ版の場合、グローバルプロジェクトは次のとおりです。私のバックエンドは、静的ファイルを提供してデスクトップ上のwebappにアクセスするnode.jsサーバーと、データにアクセスして提供するapiで構成されています。私のフロントエンドは主にAndroidアプリです。全体はローカルネットワークのオンプレミスでセットアップされ、最悪の場合、外部リソースへのアクセスはまったくありません。クラウドベースのキー管理システムなどを使用できません。
私は顧客用のデータベースを1つ持っており、タブレットやデスクトップコンピューターを介して複数のユーザーがアクセスします。
タブレットが最終的にオフラインになる可能性があり、データベース全体が比較的小さくなるため、目標はタブレットにデータベース全体をダウンロードし、後で変更されたすべてのデータを同期することです。最も機密性の高いデータは、ほとんどの場合、タブレット上で暗号化されたままで、必要な場合にのみ復号化されることを望みます。変更が加えられた場合、データはサーバーに送信される前に、タブレットで暗号化されます。
現在私が計画していることは、すべての機密データをデータベースで暗号化することです(キー "K1"を使用)。暗号化されたデータと暗号化キーの両方をサーバーに保存しないようにするには、そのキー自体がキー「K2」で暗号化されます。こうすることで、暗号化されたK1をタブレットに保存し(アプリのソースにハードコード化)、他のキーをサーバーに保存し、必要に応じてタブレットに送信できます。主な目的は、サーバーにアクセスする攻撃者が暗号化されたデータと暗号化キーの両方にアクセスできないこと、およびタブレットが盗まれた場合、暗号化キーK1が容易に漏洩されないことです。
このソリューション自体はまだ弱いかもしれませんが、できる限り取り組んでいますが、いずれにせよ、1つの大きな欠点があります。ブラウザを介してWebアプリケーションにアクセスするときに、クライアント側のキーをハードコーディングできないのです。特定のデスクトップアプリがインストールされている(私がインストールすることもできますが、これにより、プロジェクトがさらに複雑になり、時間のかかるタスクが追加されます)。私が考えるすべてのソリューションは、暗号化されたデータと暗号化キーの両方を同じサーバー上に置くことで終わります。私が知る限り、これは回避したい大きな欠陥です。
だからここに私の質問です:完全に安全ではないにしても、完全に欠陥があるわけではないにせよ、この暗号化キーを暗号化されたデータとともにサーバーからWebクライアントに送信する方法はありますか?または、フロントサイドでデータを復号化し、サーバーが暗号化キーにアクセスすることを回避する方法はありますか?
私が説明した解決策についてのコメントも、特にそれが絶対にひどいものであると私に伝えることである場合は、高く評価されます。よろしくお願いします!
まず、暗号化、プライバシー、および医療データに関する法律を本当に理解できるようになるまで、開発を停止します。金銭的な理由でソリューションを検査および認定する専門家がいない場合、金銭的な理由でソリューションを開発しないでください。設計とテストの支援を専門家に依頼するのに費やされる費用は、データ漏洩イベントによる罰金と画像の損傷よりも数桁少ない額です。
次に、データベース全体をクライアントに保存しないでください。スケールしないため、0日目からスケールを考慮して設計する必要があります。設計によって拡大縮小されないものを設計する場合、それは後であなたを噛みます。ハード。
これを続けたい場合(サイエンスの場合、または学習する場合)は、エンベロープ暗号化を使用します( このIBMリンク は、わかりやすい説明です)。これは基本的に、クライアントがデータを生成し、対称鍵で暗号化し、この鍵を自分の鍵で暗号化し、暗号化データと暗号化鍵を一緒に送信することを意味します。サーバーはblobを保存し、その内容については何も知りません。
クライアントがデータを必要とするとき、それはブロブを受け取り、暗号化された対称鍵を抽出し、鍵を復号化し、それを使用してデータを復号化します。
ユーザーの秘密鍵をどのように作成しますか? Key Derivation Function(KDF) が必要です。 KDFはユーザーのパスワードと他のいくつかのパラメーターを受け取り、キーを生成します。同じパラメーターでKDFを実行するたびに、同じキーが出力されます。これは非常に特殊なハッシュ関数と見なすことができます。常に同じ値を入力すると、常に同じハッシュが返されます。
しかし、ユーザーが自分のパスワードを変更したい場合はどうでしょうか。すべてのデータが失われましたか?いいえ、ちがいます。中間キーを作成し、それを使用してすべてのDEKを暗号化し、この中間キーをユーザーキーで暗号化する必要があります。暗号化された中間キーをサーバーに保存します。ユーザーがパスワードを変更したい場合は、暗号化された中間キーを取得し、現在のキーで解読し、パスワード(およびその結果、秘密キー)を変更し、新しい秘密キーで中間キーを再暗号化して保存します。それが戻った。
また、ユーザーがキーを忘れた場合はどうなりますか?エンベロープ暗号化を使用して、彼は運命づけられています。何らかの方法で暗号化されていない中間キー(または独自のキーで暗号化されている)を保存し、セキュリティチェーン全体を壊さない限り、それを回復する方法はありません。
はい、わかります。そして、私の説明は最高ではありませんでした。実装には多くの落とし穴がありますが、安全な方法です。 IBMのEnvelope Encryption実装を Google Cloud から、 [〜#〜] aws [〜#〜] から、などのように読んでください。
そして上司に、適切な経験なしに医療データを管理する安全なサービスを開発することは、将来の大きな問題を求めていることを知らせてください。