暗号化フィールドでMySQLデータベースを検索する方法


15

私がする必要があるとし、特定のテーブルのフィールド暗号化MySQLのデータベースを。さらに、暗号化したフィールドの一部検索する必要があります。

とにかくこれらのフィールドをどのように検索しますか?

各レコードを段階的に復号化することはオプションではありません。数千のレコードが複数あるとします。各レコードを復号化し、各レコードが検索に一致するかどうかを確認するには、時間がかかりすぎます。

更新2012-09-07

新しいアプリケーションを実装しようとしているので、データベーススキーマにさらに詳細を追加しても構いません。さらに、現在稼働中のアプリケーションを拡張する必要があります。しかし、これらのアプリケーションの場合でも、詳細を追加しても問題ありません。

更新2012-09-08

暗号化はこの質問の核です。

一部の回答で提案されているアクセス制限はすでに適用されていますが、データを暗号化するための正式な要件に適合していません。

この正式な要件は Payment Card Industry Data Security Standard [PCI]ではありません

回答:


11

明らかにそれらは閲覧されることを意図したものではないため、それらを検索することには問題があります。

私が過去に使用した1つのトリックは、暗号化する前に暗号化されたデータをハッシュし、インデックス付き列にハッシュを保存することです。もちろん、これは値全体を検索する場合にのみ機能します。部分的な値には同じハッシュがありません。

必要に応じて、ハッシュの「フルテキスト」インデックスを作成することでおそらくこれを拡張できますが、本当に速く複雑になる可能性があります。

補遺

辞書攻撃に対する脆弱性についてのチャットでのかなり長い議論ごとに、回答に脚注を追加することが提案されているため、上記のアプローチに対するこの潜在的なセキュリティリスクについて説明します。

辞書攻撃:辞書攻撃は、誰かが既知の値のリストを事前にハッシュし、そのハッシュをデータベース内のハッシュされた列と比較することです。一致するものが見つかった場合、既知の値は実際にハッシュされているものである可能性があります(ただし、ハッシュは一意であることが保証されていないため、明確ではありません)。これは通常、ハッシュが辞書と一致しないようにランダムな「ソルト」を追加または追加して値をハッシュすることで軽減されますが、上記の答えは検索性を失うためソルトを使用できません。

この攻撃は、パスワードのようなものを扱う場合は危険です。一般的なパスワードハッシュの辞書を作成すると、そのハッシュ値をテーブルですばやく検索し、そのようなパスワードを持つユーザーを識別し、そのユーザーのIDを盗むために資格情報を効果的に抽出できます。

SSN、クレジットカード番号、GUIDなど、カーディナリティの高いアイテムの場合はそれほど危険ではありません(ただし、これらの保存に関連するさまざまなリスク[読み取り:法的]があるため、それらの保存についてアドバイスするつもりはありません。 )。

これは、辞書攻撃が機能するために、可能な値とそのハッシュの辞書を事前に作成しておく必要があるためです。理論的には、可能なすべてのSSNの辞書を作成できます(すべてのフォーマット順列が削除されたと仮定すると、10億行、クレジットカードの数十兆のエントリ)...しかし、それは通常辞書攻撃のポイントではありません基本的には、あらゆる値を体系的に調査するブルートフォース攻撃に匹敵します。

SSNを人に一致させようとしている場合は、特定の SSNまたはクレジットカード番号を検索することもできます。繰り返しますが、通常は辞書攻撃のポイントではありませんが、実行することは可能です。したがって、これが回避する必要があるリスクである場合、私の答えはあなたにとって良い解決策ではありません。

だからあなたはそれを持っています。暗号化されたすべてのデータと同様に、通常は何らかの理由で暗号化されているため、データとそれを保護しようとしているものに注意してください。



5

あなたは見て撮りたいかもしれCryptDBを。透過的なストレージと暗号化されたデータのクエリを可能にするMySQLとPostgreSQLのフロントエンドです。アプリケーションとデータベースの間を通過するデータを暗号化および復号化し、暗号化されたデータを操作するクエリを書き換えることで機能します。また、各列の暗号化モードを動的に調整して、アプリケーションが使用するクエリに必要な情報だけを公開します。

CryptDBで使用されるさまざまな暗号化方法には次のものがあります。

  • RND、完全にIND-CPAの安全な暗号化スキームであり、データに関する情報は漏えいせず(その存在と、可変長タイプの場合は長さを除く)、保存と検索のみを許可し、クエリは許可しません。

  • DET、決定性のあるRNDのバリアント。2つの同じ値(同じ列)が同じ暗号文に暗号化されます。フォームの等式クエリをサポートしますWHERE column = 'constant'

  • OPE、などの不等式クエリをサポートする順序保持暗号化スキームWHERE column > 'constant'

  • HOM、部分的に準同型の暗号化スキーム(Paillier)。暗号テキストを乗算することにより、暗号化された値を一緒に追加できます。SUM()クエリ、追加、インクリメントをサポートします。

  • SEARCH、形式のキーワード検索をサポートする計画WHERE column LIKE '% word %'

  • JOINおよびOPE-JOIN、異なる列の値を互いに比較できるようにするDETおよびOPEのバリアント。それぞれ等価結合と範囲結合をサポートします。

CryptDBの真の強みは、各列の暗号化方式を表示されるクエリに動的に適応させることです。そのため、低速または安全性の低いスキームは、それらを必要とする列にのみ使用されます。暗号化キーをユーザーパスワードにチェーンするなど、他にもさまざまな便利な機能があります。

