暗号化はセキュリティのトピックとしてよく取り上げられますが、プライバシーの面でも重要です。暗号化の目的は、暗号化された情報を他人が読み取れないようにすることですが、他人が自分の情報を読み取れないようにすることは、情報のプライバシーを保護する方法の 1 つです。ユーザー自身が行える操作は多くの場合制限されますが、利用するサービスのプロバイダとしてサポートを得ることで、暗号化によってユーザーのデータを維持できます。
ユーザーのプライバシーを支援するために暗号化を適用する方法としては、転送中の暗号化、保存時の暗号化、エンドツーエンドの暗号化という 3 つの関連方法があります。
- 転送データの暗号化とは、ユーザーとサイト間でデータを暗号化し続けることです。つまり HTTPS です。すでにサイトに HTTPS を設定しているかもしれませんが、サイトに転送されるデータはすべて暗号化されているとお考えですか?これがリダイレクトと HSTS の目的です。これらについては後述しますが、HTTPS 設定に含める必要があります。
- 保存データの暗号化は、サーバーに保存されているデータの暗号化です。これによりデータ侵害から保護でき、セキュリティ体制の重要な部分を占めます。
- エンドツーエンドの暗号化: クライアント上のデータがサーバーに到達する前に暗号化されます。これにより、デベロッパーからもユーザーデータが保護されます。ユーザーのデータを保存することはできますが、読み取ることはできません。このように実装するのは困難であり、すべての種類のアプリケーションに適しているわけではありませんが、自分のデータを見ることができるユーザーは本人以外であるため、ユーザーのプライバシーを保護する強力な手段になります。
HTTPS
まず、HTTPS 経由でウェブサービスを提供します。これはすでに完了している可能性が高いですが、そうでない場合は重要なステップです。HTTPS とは HTTP です。HTTP とは、ブラウザがサーバーにウェブページをリクエストするために使用するプロトコルですが、暗号化には SSL が使用されています。つまり、送信者(ユーザー)と受信者(自分)の間の HTTPS リクエストは、暗号化されているため、外部の攻撃者が読み取ったり、読み取ったり変更したりすることはできません。これは転送中の暗号化です データがユーザーからユーザーへ転送される間また、転送中の HTTPS 暗号化は、ユーザーの ISP やユーザーが使用している Wi-Fi のプロバイダが、ユーザーのサービスとの関係の一環としてユーザーに送信しているデータを読み取ることができなくなります。サービスの機能にも影響する可能性があります。既存の JavaScript API の多くの使用では、ウェブサイトを HTTPS 経由で提供する必要があります。MDN にはより包括的なリストがありますが、安全なコンテキストの背後にある API には、Service Worker、プッシュ通知、ウェブ共有とウェブ暗号化、一部のデバイス API などがあります。
HTTPS 経由でウェブサイトを提供するには、SSL 証明書が必要です。これらは Let's Encrypt を使用して無料で作成できます。また、ホスティング サービスを使用している場合は多くの場合、ホスティング サービスから提供されます。ウェブサービスに「プロキシ」し、HTTPS、キャッシュ、CDN サービスを提供できるサードパーティ サービスを使用することもできます。Cloudflare や Fastly など、このようなサービスの例は多数ありますが、どのサービスを使用するかは、現在のインフラストラクチャによって異なります。これまで HTTPS は、実装が面倒で高額になることがありました。そのため、支払いページや特に安全なオリジンでのみ使用する傾向がありましたが、無料で利用可能な証明書、標準の改善、ブラウザの普及により、これらの障害はすべて取り除かれました。
推奨事項
- いずれの場合も、サーバーで HTTPS を有効にします。
- Cloudflare などのサーバーの前にプロキシを使用することを検討してください(このプロセスの説明は httpsiseasy.com/ にあります)。
- Let's Encrypt では、独自の Let's Encrypt SSL 証明書を作成する手順を確認できます。
- または、OpenSSL を直接使用して独自の証明書を作成し、任意の認証局(CA)で署名します(これを行う方法については、HTTPS を有効にするをご覧ください)。
どちらのアプローチを選択するかは、ビジネス上のトレードオフによって異なります。サードパーティに SSL 接続の管理を任せるのが、最も簡単に設定できるだけでなく、ロード バランシング、キャッシュ保存、分析などのメリットもあります。ただし、なんらかの制御をそのサードパーティに明らかに譲り渡すことや、サードパーティのサービスへの避けられない依存関係も伴います(使用するサービスやトラフィック レベルによっては支払いが発生する可能性もあります)。
証明書の生成と CA による署名は、これまで SSL プロセスの実行方法でしたが、Let's Encrypt がプロバイダでサポートされている場合や、サーバーチームがそれに熟練しており、無料で利用できれば、Let's Encrypt を使用するほうが簡単です。また、クラウド ホスティングよりも上位のレベルでなんらかのサービスを使用している場合は、プロバイダが SSL をサービスとして提供することもよく見られるため、確認することが重要です。
理由
セキュリティはプライバシーの一部でもあります。干渉からユーザーデータが保護されていることを示せば、信頼関係を築くことができます。HTTPS を使用していない場合、サイトはブラウザによって「保護されていない」と報告されます(以前から存在しています)。 多くの場合、既存の JavaScript API は HTTPS ページ(「安全なオリジン」)でのみ使用できます。 また、インターネット利用が ISP に見られることからユーザーを保護します。 これがベスト プラクティスであることは間違いありません。現時点でウェブサイトで HTTPS を使用しないほうがよい理由はほとんど、またはまったくありません。
ブラウザで HTTP(保護されていない)ページが表示される仕組み
HTTPS にリダイレクトする
サイトが http: と https: の両方の URL でアクセスできる場合は、http: の URL アクセスをすべて https にリダイレクトしてください。これは上記の理由でもあります。また、サイトへのアクセスが増えても whynohttps.com にサイトが表示されないようにできます。その方法は、インフラストラクチャによって大きく異なります。AWS でホストされている場合は、クラシックまたはアプリケーション ロードバランサを使用できます。Google Cloud も同様です。Azure では Front Door を作成し、Node では Express で request.secure を確認します。Nginx ではすべてのポート 80 をキャッチして 301 を返します。Apache では RewriteRule を使用します。ホスティング サービスを使用している場合は、多くの場合、Netlify、Firebase、GitHub Pages などが、HTTPS URL へのリダイレクトを自動的に処理します。
HSTS
HSTS は「HTTP Strict-Transport-Security」の略で、サービスに対して HTTPS を使用するようブラウザをロックする方法です。HTTPS への移行に問題がない場合、またはすでに移行が完了している場合は、送信レスポンスに Strict-Transport-Security HTTP レスポンス ヘッダーを追加できます。以前にサイトにアクセスしたブラウザは、このヘッダーを表示したことを記録し、それ以降は、HTTP をリクエストしても、自動的に HTTPS としてこのサイトにアクセスします。これにより、上記のようなリダイレクトを回避できます。これは、ブラウザが HTTPS を使用するようにサービスに対するすべてのリクエストをサイレント モードで「アップグレード」するようなものです。
同様に、Upgrade-Insecure-Requests ヘッダーをページとともに配信することもできます。これは Strict-Transport-Security
とは異なりますが、関連しています。Upgrade-Insecure-Requests: 1
を追加すると、このページから他のリソース(イメージ、スクリプト)へのリクエストは、リンクが http であっても https としてリクエストされます。ただし、ブラウザはページ自体を https として再リクエストせず、ブラウザは次回にそのことを記憶しません。実際には、Upgrade-Insecure-Requests は、多数のリンクがある既存のサイトを HTTPS に変換する場合に便利です。コンテンツ内のリンク URL を変換するのは困難ですが、可能な場合はコンテンツを変更したほうがよいでしょう。
HSTS は主にセキュリティ機能です。つまり、以前アクセスしたことのあるユーザーのためにサイトを HTTPS に「ロック」します。ただし、前述のように、HTTPS はプライバシーに適しており、HSTS は HTTPS に適しています。同様に、すべてのコンテンツを更新する場合、Upgrade-Insecure-Requests は実際には必要ありませんが、サイトを常に HTTPS にするために多層防御を追加できる便利な「一帯一路」のアプローチです。
推奨事項
送信レスポンスに HSTS ヘッダーを追加します。
Strict-Transport-Security: max-age=300; includeSubDomains
max-age パラメータは、ブラウザが HTTPS のアップグレードを記憶して適用する期間を秒単位で指定します。(ここでは 300 秒、つまり 5 分に設定しています)。最終的には 6,3072,000(2 年)にすることが望まれます。これは hstspreload.org が推奨する数値ですが、問題が発生した場合に回復することは非常に困難です。そのため、最初は小さい数値(300)を設定し、エラーが発生していないことを確認してテストしてから、段階的に数値を増やすことをおすすめします。
送信レスポンスに Upgrade-Insecure-Requests
ヘッダーを追加します。
Upgrade-Insecure-Requests: 1
Content-Security-Policy: upgrade-insecure-requests
エンドツーエンドの暗号化
ユーザーデータのプライバシーを保護するには、ユーザー(ご自身を含む)以外に開示しないことをおすすめします。これは信頼関係において大いに役立ちます。つまり、ユーザーのデータがなければ、ユーザーが望まない操作はできないことは明らかです。そのための 1 つの方法は、すべてをクライアントサイドで保存することで、ユーザーデータがデバイスから一切出ないようにすることです。このアプローチは機能しますが、純粋なクライアントサイド アプリケーションには制限があります。ブラウザのデータ ストレージのサイズに制限があり、ブラウザによっては、ほとんどまたはまったく警告なしでクリアされる可能性があることです。また、ノートパソコンとスマートフォンなど、2 つのデバイスからデータにアクセスすることも困難または不可能です。このため、通常どおりサーバーにデータを送信しながら、ユーザーだけが知っている鍵でデータを暗号化し、サーバーがデータにアクセスできない(復号できないため)保存できるようにしておくと便利です。
仕組み
このアプローチは「エンドツーエンドの暗号化」または「e2e」と呼ばれるメッセージング アプリケーションで頻繁に使用されます。このようにして、互いの鍵を知っている 2 人のユーザーがメッセージを相互に暗号化および復号し、メッセージング プロバイダを介してメッセージを送信できますが、メッセージング プロバイダ(これらの鍵を持たない)はメッセージを読むことはできません。ほとんどのアプリケーションはメッセージ アプリではありませんが、クライアントサイドのみのデータストアと、クライアントが認識している鍵によるデータの暗号化という 2 つの方法を組み合わせることで、データをローカルに保存しながら、暗号化してサーバーに送信することもできます。このアプローチには限界があることを認識することが重要です。これは、すべてのサービスで利用できるわけではなく、特に、サービス プロバイダがユーザーが保存しているものにアクセスする必要がある場合には使用できません。このシリーズのパート 2 で説明したように、データの最小化の原則に従うことをおすすめします。可能な限りデータの収集は行わないでください。ユーザーにデータ ストレージが必要だが、サービス提供のためにそのデータにアクセスする必要がない場合は、エンドツーエンドの暗号化が有効な代替手段です。サービスを提供する際にユーザーが保存するものを確認する必要があるサービスを提供している場合、エンドツーエンドの暗号化は適切ではありません。そうしない場合は、ウェブサービスのクライアント側 JavaScript で、サーバーに送信するデータを暗号化し、受信するデータを復号できます。
例: Excalidraw
Excalidraw では、この点と方法について説明しています。これは、サーバー上に描画を保存するベクター描画アプリであり、ランダムに選択された鍵で暗号化されます。比較的少ないコードでこのエンドツーエンドの暗号化を Excalidraw が実装できる理由の一つは、window.crypto を使用して暗号ライブラリがブラウザに組み込まれたことです。これは 最新のすべてのブラウザでサポートされている一連の JavaScript API です。暗号化は難しく アルゴリズムの実装には
多くのエッジケースが伴いますブラウザに面倒な処理を任せることで、ウェブ デベロッパーは暗号化を利用しやすくなり、暗号化されたデータによるプライバシーの実装が容易になります。Excalidraw が執筆した記事で述べているように、暗号鍵は URL フラグメントの一部であるため、クライアントサイドに残ります。ブラウザが URL https://example.com/path?param=1#fraghere
にアクセスすると、URL のパス(/path
)とパラメータ(param=1
)はサーバー(example.com
)に渡されますが、フラグメント(fraghere
)は渡されず、サーバーには認識されません。つまり、暗号化されたデータがサーバーを通過しても、暗号鍵は送信されず、データがエンドツーエンドで暗号化されるため、プライバシーが維持されます。
制限事項
ユーザーデータの暗号化に対するこのアプローチは確実ではありません。ユーザーの信頼を高めるには役立ちますが、完全にはそれに置き換わるものではありません。ユーザーは、依然として、クライアントサイドの JavaScript を、不可逆的にデータを暗号化しないよく似た JavaScript に入れ替える可能性があるため、引き続きサービスを信頼する必要があります。ただし、ユーザーが使用しているウェブサイトがそれを行っているかどうかをユーザーが検出することは可能ですが、プロバイダが意図的に暗号化を行っていないことを実証することで、サービス プロバイダが意図的に暗号化を行っていないことを実証することはできません。
また、エンドツーエンドの暗号化の目標の一つは、サイト所有者がデータを読み取れないようにすることです。これはプライバシーの保護には役立ちますが、問題があった場合にサポートできないことも意味します。基本的に、エンドツーエンドの暗号化を使用するサービスでは、ユーザーが暗号鍵を管理します。(これは明白でも明白でもないかもしれませんが、誰かが鍵を持っている必要があります。データの機密性が保たれているのはあなたではありません)。これらの鍵を紛失した場合、対処すべきことはありません。また、それらの鍵で暗号化されたデータも失われる可能性があります。ここで、プライバシーとユーザビリティのバランスを適切に取ることが重要となります。暗号化を使用するすべての人にデータを非公開に保つと同時に、独自の鍵を安全に管理する暗号学の専門家に頼らなくても済むようにします。
保存データの暗号化
ユーザーの転送データを暗号化するだけでなく、サーバーに保存されているデータの暗号化も検討することが重要です。 これにより、保存データへの不正アクセスを取得した人のデータが暗号化され、復号鍵がないことが望ましいため、データ侵害からの保護に役立ちます。保存データの暗号化には、2 つの異なる補完的なアプローチがあります。1 つはユーザーが追加する暗号化で、もう 1 つはクラウド ストレージ プロバイダが追加する暗号化です(クラウド ストレージ プロバイダを使用している場合)。ストレージ プロバイダの暗号化では、ソフトウェアを介したデータ侵害に対する保護はあまり提供されません(通常、ストレージ プロバイダの暗号化は、そのサービスのユーザーが透過的であるためです)。ただし、プロバイダのインフラストラクチャで発生する侵害に対しては有用です。簡単に有効にできることが多いため、検討する価値があります。このフィールドは頻繁に変更されるため、セキュリティ チーム(またはセキュリティに精通したエンジニア)にアドバイスすることをおすすめしますが、すべてのクラウド ストレージ プロバイダは、デフォルトで Azure Storage と Google Cloud Storage を設定することで、ブロック ストレージの Amazon S3 と、データベース データ ストレージの AWS RDS、Azure SQL、Google Cloud SQL に対して保存データの暗号化を提供しています。{/11クラウドストレージを使用している場合は プロバイダに問い合わせてくださいユーザーデータをデータ侵害から保護するために保存データの暗号化を自身で処理することはさらに困難です。暗号鍵を安全に管理し、攻撃者にも利用できるようにすることなく、コードで使用できるようにするロジスティクスは困難だからです。このページは、そのレベルのセキュリティ問題に関するアドバイスには適していません。セキュリティに精通したエンジニアや専任チームに相談するか、外部のセキュリティ機関に相談してください。