4
0

More than 3 years have passed since last update.

PHP 暗号化、ハッシュ関数

Last updated at Posted at 2019-12-31

ワンタイムパッド

  • 平文と乱数でXOR論理演算するだけの暗号。
  • 情報理論的安全性を持つ暗号方式である。
  • 一度使用した鍵(乱数)は、廃棄するのが原則である。
  • OTPの使い回しで解読された事例で、ベノナ文書がある。
  • もっとも鍵の配送問題に難があるため、実用的でない。

<?php
// 暗号化したい文字列
$str = "保つのに時があり,捨てるのに時がある。";
// ワンタイムパッド
$pad = [
  12,20,148,22,87,91,239,187,206,215,103,207,192,46,75,243,
  204,61,121,210,145,167,108,78,166,129,109,239,138,134,150,196,
  217,63,158,201,204,66,181,198,54,0,0,130,163,212,57,167,
  169,115,170,50,109,116,173,177,252,242,233,3,33,28,139,73,
];

// ワンタイムパッドで暗号化
function convert($str, $pad) {
  $res = "";
  for ($i = 0; $i < strlen($str); $i++) {
    // 一文字取り出し、ASCIIコードに変換
    $c = ord(substr($str, $i, 1));
    // XORで暗号化
    $cx = $c ^ $pad[$i];
    // ASCIIコードを文字に変換
    $res .= chr($cx);
  }
  return $res;
}

// 暗号化
$enc = convert($str, $pad);
echo "暗号化した文字列:{$enc}\n";
// 復号化 (P xor K) xor K = P
$dec = convert($enc, $pad);
echo "復号化した文字列:{$dec}\n";

公開暗号鍵方式

  • 公開暗号鍵と秘密鍵の二つの鍵を利用して暗号化するものを「公開暗号鍵方式」と呼ぶ。
  • 受信側が公開鍵と秘密鍵を持っている。
  • 送信側は受信側が公開している公開鍵を取得して、公開鍵でデータを暗号化して送信する。
  • 受信側は受け取ったデータを秘密鍵で復号化してデータを取得する。
<?php
$passphrase = 'test';

// config
$conf = [
    //Digest method
    'digest_alg'       => 'sha512',
    //Specifies how many bits should be used to generate a private key.
    'private_key_bits' => 2048,
    //Specifies the type of private key to create. 
    'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
// Create the keypair
$pk = openssl_pkey_new($conf);

// Get private key
openssl_pkey_export($pk, $private_key, $passphrase);

// Get public key
$pub = openssl_pkey_get_details($pk);
$pub_key = $pub["key"];

// Write data to the file
file_put_contents("private.pem", $private_key);
file_put_contents("public.pem", $pub_key);

echo "秘密鍵: " . $private_key . "\n";
echo "公開鍵: " . $pub_key . "\n";

// Read data
$pub_key = file_get_contents("public.pem");
$pri_key = file_get_contents("private.pem");

$data = 'plaintext data goes here';

// Encrypt the data to $encrypted using the public key
openssl_public_encrypt($data, $encrypted, $pub_key);

// Get the private key using pass phrase
$pri = openssl_get_privatekey($pri_key, $passphrase);

// Decrypt the data using the private key and store the results in $decrypted
openssl_private_decrypt($encrypted, $decrypted, $pri);

echo $decrypted;

ハッシュ関数

  • 任意の長さのデータ入力すると固定長のビット列を返す関数。
  • 以下の特性を持つ。
    • 原像計算困難性(一方向性) : 与えられたハッシュ値に対して、そのハッシュ値を出力するようなハッシュ関数への入力を求めることが困難。
    • 第2原像計算困難性(弱衝突耐性) : メッセージのハッシュ値が与えられたとき、そのハッシュ値から他のメッセージを探すことが困難なこと。
    • 衝突困難性(強衝突耐性) : 同じハッシュ値を与える二つの入力値を求めることが困難。
  • MD5, SHA-1は強衝突耐性が破られており、同じハッシュ値を持つ2つのメッセージが作れる。
  • PHPだとpassword_hashでハッシュ化できる関数がある。ハッシュ化アルゴリズムはbcrypt アルゴリズム。

ソルト

ハッシュ化されたパスワードであっても、「レインボーテーブル」や「総当たり」などの攻撃で元のパスワードを復元できる可能性があるので、ソルト(salt)と呼ばれる適当な文字列をパスワードに付加する。

ストレッチング

生成したハッシュ値を再度ハッシュ化するループを回す手法。

参考

ワンタイムパッド - Wikipedia
ハッシュ関数 - Wikipedia
password_hash - PHPマニュアル

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0