Лучший способ использовать PHP для шифрования и дешифрования паролей?[дубликат]

StackOverflow https://stackoverflow.com/questions/1289061

Вопрос

Возможный Дубликат:
PHP 2-стороннее шифрование:Мне нужно хранить пароли, которые могут быть восстановлены

Я планирую хранить информацию о зарубежных учетных записях моих пользователей на своем веб-сайте, например, имя пользователя и пароли rapidshare и т.д...Я хочу сохранить информацию в безопасности, но я знаю, что если я хэширую их информацию, я не смогу извлечь ее для последующего использования.

Base64 поддается расшифровке, так что нет смысла использовать это просто так.Моя идея состоит в том, чтобы зашифровать пользователя и передавать до и после того, как он получит base64ed таким образом, даже после того, как вы его расшифруете, вы получите какой-нибудь забавно выглядящий текст, если попытаетесь расшифровать.Существует ли функция php, которая принимает значения, которые создадут уникальную комбинацию строк и дескремблируют ее позже, когда значение будет введено повторно?

Есть какие-нибудь предложения?

Это было полезно?

Решение

Вы не должны шифровать пароли, вместо этого вы должны хэшировать их, используя алгоритм, подобный bcrypt. Этот ответ объясняет, как правильно реализовать хэширование паролей в PHP. Тем не менее, вот как вы бы зашифровали / расшифровали:

$key = 'password to (en/de)crypt';
$string = ' string to be encrypted '; // note the spaces

Для шифрования:

$iv = mcrypt_create_iv(
    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
    MCRYPT_DEV_URANDOM
);

$encrypted = base64_encode(
    $iv .
    mcrypt_encrypt(
        MCRYPT_RIJNDAEL_128,
        hash('sha256', $key, true),
        $string,
        MCRYPT_MODE_CBC,
        $iv
    )
);

Для расшифровки:

$data = base64_decode($encrypted);
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));

$decrypted = rtrim(
    mcrypt_decrypt(
        MCRYPT_RIJNDAEL_128,
        hash('sha256', $key, true),
        substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),
        MCRYPT_MODE_CBC,
        $iv
    ),
    "\0"
);

Предупреждение:Приведенный выше пример шифрует информацию, но не аутентифицирует зашифрованный текст, чтобы предотвратить подделку. Ты должен не для обеспечения безопасности полагайтесь на неаутентифицированное шифрование, тем более что предоставленный код уязвим для атак Oracle с дополнением.

Смотрите также:

Кроме того, не используйте просто "пароль" для ключа шифрования. Ключи шифрования - это случайные строки.


Демо-версия на 3v4l.org:

echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="

echo "\n";

echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "

Другие советы

Предупреждение о безопасности:Этот класс небезопасен.Это использование Рейндаэль 256-ЕЦБ, который не является семантически безопасным.Просто потому, что "это работает", не означает, что "это безопасно".Кроме того, впоследствии это приводит к удалению пробелов из-за неправильного заполнения.

Недавно нашел этот класс, он работает как мечта!

class Encryption {
    var $skey = "yourSecretKey"; // you can change it

    public  function safe_b64encode($string) {
        $data = base64_encode($string);
        $data = str_replace(array('+','/','='),array('-','_',''),$data);
        return $data;
    }

    public function safe_b64decode($string) {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }

    public  function encode($value){ 
        if(!$value){return false;}
        $text = $value;
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->skey, $text, MCRYPT_MODE_ECB, $iv);
        return trim($this->safe_b64encode($crypttext)); 
    }

    public function decode($value){
        if(!$value){return false;}
        $crypttext = $this->safe_b64decode($value); 
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->skey, $crypttext, MCRYPT_MODE_ECB, $iv);
        return trim($decrypttext);
    }
}

И назвать это:

$str = "My secret String";

$converter = new Encryption;
$encoded = $converter->encode($str );
$decoded = $converter->decode($encoded);    

echo "$encoded<p>$decoded";

Предупреждение о безопасности: Этот код небезопасен.

рабочий пример

define('SALT', 'whateveryouwant'); 

function encrypt($text) 
{ 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
} 

function decrypt($text) 
{ 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SALT, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
} 

$encryptedmessage = encrypt("your message"); 
echo decrypt($encryptedmessage); 

Одна вещь, о которой вы должны быть очень хорошо осведомлены, когда имеете дело с шифрованием:

Попытки быть умным и изобретать что-то свое обычно оставляют вас с чем-то неуверенным.

Вероятно, вам было бы лучше всего использовать один из расширения криптографии которые поставляются с PHP.

Это даст вам лишь незначительную защиту.Если злоумышленник может запустить произвольный код в вашем приложении, он может получить пароли точно таким же образом, как и ваше приложение.Вы все еще могли бы получить некоторую защиту от некоторых атак SQL-инъекций и неуместных резервных копий БД, если вы храните секретный ключ в файле и используете его для шифрования на пути к БД и дешифрования на выходе.Но вы должны использовать bindparams, чтобы полностью избежать проблемы с внедрением SQL.

Если вы решите зашифровать, вам следует использовать для этого какую-нибудь высокоуровневую криптографическую библиотеку, или вы будет пойми это неправильно.Вам нужно будет правильно настроить ключ, заполнить сообщение и проверить целостность, иначе все ваши усилия по шифрованию окажутся бесполезными. GPGME ( Графический интерфейс ) это хороший выбор для одного примера.Mcrypt имеет слишком низкий уровень, и вы, вероятно, поймете это неправильно.

Предупреждение безопасности:Этот код является неуверенный в себе.В дополнение к уязвимости к атакам с использованием выбранного зашифрованного текста, его зависимость от unserialize() делает его уязвимым для внедрения объектов PHP.

Для обработки строки / массива я использую эти две функции:

function encryptStringArray ($stringArray, $key = "Your secret salt thingie") {
 $s = strtr(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), serialize($stringArray), MCRYPT_MODE_CBC, md5(md5($key)))), '+/=', '-_,');
 return $s;
}

function decryptStringArray ($stringArray, $key = "Your secret salt thingie") {
 $s = unserialize(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode(strtr($stringArray, '-_,', '+/=')), MCRYPT_MODE_CBC, md5(md5($key))), "\0"));
 return $s;
}

Это гибко, поскольку вы можете хранить / отправлять через URL строку или массив, потому что строка / массив сериализуется перед шифрованием.

Проверьте mycrypt(): http://us.php.net/manual/en/book.mcrypt.php

И если вы используете postgres, есть pgcrypto для шифрования на уровне базы данных.(облегчает поиск и сортировку)

Лучшая идея для шифрования / дешифрования ваших данных в базе данных, даже если у вас есть доступ к коду, - это использовать 2 разных способа передачи личного пароля (user-pass) для каждого пользователя и личный код для всех пользователей (system-pass).

Сценарий

  1. user-pass хранится вместе с md5 в базе данных и используется для проверки каждого пользователя при входе в систему.Этот пользовательский пропуск является другой для каждого пользователя.
  2. Каждая запись пользователя в базе данных содержит в md5 system-pass для шифрования / дешифрования данных.Этот системный пропуск является то же самое для каждого пользователя.
  3. Каждый раз, когда пользователь удаляется из системы, все данные, зашифрованные при старом системном проходе, должны быть зашифрованы снова при новом системном проходе, чтобы избежать проблем с безопасностью.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top