質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

4回答

7197閲覧

DB検索性の高い暗号化処理について(復号化の必要なし)

sakamata

総合スコア203

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

1グッド

3クリップ

投稿2018/11/24 07:48

編集2018/11/24 09:07

Laravel5.6
mysql Ver 15.1 Distrib 5.5.56-MariaDB (本番環境)
mysql Ver 14.14 Distrib 5.7.22, (開発環境)

でアプリケーションを制作しています。

DBに個人を特定する値が入っています。ぶっちゃけると MACAddressなのですが
毎回、500件程にwhereで絞り込んだ後に、およそ100件程のMACAddressの付き合わせ検索を連続で頻繁に行う必要があります。
具体的には外部からhttpsでPOSTされて来る100件程の生のMACAddressの値と、DBの値を比較する処理をしています。

これまでDBにはMACAddressが生データで入力されており、完全一致で検索をかけていましたが、
これをhash化して管理したいと考えています。

そこで検索性が高く、いざというとき(DBデータ盗まれた等)複号化されにくい暗号化の方法としてどのようなものを使うのがふさわしいでしょうか?

まとめると以下の様な条件になります。

・DB検索に時間がかからなければ良い。
・システムとして値の複号化は必須要件ではない。(つまりopenSSL等で複号化をしないでも良い)
・DBの方では一意性が保証できる値となっていれば良い。
・DBの情報が漏洩した際、復元されにくいものが良い。
・md5,sha1 は計算力を使えば複号されるので不採用。
・Laravelファサードの Hash:check() はかなりの処理時間がかかるので不採用。

また、このような要求にこたえられるような暗号化の記述がされたサイト等あれば、
それのみでもご紹介いただけると幸いです。

Jota-Shimazaki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanat

2018/11/24 09:16

インターネット上に公開されているサービスでの話という前提で問題ありませんか?
sakamata

2018/11/24 09:17

はい、そうなります。
guest

回答4

0

・md5,sha1 は計算力を使えば複号されるので不採用。

という前提であれば、SHA-256でも大差はないと考えられます。MD5やSHAシリーズは、ハッシュ値の計算に高速性が求められる要件(たとえばDVDイメージのハッシュ値を求める等)に適したもので、総当たり耐性は弱いです。te2jiさんの指摘のように、MAC Addressは48ビットしかないですし、ベンダー固有の値もあるので、総当たり攻撃はやりやすい条件です。

ということで、パスワードの保存と同じように、ソルトとストレッチングを施したらどうでしょうか?パスワードの保存とは要件が異なるので、レコード毎に異なるソルトをつけることはできませんが、固定のソルトで、かつできるだけソルトを秘匿すれば、元のマックアドレスが知られるリスクを減じることができます。

PHPで実装する場合、password_hashも使えなくはなかったのですが、PHP 7.0でソルトを外部から指定することが非推奨になりましたので、crypt()関数を使うのがよいでしょう。以下は、Blowfishという総当たり攻撃に強いアルゴリズムを使った実装例です。

$mac_key = crypt($mac_address, '$2y$10$ABCDEFGHIJKLMNOPQRSTUV$');

ここで、$10$ のところはストレッチングの回数のパラメータ(回数そのものではない)ですので、実行時間を見ながら調整してください。大きいほど強度は高くなりますが、実行時間はかかります。
ABCDEFGHIJKLMNOPQRSTUVはソルトですので、ランダムな別の値にしたうえで、できるだけ外部に漏れにくい実装を工夫してください。万一ソルトが漏れても、復号には総当たりをするしかないので、それほど神経質になる必要はないと思います。
crypt()関数はバイナリセーフでないので、マックアドレスは16進数など、NULLバイトが入らないようにしてください。

投稿2018/11/24 11:24

編集2018/11/24 12:40
ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakamata

2018/11/24 12:23

詳細な回答ありがとうございます。ソルトというものを初めて知りました。 これまで DBに暗号化したい値を入れる際は 対象の文字列に対し、環境変数に書いたランダムな値を結合する、等の方法で暗号化/復号化/hashチェック等を行ってしましたが、きちんとした名前や作法(?)があった訳ですね。 また`$10$`で強度を調整できることも初めて知りました。こちらもパフォーマンスをみつつ調整します。 確かにMACAddressは解析されやすそうです。御指南いただいた方法で試してみたいと思います。 また、とても心強い方からのアドバイスで嬉しさひとしおです。ありがとうございました。
guest

0

ベストアンサー

SHA-1の強度で許容されないのであればSHA-256が最有力になるのではないでしょうか。

