web-dev-qa-db-ja.com

暗号化されたMySQLデータベースエントリでWebアプリを構築しますか?

私はPHP MySQLベースのWebサイトを構築し、暗号化されたユーザーの詳細を保存し、その他すべてのフィールドをプレーンテキストで保存する経験があります。最新のプロジェクトでは、機密データをデータベースに保存する必要があります。私はすべて自分をホストしています。

ユーザーが自分のエントリにアクセスしてプレーンテキストの結果を表示できるシステムをセットアップしたいのですが、他のユーザーにアクセスできたとしても、それらは暗号化された、理解できない文字列になります。

私はこれを達成する方法を考えていますが、おそらくそれは最適ではないか、すでにより効率的な方法でこれを行うためのツールが存在します。

  1. ユーザー名をプレーンテキストとして保存し、パスワードをsha1()で暗号化します。または、両方ともsha1()で暗号化されています。
  2. ユーザーのパスワード(暗号化されたものではなく、入力したもの)を使用して、そのユーザー名とパスワードに固有のキーを定義します。これは、セッション変数として格納されます。
  3. そのキーを使用して、すべてのユーザーデータを暗号化または復号化します。

私の意見では、誰かがデータベースにアクセスし、プレーンテキストのユーザー名と暗号化されたパスワードのリストを見たとしても、どこにも保存されていないため、特定のキーを見つけることができませんでした。したがって、アクセスが取得されたとしても、機密データベースフィールドの内容を解読することはできませんでした。もちろん、私はとにかく彼らがデータベースにアクセスするのを止める方法で構築していますが、万能の努力として、これは良い一連のステップのように思えます。

専門家はこれについてコメントして、いくつかのアドバイスを提供できますか?どうもありがとう。

5
Joey O

MySQLによると、AES暗号化_Advanced Encryption Standard_)は、SQLで可逆的な暗号化と復号化を提供するために利用できる最良の方法です。

以前はRijndaelとして知られていた_AES_ENCRYPT_関数と_AES_DECRYPT_関数がMySQLに組み込まれているため、ユーザーデータを取得してソルトで暗号化し、データベースに保存できます。後で再度抽出して復号化します。

塩を定義する

暗号化するデータにソルトを適用する必要があります。これは、暗号化アルゴリズムが使用する特別なコードで、鍵のように機能します。

データを復号化するには、まったく同じキーを提供する必要があります。攻撃者がデータベースにアクセスする必要がある場合、ソルトを知らない限り、データベースを解読することはできません。

PHPでこのようにソルトを定義すると、SQLステートメントに定数をより簡単に取り込むことができます。

if(!define('SALT')) define('SALT','897sdn9j98u98jk');

MySQLデータベースにデータを挿入して機密情報を暗号化するには、saltとともにこのようなコマンドを発行する必要があります。

INSERT INTO your_table (username,email,shoe size) VALUES ('$username', AES_ENCRYPT('$email','".SALT."'), AES_ENCRYPT('$shoesize','".SALT."'));

ユーザー名は機密ではないため、これはプレーンテキストで挿入されますが、ユーザーのメールと靴のサイズを暗号化して、saltにアクセスしないとユーザーが表示されないようにします。

ある時点で、暗号化された形式で保存したデータの一部にアクセスする必要があります。これは、MySQLのAES_DECRYPT関数と、データを暗号化して挿入したときに使用したのと同じソルトを使用して非常に簡単に行うことができます。

SELECT username, AES_DECRYPT('email','".SALT."') AS email, AES_DECRYPT('shoesize','".SALT."') AS shoesize FROM your_table WHERE username ='fred';

AES_DECRYPTを使用せずに、または間違った、またはソルトなしで暗号化されたデータを選択すると、奇妙な文字の見苦しい、読み取れない文字列が表示されます。つまり、攻撃者がデータベースにアクセスできても、サーバーにアクセスしてソルトを表示できない場合、保存されているデータを読み取ることはできません。少なくとも、データを解読するためにかなりの時間を費やす必要はありません。

暗号化されたレコードの更新は挿入と非常に似ています。基本的には、同じソルトを適用してAES_ENCRYPTコマンドを再発行し、データを再度暗号化して安全にロックします。

UPDATE your_table SET email = AES_ENCRYPT('$email','".SALT."'), shoesize = AES_ENCRYPT('$shoesize','".SALT."') WHERE username= 'fred';

AES_ENCRYPTとAES_DECRYPTの両方を使用して暗号化されたデータを検索する

暗号化されたデータを検索して、暗号化されていない形式で表示する必要がある場合、状況は少し複雑になります。

たとえば、メールアドレスを使用してユーザーを検索したいが、データベースでそれを暗号化したとします。最初に、検索するメールアドレスをAES_ENCRYPTとソルトで暗号化する必要があります。次に、AES_DECRYPTを使用して、MySQLが確実に復号化し、読み取り可能な形式で返すようにする必要があります。

これを実現するには、次のようなコードを使用します。

SELECT user_username, AES_DECRYPT(email,'".SALT."') AS email, AES_DECRYPT(shoesize,'".SALT."') AS shoesize FROM your_table WHERE (email = AES_ENCRYPT('$q','".SALT."'));

詳細については、次のリンクを参照してください。 http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html

6
Jenny Casarino