興味のある方は、CryptDB Webサイトからリンクされた論文、特にPopa、Redfield、Zeldovich、Balakrishnanによる「CryptDB:暗号化クエリ処理による機密性の保護」をご覧になることをお勧めします(SOSP 2011)。また、これらのペーパーでは、さまざまな種類のクエリのサポートに伴うさまざまなセキュリティとパフォーマンスのトレードオフについても詳しく説明しています。


1
It works by encrypting and decrypting data as it passes between the application and the database:これは、検索対象のデータが既にデータベースにある場合(暗号化されている場合)に問題を引き起こす可能性がありますが、データベースを検索するクエリ自体はCryptDBに渡されるだけです(暗号化されますか?)。この方法がどのように効率的かを理解できませんか?
マーティン

3

なぜ現在の回答が要件を完全に疑問視していないのか理解できないので、質問として答えを残します。

ビジネス上の理由は何ですか?暗号化する必要があるデータとその理由は何ですか?PCIコンプライアンスをお探しなら、エッセイを書くことができます。

要件に関する質問:

  • 結果として存在する/存在しないを返す必要がありますか、それとも実際のデータを返す必要がありますか?
  • LIKE '%OMG_SEKRIT%'機能が必要ですか?
  • 誰がデータを見ることができず、なぜですか?

RDBMSセキュリティは通常、ユーザー/ロールによって実施される許可ベースで行われます。通常、データはディスク上のRDBMSによって暗号化されますが、データを効率的に保存および取得するように設計されたアプリケーションにとっては意味をなさないため、列データ自体では暗号化されません。

user / role / apiで制限します。ディスクで暗号化します。より重要なデータを保存している場合、MySQLを使用している理由を知りたいと思います。


主に、存在する/存在しないを見つけてから、特定のレコードを見つける必要があります。LIKEの完全なサポートは問題ありません。しかし、私は、単語のマッチング以上のものが可能になるのだろうかと思います。許可されたユーザーはデータを見ることができます。アプリはそれらのアイテムを解読し、正当なユーザーには表示する権利があります。許可ベーススキーマはオプションではありません。
-SteAp

「より重要なデータ」の基準は何ですか?
アルカニン

2

私はこれを調査していて、あなたの質問に出会いました。私は、論文「暗号化されたデータの検索のための実用的なテクニック」http://www.cs.berkeley.edu/~dawnsong/papers/se.pdfのセクション5.4で概説されているアプローチに傾いています。

基本的な要点は、暗号化された検索ドキュメントに存在する暗号化されたキーワードを含むインデックスを作成することです。秘Theは、これらのキーワードが存在するドキュメント(またはデータベース)内の場所も暗号化することです。


1

プログラム的に、効率的なソリューションは

  1. レコードIDで検索しているフィールドのみのすべてのレコードを取得します
  2. それらを一時テーブルに復号化する
  3. そのテーブルに対して検索を実行します
  4. IDを使用して、検索条件に一致する完全なレコード(すべてのフィールド)を取得します
  5. それらを解読してユーザーに返す

ポイントは、1と4は、最初にすべてのレコードのすべてのフィールドを取得および復号化するよりもはるかに小さいデータセットであるということです。

お役に立てば幸いです。


平文での一時テーブルは、適切なタイミングでサーバーを混乱させるか、単純にコピーし、比較的(すなわち非常に)簡単につかむことであり、読みtemp/、のための平文の値フォルダと強打を全体の列がありますが、これは操作の安全な方法ではありません
マーティン

1

これは、MYSQLの内部暗号化機能を使用することにより、完全な検索機能で可能です。

以下に例を示します。

!!! 私はMYSQL ENCODE()をここで簡単に使用しています。MYSQL_ENCODEは現在、安全でないと考えられています。他の内部MYSQL関数を使用してください!!!

UPDATE my_table
SET field=ENCODE('my_data', 'my_password')
WHERE ID=1;

SELECT DECODE(field, 'my_password') as field FROM my_table
WHERE field LIKE 'data';

上記のコメントが示唆するように、ENCODE()を使用しないでください。他の暗号化関数の1つを使用してください。

phpなどのアプリケーション内でこれを行う場合、各ゲートウェイクラス内に各テーブルの暗号化列のリスト/配列を保存することにより、dbゲートウェイまたはリポジトリクラス内でこれを行うことができます。

class UserGateway
{
    protected $encrypted_fields = array(
        'username',
        'email'
    );

    public function get($fields, ...)
    {
        foreach ($fields as $k => $field) {
            if (in_array($field, $fields)) {
                $fields[$k] = $this->decodeSelect($field);
            }
        }

        $sql = 'SELECT '.implode(',', $fields);

        //......
    }

    protected function decodeSelect($field)
    {
        return "DECODE($field, $pass) AS $field";
    }
}

もちろん、これは非常にラフで安全性の低いコードであり、大幅な改善なしに本番環境で使用しないでください。しかし、それは一般的なアイデアを与えるという目的を果たすべきです。


-1

SQLで、部分的ではなく完全な値(たとえば、LIKE 'value%')に対して検索していると仮定します...検索データをキャプチャするとき、データが暗号化されたときに使用したのと同じアルゴリズムを使用してそのデータを暗号化し、検索します。

例えば:

何だっただろう:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'Value'

代わりに次のようになります。

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'

1
例えば、あなたが行ごとにユニークな塩を持っている場合は、それぞれの行の塩は、検索文字列に使用する必要がありますので、salt値で動作しますいいえまともな暗号化は、これはかなり速い、複雑な取得するつもり、と高価されます
マーティン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.