・DB検索に時間がかからなければ良い。

については、インデックスが適切に貼られていれば問題無いでしょう。
(もしSHA-256処理によるCPU負荷が問題になるのであれば、HW性能と要件が釣り合っていないのでどちらかを変える必要がある)

(前提をひっくり返すことになりますが)
インターネット経由の通信で取得されるMACアドレスは個人や端末を特定できるものでは無い(最も個人に近い箇所でもプロバイダのルータのMACアドレスになるはず)ので、セッションIDを使ったり、cookieでクライアントを特定できるトークンを発行してそちらで特定する方が良い様に思います。

投稿2018/11/24 09:48

tanat

総合スコア18709

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakamata

2018/11/24 10:06

回答ありがとうございます。SHA-256ですと64文字の乱数に変換ということですね。 検索性はアドバイスいただいた通り、DBに対して正しくインデックスを張るという事で解決しようと思います。 また、MACアドレスについてのご指摘もありがとうございます。これはwi-fiルーター等のローカルネットワークに接続された端末のMACAddressを取得しております。つまり個人のPCやスマホ等の端末固有のものなので、ある程度の一意制が確保されています。 とはいえ、端末によっては値を変えたり出来てしまうものだそうで、DBには一意の値としては信用しないで管理するのを前提にして設計しております。 アプリ仕様の説明を省いてしまいますが。結論としては SHA-256 でhash化してDBでMACAddressを管理、POSTされたMACAddressを複合インデックスを張ったtable値と比較して検索性を上げる。 という道筋が見えてきました。 アドバイスありがとうございます!
guest

0

・DBの情報が漏洩した際、復元されにくいものが良い。

MACAddress って組み合わせが決まってるから、総当たりでもそこそこ簡単に解析できちゃうんじゃないかなぁ。。。
stretching は必須な気がする。

投稿2018/11/24 11:10

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakamata

2018/11/24 12:27

stretching という事は、別の解析されにくい文字列等をつなげてた状態でhash化する。ということでしょうかね。確かに短くて法則性のある文字列なので、解析されやすいかもしれませんね。なので、ockeghem様のアドバイスにもありました通りソルトを付けて対応しようかと思います。アドバイスありがとうございました。
退会済みユーザー

退会済みユーザー

2018/11/24 12:46

> stretching という事は、別の解析されにくい文字列等をつなげてた状態でhash化する。ということでしょうかね。 違います。検索すれば、サクッと出てくるので、確認してください。 あと、そもそもの MAC address の保存目的によっては適した手段ではないので、要件との突き合わせをし直すことをオススメします。
sakamata

2018/11/24 14:49

回答ありがとうございます。 stretching とはhash化した値に対してさらにhash化を繰り返し行わせる方法ということでしょうかね。これも未知の方法でした、認識を改めます。 https://www.slideshare.net/ockeghem/how-to-guard-your-password 偶然というか必然というか、検索して出てきたのは他の回答者の方の資料でした。 パスワードを解析されないようにするには向いているかもしれません、が、確かにご指摘通り今回の要件には少々不向きかもしれませんが、セキュリティに対するよい意識付けになりました。 ありがとうございます。
guest

0

皆さまの回答でhash化や暗号化、セキュリティに対する意識をいっそう強く持てる様になりました。
ひとまずWebサーバー側でアドバイスいただいた様に不可逆暗号化して、DBに値を入れる様に実装しましたがやはり暗号化する際のパフォーマンス低下が気になります。そこで、外部から生のMACAddressをPOSTさせて暗号化させるより、その外部自体で先に暗号化をさせてからPOSTをさせた方が、圧倒的にパフォーマンスが出ることが明らかなので、以下のページなどを参考に今回のアドバイスを生かした暗号化をローカル環境のデバイスの方に施そうと思います。

https://ten-snapon.com/archives/1399
回答ありがとうございました。

投稿2018/11/25 07:22

sakamata

総合スコア203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/11/25 08:19 編集

MAC address そのものである意味はなく、一意な識別子として使用したいということであれば、MAC address にこだわらず、適当な token で良いと思います。 あと、暗号化やハッシュ値への変換を行うレイヤーも色々処理が可能な箇所があります。 以前に質問をいた時に、有用な回答を頂いておりますので参考になれば https://teratail.com/questions/43815
ockeghem

2018/11/25 08:42

クライアント側でハッシュ計算する場合は、ソルトを完全に秘匿することが難しい(リバースエンジニアリングに弱い)ことは考慮されたほうがよいと思います。
sakamata

2018/11/25 08:53

