本文へスキップ本文へスキップ
Web開発

予約フォームの個人データ、暗号化すれば安全?Supabase保存で見直したセキュリティ設計

予約フォームの個人データ、暗号化すれば安全?Supabase保存で見直したセキュリティ設計
目次

予約フォームの個人データ、暗号化すれば安全?Supabase保存で見直したセキュリティ設計

Webで予約フォームを作ると、名前や連絡先など、扱いに気を使うデータが増えます。

自分も予約機能を作る中で、

「そのままDBに保存するのは怖い。暗号化して保存しておけば安心だろう」

と考えました。

そこでSupabaseへ保存するデータを暗号化する構成にしました。

ただ、調べていくと少し話が変わってきます。

暗号化してある = 安全

ではありませんでした。

暗号方式が適切でも、鍵が同じ場所に置いてあったらどうするのか。 そもそも読める必要がない人までDBへアクセスできたらどうするのか。 復号できる処理を誰でも呼べたらどうするのか。

暗号化は大事です。

でも、個人データを守る設計は、暗号化だけで完結しません。

今回は、予約フォームのデータ保存を考え直したことをきっかけに、

「個人情報をDBへ保存するとき、何を考えればいいのか」

を整理します。

具体的な案件名やサイト名、実際の暗号鍵・内部構成は出しません。 また、現在は公開前の実装なので、本番運用済みの仕組みとして紹介する記事でもありません。


情報漏えいは「大企業だけの話」ではない

セキュリティの話は、どうしても大げさに聞こえます。

でも個人データを扱うなら、少なくとも「漏れたら困る」という前提では考えておいた方がいいです。

個人情報保護委員会の令和7年度年次報告では、個人データの漏えい等について、個人情報保護法に基づく報告を17,139件処理したとされています。

参考: https://www.ppc.go.jp/aboutus/report/annual_report_2025/⁠(外部サイト)

IPAの「情報セキュリティ10大脅威 2026」でも、個人向けの脅威として「インターネット上のサービスからの個人情報の窃取」が挙げられています。

参考: https://www.ipa.go.jp/security/10threats/10threats2026.html⁠(外部サイト)

もちろん、

予約フォームを作ったらすぐ攻撃される

という話ではありません。

ただ、名前、電話番号、メールアドレス、予約内容のような情報を保存するなら、

「とりあえずDBに入れておく」より、一段考えておく価値はある

と思います。


最初に考えたのは「DBへ入れる前に暗号化する」

自分が最初に考えたのは単純でした。

アプリ側でデータを暗号化する。

その暗号化済みデータをSupabaseへ保存する。

必要になったときだけ復号する。

DBを直接見ても、人がそのまま読める文字列ではない。

これならかなり安心に見えます。

実際、暗号化は重要な対策です。

OWASPのCryptographic Storage Cheat Sheetでも、保存データを守る方法として、アプリケーション層・データベース層・ファイルシステム層など、複数の場所で暗号化を行えることが説明されています。

参考: https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html⁠(外部サイト)

ただし、ここで一つ大きな疑問が出ました。

暗号化したデータと、その暗号を解く鍵を同じところに置いたらどうなる?

ドアに鍵を付けても、鍵をドアノブにぶら下げていたら意味が薄い。

かなり雑な例えですが、考え方としてはこれに近いです。

予約フォームの個人データ、暗号化すれば安全?Supabase保存で見直したセキュリティ設計

暗号化の強さより先に「鍵をどう扱うか」が重要だった

暗号化というと、

  • AES-256なら強い

  • 何bitなら安全

  • このライブラリなら安心

みたいな話に目が行きがちです。

もちろん方式の選択は重要です。

OWASPでは、保存データを対称鍵暗号で保護する場合、AESを安全なモードで使用することなどを推奨しています。

ただ、それと同じくらい繰り返し出てくるのが鍵管理です。

暗号化されたデータがあっても、

鍵を取られたら復号できます。

だから考えることは、

  • 鍵をどこに保存するか

  • ソースコードへ直書きしていないか

  • Gitへ入っていないか

  • 誰が鍵へアクセスできるか

  • 漏えい時に鍵を交換できるか

  • 古い鍵をどう扱うか

  • 暗号化データと鍵を分離できているか

まで広がります。

OWASPも、可能であれば暗号鍵は暗号化対象データとは別の場所へ保存することを推奨しています。

参考: https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html⁠(外部サイト)

つまり、

暗号化したから終わりではなく、鍵まで含めて初めて暗号化設計

ということです。

ここは自分が最初に考えていたより、かなり重要でした。


「暗号化」と「アクセス制御」は別物

もう一つ、整理しておきたいのがここです。

データが暗号化されていても、

誰でもその行を取得できる状態

なら、それは別の問題です。

たとえば、

  • 本人だけ見られる

  • 管理者だけ見られる

  • 書き込みだけできて読み取りはできない

  • 特定のサーバー処理からしか触れない

といった制御は、暗号化とは別に必要です。

SupabaseではPostgreSQLのRow Level Security、いわゆるRLSを使って、行単位でアクセスルールを設定できます。

Supabase公式Docsでは、ブラウザからアクセス可能な公開スキーマのテーブルではRLSを有効にするよう説明されています。

参考: https://supabase.com/docs/guides/database/postgres/row-level-security⁠(外部サイト)

たとえば、

自分のデータだけSELECTできる

というルールをDB側へ持たせることができます。

つまり、

暗号化 = 中身を読みにくくする
RLS・権限 = そもそも誰がデータへ触れるかを制限する

です。

どちらか片方ではなく、役割が違います。


Supabaseを使っているから自動的に安全、でもない

