X

PHP (不)建議使用的 加解密演算法

PHP 7.2 後 mcrypt 被拿掉了,但是偏偏以前使用的演算法,PHP7.2 的 OpenSSL 不支援,所以要重新來找新的加解密演算法。

PHP 建議與不建議使用的 加解密演算法

加解密演算法這麼多種,要怎麼挑選呢?

PHP 官方文件的範例就有排除法,排掉 (ECB, RC2, RC4, DES, 3DES, MD5 based)後,能用的演算法就剩不多,在從裡面來挑選一下。

PHP: openssl_get_cipher_methods - Manual,下述程式取自此篇:

<?php
$ciphers = openssl_get_cipher_methods();
$ciphers_and_aliases = openssl_get_cipher_methods(true);
$cipher_aliases = array_diff($ciphers_and_aliases, $ciphers);

//ECB mode should be avoided
$ciphers = array_filter( $ciphers, function($n) { return stripos($n,"ecb")===FALSE; } );

//At least as early as Aug 2016, Openssl declared the following weak: RC2, RC4, DES, 3DES, MD5 based
$ciphers = array_filter( $ciphers, function($c) { return stripos($c,"des")===FALSE; } );
$ciphers = array_filter( $ciphers, function($c) { return stripos($c,"rc2")===FALSE; } );
$ciphers = array_filter( $ciphers, function($c) { return stripos($c,"rc4")===FALSE; } );
$ciphers = array_filter( $ciphers, function($c) { return stripos($c,"md5")===FALSE; } );
$cipher_aliases = array_filter($cipher_aliases,function($c) { return stripos($c,"des")===FALSE; } );
$cipher_aliases = array_filter($cipher_aliases,function($c) { return stripos($c,"rc2")===FALSE; } );

print_r($ciphers);
print_r($cipher_aliases);
?>

程式跑出來,能使用的演算法:

Array
(
[18] => AES128
[19] => AES192
[20] => AES256
[21] => BF
[26] => CAST
[27] => CAST-cbc
[50] => IDEA
[82] => aes128
[83] => aes192
[84] => aes256
[85] => bf
[90] => blowfish
[91] => cast
[92] => cast-cbc
[115] => idea
)

這些跑出來的演算法,該挑哪一個呢?在 PHP 上述的官網下面有程式,直接可以測試演算法的速度,程式如下:

<?php
const TEST_COUNT = 100000;
const SOURCE = 'Note that HTML tags are not allowed in the posts, but the note formatting is preserved.';
const KEY = "password";

function TESTER( $testing_function, $argument )
{
    $t = microtime(true);

    for ($test_iterator = 0; $test_iterator < TEST_COUNT; $test_iterator++) {
        $testing_function( $argument );
    }
    return round(microtime(true) - $t, 4);
}

$crypt = function($cipher) {
    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($ivlen);
    openssl_encrypt(SOURCE, $cipher, KEY, $options=0, $iv);
};

$methods = openssl_get_cipher_methods(false);

array_splice( $methods, 0, count($methods) / 2);

$timings = array();

foreach ($methods as $cypher) {
    $time = TESTER( $crypt, $cypher );
    $timings[ $cypher ] = $time;
    echo str_pad($cypher, 40, ' ', STR_PAD_LEFT), " have time ", str_pad($time, 8, STR_PAD_LEFT), ' seconds. ', PHP_EOL;
}

uasort($timings, function($a, $b){
    return $a <=> $b;
});

$min_time = round(reset($timings) / TEST_COUNT, 7);
$min_cypher = key($timings);

$max_time = round(end($timings) / TEST_COUNT, 7);
$max_cypher = key($timings);

echo '-------------', PHP_EOL;
echo "Total tests: ", count($timings), PHP_EOL;
echo "Max timing : {$max_time} seconds for `{$max_cypher}` algorithm.", PHP_EOL;
echo "Min timing : {$min_time} seconds for `{$min_cypher}` algorithm.", PHP_EOL;

echo 'Details: ', PHP_EOL;

foreach ($timings as $m => $t) {
    echo '- ', str_pad($t, 8, STR_PAD_LEFT), " seconds for `{$m}`", PHP_EOL;
}

echo PHP_EOL;
?>

速度跑完後,應該就可以評估要挑選哪個演算法了~

相關網頁

  • Encryption operating modes: ECB vs CBC - 為何不要用 ECB 要用 CBC
  • Openssl blowfish cbc (BF-CBC) or AES-256-CBC
    • Is AES-256-CBC more secure than BF-CBC? Or is it just another way of encryption?
    • both blowfish & AES are block ciphers,AES is said that is more secure than blowfish...
Tsung: 對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.
Related Post