>te2ji 様 ありがとうございます。読み始めました。大変興味深いです。 何を隠すべきか、どこまで安全性を担保すべきか?まで考えてから改めて方策を練りたいと思います。 >ockeghem 様 ありがとうございます。確かにそうですね。この辺は完全な対策ではありませんが、クライアント毎にソルトを変えて対応しようと考えています。全く別レイヤーの話ですとクライアント側での物理的な盗難なども考える必要があるのですが、その際の被害も最小限に抑える工夫などもすべきですね。
sakamata

2018/11/25 08:59

良く考えたらクライアント側には一切MACAddressの情報が残らないので大きなリスクは無いかもです。ただ、暗号化の方法は解析されるので、その上でWebサーバー側の情報を握られるとより解析されやすくなり、少し怖くもありますが、最悪単一のクライアントの情報が解析される程度にとどまるのかもと、現状では推察しています。
ockeghem

2018/11/25 11:20

クライアント毎にソルトを変えたら、検索が難しくなる気がしますが、大丈夫ですか?
sakamata

2018/11/25 13:46 編集

お気遣いありがとうございます。 システムの仕様上おそらく大丈夫と思われます。 たとえクライアントAと、クライアントBにそれぞれ同じMACAddressの端末が接続しても、別の端末として扱う事を想定してますので、むしろ異なるソルトで異なるhashになった方がシステム上都合が良いと判断しています。
ockeghem

2018/11/25 14:37

Macアドレスを検索する際に、Macアドレスからハッシュ値を計算するしてハッシュ値をDB上で検索すると思うのですが、ハッシュ値を求めるにはソルトがわからないといけないので、どの端末か分からない前提ではソルトがわからず、総当たりするしかないと思ったのですが
sakamata

2018/11/25 15:16

クライアント側ではMACAddressを収集した時点で固定値のsoltを付けて `shasum -a 256` によってhash化することをを想定しています。したがって特定のMACAddressは毎回同じhash値を発行してからPOSTをすることを想定しています。 例えば以下の様なものです。 ``` hash=(`echo -n $mac$secret | shasum -a 256 | awk '{print $1}'`) ``` しかしこれはまずいでしょうか?生成されたhash値をPOSTした後一度DBに収めてしまえば、毎回クライアント側からは、その場に繋がっている端末の一意のhash値がPOSTされてくる為、その端末が存在するか否かがわかると認識しています。
sakamata

2018/11/25 15:27

あと、この処理にストレッチングもクライアント側のCPU負荷(RaspberryPi)と相談しつつ入れようと考えています。ストレッチングの数も毎回決め打ちであれば、同じhash値が生成されると把握しておりますが、私の認識に誤りはないでしょうか?
sakamata

2018/11/25 16:02

度々すみません。返信の際の最後におっしゃられている『総当たり』とはDBの全件検索という事でしょうか?それを前提とするのであれば、問題は無いと考えています。 MACAddressをPOSTする際に、どのクライアントからの情報であるかも付与してPOSTしているので、クライアントに存在する100件程のレコードに絞り込んだ状態での検索となります。
ockeghem

2018/11/25 21:32

ちょっと勘違いしていまして、「総当たり」は必要ないですね。失礼しました。 しかし、端末毎に固有のソルトをもつくらいであれば、te2jiさんが指摘されたように、端末毎に固有の値を記憶するほうがよいのではないでしょうか? UUIDがこの目的に適していると思います
sakamata

2018/11/26 05:47

いえいえ、私の説明が下手で誤解をさせてしまっているようです。すみません。 UUIDを初めて知りました。確かに固有IDを取得してMACAddressと紐づけするという方法も良いですね。 ただ、クライアント側のプログラムはなるべく簡単なもので、値等もなるべく保持しない事を前提にシステムを設計しています。実はクライアント側は arp-scan をかけてサーバーに定期的にPOSTしているのみの単純なshellスクリプトです。ここにMACAddressとUUIDとの紐づけをするとなると、クライアント側に情報を管理記憶させる処理が必要となりますのでそれは避けたいのです。 また、別の方法としてクライアント側でMACAddressを生でPOST、サーバー側でUUIDに変換して保存、という処理をしたとしても、POSTされる都度、サーバー側で毎回UUIDに変換してから(別の値が発行されてしまう?)値の検索をかける。という事で二度手間的な処理が発生しますので、これもあまり得策ではないかもしれません。 なので現状は クライアント側で arp-scan をかけ、 MACAddressを shasum 256 にソルトを付けてhash化してPOSTさせ、その値をサーバー側で保持するのが、最適と判断します。 色々と丁寧なアドバイスを本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問