Рекомендации по криптографии для хранения паролей в Node

Я ищу простое и безопасное решение для хранения пароля пользователя с помощью Node. Я новичок в криптографии, но пытаюсь собрать решение вместе с исследованиями в Интернете. Я ищу подтверждение того, что то, что я придумал, является надежным решением для веб-приложения с базовыми (не банками, больницами и т. д.) потребностями безопасности. Вот:

var crypto = require('crypto');
var SALT_LENGTH = 64;
var KEY_LENGTH = 64;
var ITERATIONS = 1000;

function createHashedPassword(plainTextPassword, cb) {
    crypto.randomBytes(SALT_LENGTH, function (err, salt) {
        console.time('password-hash');
        crypto.pbkdf2(plainTextPassword, salt, ITERATIONS, KEY_LENGTH, function (err, derivedKey) {
            console.timeEnd('password-hash');
            return cb(null, {derivedKey: derivedKey, salt: salt, iterations: ITERATIONS});
        });
    });
};

... и вот выбор, который я сделал, который привел меня к этому моменту:

Какой алгоритм хеширования использовать?

Основываясь на этой широко цитируемой статье, похоже, что ведущими претендентами являются PBKDF2, bcrypt и scrypt . Я выбрал PBKDF2, потому что он имеет встроенную поддержку в Node.

Какой размер соли использовать?

Этот ответ о переполнении стека показался мне самым простым ответом, который я смог найти. Я все еще не очень понимаю, почему 64 байта - это правильный размер соли. Когда я гуглю, я получаю другие ответы на обмен стеками, такие как this, но я не уверен, что это применимо к алгоритму Node? Совершенно запутанный здесь, объяснение, предназначенное для новичка, использующего эту функцию Node, было бы потрясающим.

Какую длину ключа использовать?

Еще раз, я в основном основывал свой выбор на том же ответе, что и выше, но я м так же туманен в основах «почему». В ответе говорится, что «генерировать ключи меньше, чем ваш ввод, бесполезно, поэтому используйте не менее 64 байт». Хм? Еще раз, практическое объяснение было бы полезно.

Сколько итераций использовать?

Для этого вопроса я основывал свой выбор на этом ответе на обмен стеками. Я мало что в этом понимаю, но я понял, что алгоритм должен занимать примерно 8 мс. Итак, как вы можете видеть, я установил таймеры для функции и настроил свои итерации, чтобы получить ее на этом приблизительном уровне на моей машине.

Спасибо!


person markdb314    schedule 22.10.2014    source источник
comment
Когда дело доходит до безопасности, обычно лучше придерживаться хорошо известных и хорошо протестированных библиотек. На ум приходит Passport.JS, и у него есть плагины, которые вы можете использовать для обработки хеширования.   -  person Pier-Luc Gendreau    schedule 23.10.2014
comment
Спасибо @Pier-LucGendreau. Я использую PassportJS, но он не включает код для хэширования и хранения паролей как часть своей библиотеки или его подмодулей. Если я что-то упустил, пожалуйста, дайте мне знать.   -  person markdb314    schedule 24.10.2014
comment
Вы можете использовать github.com/saintedlama/passport-local-mongoose.   -  person Pier-Luc Gendreau    schedule 24.10.2014
comment
Хорошо, я взглянул на это... но я вижу более произвольный выбор констант, о которых я упоминал выше. Они выбирают длину соли по умолчанию 32 байта, длину ключа 512 байт и итерации 25000. В моем комментарии к ответу относительно пакета узла «учетных данных» ниже создатель говорит, что соль должна быть того же размера, что и хеш . Не короче и не длиннее. Одна из этих реализаций неверна! Это демонстрирует то, что я видел в ходе исследования этого... каждая реализация, которую я нахожу, использует разные значения для этих констант, без объяснения причин.   -  person markdb314    schedule 24.10.2014
comment
Прежде всего, помните, что ни одно решение не является пуленепробиваемым. Лучшее решение для перебора на сегодня — это медленные хэши! 20 лет назад вы могли легко положиться на DES или RSA, сегодня ни один из них не является безопасным. Это слои на слоях с проверкой третьей стороны, и даже тогда вы просто машете рукой....   -  person winmutt    schedule 24.10.2014


Ответы (2)



Я настоятельно рекомендую использовать BCrypt. У алгоритма есть много преимуществ, и большинство реализаций решают все эти вопросы за вас.

Как описано в этом ответе:

Bcrypt имеет наилучшую репутацию для криптографического алгоритма: он существует уже довольно давно, используется довольно широко, «привлекает внимание» и до сих пор остается нерушимым.

Подробную статью о том, как внедрить BCrypt в node/express, а также в другие фреймворки, я написал здесь: http://davismj.me/blog/bcrypt

person Matthew James Davis    schedule 28.01.2016