暗号化全般、および具体的には DB 暗号化オプションについてもう少し背景を説明したいと思うかもしれません (データ ストアについては言及していませんが、完全な暗号化には MySQL と Postgres のオプションがあります)。一般に、ほとんどの場合、「独自にロールする」ことは悪い考えであり、残念なことに、mcrypt() と openssl_*() 関数の間には、率直に言って、初心者に提示されるオプションが多すぎます (EBC と CBC を同等に提示するなど)。有効なオプション)。このスレッド: https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-ownは主に「斬新な」暗号化プリミティブを作成することの無益さについて話していますが、原則は素朴な試みにも適用されますアプリケーションおよびデータベース レベルの暗号化の実装についても同様です。
実際問題として、対処しなければならない可能性が最も高いのは、パスワード/キー管理の問題です。以下のコードは、すべての責任をクライアント (送信者) に負わせます。また、送信されたパスワードを保存しない限り (これでは目的全体が無効になります)、ユーザーがパスワードを忘れた場合、または将来パスワードを提供できなくなった場合は、データが暗号化されます。データベース内のデータは回復不能になります。(そして、はい、本当にYak Shaving パスをたどりたい場合は、マルチキー エンベロープ暗号化のオプションがあります)。
キー/パスワードをサーバー側に保存する場合、せいぜい、敵のパスに小さな道路のバンプを配置するだけです。敵がキーファイルを読み取ることができれば、データを取得できます. しかし、最悪の場合、パスワードをローカルに保存することで、ユーザーに誤った安心感を与えることになり、これが財務、健康、またはその他の保護された情報である場合、あなたとあなたの組織はその責任の負担を負うことになります.
最後に、成熟したライブラリがここにあります: http://phpseclib.sourceforge.net/crypt/examples.htmlしかし、私の意見では、初心者ユーザーにはあまりにも多くのオプションを提供しています (たとえば、コードジェネレーター)。パスワードハッシュについては、http ://www.openwall.com/phpass/ にある phpPass ライブラリをよく見てください。
そうは言っても、ランダムに生成された初期化ベクトルとソルト、および256ビットのAES対称(たとえば、非公開鍵)暗号を使用した、単純な双方向のかなり強力な暗号化の作業開始です。OSX Lion & CentOS/RedHat 6 でテスト済み。
幸運を!
//$message = escapeshellarg( $_POST['message'] );
$message = 'This is my very secret data SSN# 009-68-1234';
// Set to some reasonable limit for DB.
// Make sure to size DB column +60 chars
$max_msg_size = 1000;
$message = substr($message, 0, $max_msg_size);
// User's password (swap for actual form post)
//$password = escapeshellarg( $_POST['password'] );
$password = 'opensesame';
// Salt to add entropy to users' supplied passwords
// Make sure to add complexity/length requirements to users passwords!
// Note: This does not need to be kept secret
$salt = sha1(mt_rand());
// Initialization Vector, randomly generated and saved each time
// Note: This does not need to be kept secret
$iv = substr(sha1(mt_rand()), 0, 16);
echo "\n Password: $password \n Message: $message \n Salt: $salt \n IV: $iv\n";
$encrypted = openssl_encrypt(
"$message", 'aes-256-cbc', "$salt:$password", null, $iv
);
$msg_bundle = "$salt:$iv:$encrypted";
echo " Encrypted bundle = $msg_bundle \n\n ";
// Save it... (make sure to use bind variables/prepared statements!)
/* db_write( "insert into sensitive_table encrypted_msg values (:msg_bundle)",
$msg_bundle ); */
今それを取得します:
// Retrieve from DB...
//$password = escapeshellarg( $_POST['password'] );
$password = 'opensesame';
// Swap with actual db retrieval code here
//$saved_bundle = db_read( "select encrypted_msg from sensitive_table" );
$saved_bundle = $msg_bundle;
// Parse iv and encrypted string segments
$components = explode( ':', $saved_bundle );;
var_dump($components);
$salt = $components[0];
$iv = $components[1];
$encrypted_msg = $components[2];
$decrypted_msg = openssl_decrypt(
"$encrypted_msg", 'aes-256-cbc', "$salt:$password", null, $iv
);
if ( $decrypted_msg === false ) {
die("Unable to decrypt message! (check password) \n");
}
$msg = substr( $decrypted_msg, 41 );
echo "\n Decrypted message: $decrypted_msg \n";
出力例:
Password: opensesame
Message: This is my very secret data SSN# 009-68-1234
Salt: 3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37
IV: 00c1d3b4c6a6f4c3
Encrypted bundle = 3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37:00c1d3b4c6a6f4c3:KB6k+GlM+0EHbETUgEe8Lck0nF5qBz+51wc5LtmS4XMOm0Pfyyr2PIXMVEyzs/41
array(3) {
[0]=>
string(40) "3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37"
[1]=>
string(16) "00c1d3b4c6a6f4c3"
[2]=>
string(64) "KB6k+GlM+0EHbETUgEe8Lck0nF5qBz+51wc5LtmS4XMOm0Pfyyr2PIXMVEyzs/41"
}
Decrypted message: This is my very secret data SSN# 009-68-1234