予約フォームの個人データ、 暗号化すれば安全? 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(外部サイト)
ただし、ここで一つ大きな疑問が出ました。
暗号化したデータと、その暗号を解く鍵を同じところに置いたらどうなる?
ドアに鍵を付けても、鍵をドアノブにぶら下げていたら意味が薄い。
かなり雑な例えですが、考え方としてはこれに近いです。

暗号化の強さより先に「鍵をどう扱うか」が重要だった
暗号化というと、
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. そもそも保存量を減らす
不要な個人データは持たない。保持期間も考える。

このくらいに分けると、
暗号化したから大丈夫
という一つの対策に依存しなくなります。
セキュリティでよく言われる多層防御に近い考え方です。
AIに聞いて終わりではなく、公式情報まで確認する必要がある
今回のきっかけ自体は、
「これ暗号化しているから大丈夫だよね?」
とAIへ相談したことでした。
そこで、
鍵管理まで考えた方がいい
という話が出てきたことで、さらに調べるきっかけになりました。
これはAIのかなり便利な使い方だと思っています。
ただ、セキュリティは、
AIがそう言ったから採用する
では怖い分野です。
暗号方式。 ライブラリ。 権限。 クラウドサービスの仕様。
この辺は更新もあります。
最終的には、
Supabase公式Docs
OWASP
使用している暗号ライブラリの公式Docs
必要に応じてNISTなどの標準
まで確認する必要があります。
AIは「そこ危なくない?」を見つけるレビュー役として使い、そのあと一次情報へ戻る。
今のところ、この使い方が一番しっくりきています。
暗号化は「最後の安心ボタン」ではなく、一つの層だった
最初は、
個人データを暗号化してSupabaseに保存しておけば安心
くらいに考えていました。
でも調べていくと、
暗号化方式
→ 鍵管理
→ RLS・権限
→ 復号できる場所
→ 保存するデータ量
→ ログやバックアップ
までつながってきます。
これを全部完璧にしないと何も作れない、という話ではありません。
ただ、個人情報を扱う機能なら、
「暗号化した?」ではなく、「もし一つ破られたら、その次に何が守ってくれる?」
と考える方が分かりやすいと思います。
自分も今回、暗号化を一つ追加して終わりにするのではなく、保存方法全体を見るようになりました。
今後この実装を公開まで持っていくときも、具体的な暗号方式や鍵管理、RLS、ログ、バックアップまで含めて、改めて確認してから本番へ出すつもりです。