Supabaseにはセキュリティに関する仕組みがいくつもあります。

RLSだけでなく、秘密情報を管理するVaultもあります。

Supabase Vaultでは、secretを認証付き暗号化した状態でディスクへ保存し、暗号鍵は暗号化データと同じDB内には保存しない仕組みになっています。

参考: https://supabase.com/docs/guides/database/vault⁠(外部サイト)

これはかなり参考になる考え方です。

ただし、

Supabaseを使えば、保存したデータは全部勝手に安全になる

という意味ではありません。

RLSのpolicyをどう作るか。

service roleのような強い権限をどこで使うか。

フロントから直接触らせていい範囲はどこまでか。

復号処理はどこで実行するか。

アプリケーション側の設計は自分で決める必要があります。

サービスのセキュリティ機能と、自分のアプリのセキュリティ設計は別です。


「より強い暗号化」にするなら、方式だけを強くすればいいわけではない

今回、自分も最初は、

じゃあ、もっと強い暗号化にすればいいのか?

と考えました。

でも正確には、見るべき範囲を広げた方がいいです。

たとえば、単純にデータを暗号化するだけでなく、

暗号化したデータが改ざんされていないか確認できる仕組み

まで含めた「認証付き暗号」という考え方があります。

Supabase VaultもAuthenticated Encryptionを使っています。

OWASPでも、安全な暗号モードを選び、暗号化だけでなく完全性を考えることが推奨されています。

ただし、ここでこの記事に、

自分はAES-GCMでこう実装しました

のようなことは書きません。

現在の実装で実際に使用している暗号方式について、この記事のためにコード確認まで行っていないからです。

ここを勝手に補完すると、セキュリティ記事として一番やってはいけないことになります。

言えるのは、

「暗号化して保存する」から、「暗号方式・改ざん検知・鍵管理まで含めて考える」に認識が変わった

というところまでです。


保存する情報自体を減らせないかも考える

セキュリティを調べていて、もう一つ大事だと思ったのがこれです。

そもそも、そのデータを保存する必要はあるのか。

OWASPも、機密性の高い情報を守る最も良い方法の一つとして、不要な情報を保存しないことを挙げています。

たとえば予約システムなら、

  • 本当に住所まで必要なのか

  • 予約完了後もずっと残す必要があるのか

  • 管理画面へすべて表示する必要があるのか

  • ログへ個人情報を残していないか

  • バックアップにいつまで残るのか

なども考えられます。

強力な暗号化を追加する前に、

持たなくていいデータを持たない

方が強い場合もあります。

これは実装も減ります。

そして、漏えいしたときの影響も減らせます。


予約データを守るなら「何重かに分けて考える」のが分かりやすい

今回調べた内容を、自分の中では次のように整理しています。

1. 通信中を守る

HTTPS/TLSで、ブラウザからサーバーへ送る途中のデータを保護する。

2. 保存データを守る

必要な個人データについて、適切な暗号化を検討する。

3. 鍵を守る

暗号鍵をソースコードやDBと安易に同居させず、アクセス範囲やローテーションも考える。

4. DBへのアクセスを絞る

SupabaseならRLSやPostgresの権限を使って、読める人・書ける人を限定する。

5. 復号できる場所を絞る

「DBを読める人 = 平文を読める人」にならないよう、どこで復号するかを考える。

6. そもそも保存量を減らす

不要な個人データは持たない。保持期間も考える。

予約フォームの個人データ、暗号化すれば安全?Supabase保存で見直したセキュリティ設計

このくらいに分けると、

暗号化したから大丈夫

という一つの対策に依存しなくなります。

セキュリティでよく言われる多層防御に近い考え方です。


AIに聞いて終わりではなく、公式情報まで確認する必要がある

今回のきっかけ自体は、

「これ暗号化しているから大丈夫だよね?」

とAIへ相談したことでした。

そこで、

鍵管理まで考えた方がいい

という話が出てきたことで、さらに調べるきっかけになりました。

これはAIのかなり便利な使い方だと思っています。

ただ、セキュリティは、

AIがそう言ったから採用する

では怖い分野です。

暗号方式。 ライブラリ。 権限。 クラウドサービスの仕様。

この辺は更新もあります。

最終的には、

  • Supabase公式Docs

  • OWASP

  • 使用している暗号ライブラリの公式Docs

  • 必要に応じてNISTなどの標準

まで確認する必要があります。

AIは「そこ危なくない?」を見つけるレビュー役として使い、そのあと一次情報へ戻る。

今のところ、この使い方が一番しっくりきています。


暗号化は「最後の安心ボタン」ではなく、一つの層だった

最初は、

個人データを暗号化してSupabaseに保存しておけば安心

くらいに考えていました。

でも調べていくと、

暗号化方式
→ 鍵管理
→ RLS・権限
→ 復号できる場所
→ 保存するデータ量
→ ログやバックアップ

までつながってきます。

これを全部完璧にしないと何も作れない、という話ではありません。

ただ、個人情報を扱う機能なら、

「暗号化した?」ではなく、「もし一つ破られたら、その次に何が守ってくれる?」

と考える方が分かりやすいと思います。

自分も今回、暗号化を一つ追加して終わりにするのではなく、保存方法全体を見るようになりました。

今後この実装を公開まで持っていくときも、具体的な暗号方式や鍵管理、RLS、ログ、バックアップまで含めて、改めて確認してから本番へ出すつもりです。

過去の記事から 1 本

全 14 本のうち 1 本目の記事

about

このブログについて

Web 開発・インフラ・AI を手を動かして試した記録が中心です。うまくいった話もハマった話も、仕事や日々のこともそのまま書きます。