テーブル自体の各ユーザーのデータを確実に暗号化できますが、それは欠点を認識した後でのみ行います。データを暗号化すると、検索オプションが制限されます。たとえば、エントリが暗号化されている場合、name like 'Bob%'cost > 1000などの検索を実行できません。同様に、ユーザーごとに1つ(またはユーザーごとに1つのテーブル)の複数のデータベースを使用することもできますが、アプリの成長と発展に伴い、スキーマの同期を維持できないという問題が発生し始めます。

最終的に、そのようなスキームは、あなたが思っているほど安全ではないかもしれません。彼らはまだ、たとえば、人々が他の人々のデータにアクセスする主要な方法を妨げません...単に彼らのコンピュータを使うか、彼らのパスワードを推測することによって。

正直なところ、あなたの質問は、この種のデータを処理した経験がないために出されていると思います。

私へのアドバイスはセキュリティギミックを使用したいという衝動に抵抗するです。通常どおりにデータベースとテーブルを設計します。次に、データの暗号化に費やしたすべての労力をサーバー側アプリケーションの安全性の確保に費やします。すべてのリクエストが、リクエストされているデータに対するユーザー認証を適切に検証していることを確認してください。注入に関する問題がないことを確認してください。接続にはsslを使用します。サーバーで適切なファイアウォールが実行されていることを確認してください。

4
GrandmasterB

Mysqlデータを暗号化および復号化するには、AES_ENCRYPT()およびAES_DECRYPT()関数を使用します。これらの関数は、公式のAES(Advanced Encryption Standard)アルゴリズムを使用し、128ビットのキー長でデータをエンコードしました。 128ビットの方がはるかに高速で、ほとんどの目的で十分に安全です。

AES_ENCRYPT()は文字列を暗号化し、バイナリ文字列を返すためです。 AES_DECRYPT()は、暗号化された文字列を復号化し、元の文字列を返します。

AESはブロックレベルのアルゴリズムです。したがって、データが暗号化されると、パディングされます。したがって、次の式を使用して結果文字列の長さを計算できます。

1。)16 × (trunc(string_length / 16) + 1)

したがって、アドレスフィールドの構造が= VARCHAR(100) ; //100 length of varcharの場合、暗号化する前に変換する必要があります

_= 16 * (trunc(100/ 16) + 1)
= 16 * (6.25 + 1)
= 16 * 7.25
= 116
_

したがって、VARCHAR(100)VARBINARY(116) minimumに変換する必要があります。この場合は、もう少しVARBINARY(150)を使用することをお勧めします。

AES_DECRYPT()が無効なデータまたは不正なパディングを検出すると、NULLが返されるためです。しかし、入力データまたはキーが無効な場合、AES_DECRYPT()_to return a non-NULL value_(おそらくガベージ)も可能です。

構文:

1。)AES_ENCRYPT(str, key_str);

2。)AES_DECRYPT(crypt_str,key_str);

暗号化と復号化はキーに基づいて行われることに注意してください。したがって、そのキーを秘密の場所に保管し、変数を使用してmysqlにキーを渡して、データを暗号化および復号化することができます。

AES_ENCRYPT()AES_DECRYPT()は、MySQLで現在利用できる最も暗号的に安全な暗号化関数と見なすことができます。

次のようにデータを挿入します。

_INSERT into user (first_name, address) VALUES (AES_ENCRYPT('Obama', 'usa2010'),AES_ENCRYPT('Obama', 'usa2010'));
_

次のようにデータを取得します。

_SELECT AES_DECRYPT(first_name, 'usa2010'), AES_DECRYPT(address, 'usa2010') from user;
_

追加表記:

暗号化するデータにソルトを適用する必要があります。これは、暗号化アルゴリズムが使用する特別なコードで、鍵のように機能します。

データを復号化するには、まったく同じキーを提供する必要があります。攻撃者がデータベースにアクセスする必要がある場合、ソルトを知らない限り、データベースを解読することはできません。

PHPでこのようにソルトを定義すると、SQLステートメントに定数をより簡単に取り込むことができます。

3
Adromil Balais

1つのプロジェクトでは、デジタル証明書を使用して暗号化を行います。

暗号化/復号化はクライアント側で行われ、ActiveXコンポーネントまたはJavaアプレットを使用する必要があります。

もちろん、これはあなたの目的にとってやり過ぎかもしれません。

0
Kinjal Dixit

Sha1()は暗号化関数ではなく、ハッシュ関数です。これは一方通行であることを意味します。 sha1()を使用して文字列をエンコードすると、ハッシュが生成されますが、ハッシュから文字列に移動することはできません。

次に、パスワードは常にハッシュとして保存し、プレーンテキストとして保存しないでください。しかしもちろん、セキュリティはハッシュの強度に依存し、sha1()は使用できる最高のものではありません。古くなっており、パスワードには使用しないでください。 blowfishまたはpbkdf2などを使用してパスワードを保存し、ユーザーごとに異なるランダムなSaltを使用します。

次に、オットとしてすでにコメントしました。 mysql AES_EncryptおよびDecrypt関数を使用できます。ただし、暗号化文字列は安全な場所に保管してください。たとえばクライアント側ですが、SSLを使用する必要があります。または、phpのセッションとして、ファイルシステム上のファイルにプレーンテキストとして保存されます。

または、暗号化されたデータを暗号化してクライアントに送信し、クライアント側で復号化することもできます。次に、データを送信するときにクライアント側で暗号化し、暗号化されたファイルをデータベースに保存します。しかし、私はJavaScriptを使用した暗号化についてはあまり気にしていない。

0
Pinoniq