Вы не должны использовать хеш-вывод bcrypt в качестве ключа шифрования; он не предназначен для использования в качестве ключевого материала:
- BCrypt не является функцией получения ключа
- BCrypt - это функция хранения паролей.
У вас есть закрытый ключ с эллиптической кривой, который вы хотите зашифровать с помощью пароля пользователя. Конечно, вы не хотите использовать пароль напрямую - вы хотите использовать пароль для получения ключа шифрования. Для этого вы можете использовать:
Это обе функции получения ключа (например, функция получения ключа на основе пароля). Их цель - сгенерировать ключ шифрования по паролю. Они созданы быть «сложными».
Вы кормите оба этих алгоритма:
- пароль
- параметры стоимости
- поваренная соль
- желаемое количество байтов (например, 32 ==> 32 байта ==> 256 бит)
и он возвращает вам 256-битный ключ, который вы можете использовать в качестве ключа шифрования для AES-256.
Затем вы хотите сделать резервную копию ключа пользователя
Я так понимаю, вы хотите:
- хранить зашифрованный закрытый ключ эллиптической кривой на вашем сервере
- хранить хэш их пароля на своем сервере
И ваш вопрос был таков: поскольку вы уже пропустили их пароль через «функцию хеширования», не можете ли вы просто использовать этот хеш в качестве сохраненного пароля?
Нет! Этот хеш также является ключом шифрования, защищающим их закрытый ключ. Вы не хотите, чтобы этот закрытый ключ никуда передавался. Вы не хотите, чтобы он существовал где-либо. Этот 32-байтовый ключ шифрования следует удалить из памяти, как только вы закончите с ним.
Что вам следует сделать, если вы также хотите сохранить хэш пароля пользователя, - это использовать алгоритм, который обычно используется для хранения паролей:
- pbkdf2 (функция получения ключа, использованная в хранилище паролей)
- bcrypt (лучше, чем pbkdf2)
- scrypt (функция получения ключа, используемая в хранилище паролей; лучше, чем bcrypt)
- argon2 (лучше, чем scrypt)
Вы должны отдельно запустить пароль пользователя с помощью одного из этих алгоритмов хранения паролей. Если у вас есть доступ к bcrypt; используйте это поверх pbkdf2. Если у вас есть скрипт, используйте его для обоих:
- получение ключа шифрования
- хеширование пароля
Безопасность вашей системы зависит (в дополнение к секретности пароля) от вычислительного расстояния между паролем пользователя и ключом шифрования, защищающим его закрытый ключ:
"hunter2" --PBKDF2--> Key material
"hunter2" ---------bcrypt-------> Key material
"hunter2" ----------------scrypt----------> Key material
Вы хотите, чтобы между паролем и ключом было как можно большее расстояние.
Не рекомендуемый чит
Если вы действительно отчаянно пытаетесь сэкономить циклы процессора (и избежать двойного вычисления scrypt), технически вы можете взять:
Key Material ---SHA2---> "hashed password"
И назовите хэш ключа шифрования своим «хешированным паролем» и сохраните его. Вычисление одного SHA2 незначительно. Это приемлемо, потому что единственный способ использовать это злоумышленник - это попытаться угадать все возможные 256-битные ключи шифрования - это проблема, которую они не могут решить в первую очередь. Невозможно подобрать 256-битный ключ. И если бы они попытались перебрать его, дополнительная хешированная версия им не помогла, так как они могли бы просто проверить свою попытку, пытаясь расшифровать закрытый ключ.
Но это гораздо менее желательно, потому что вы храните (преобразованную) версию ключа шифрования. Вы хотите, чтобы этот ключ (и любые его преобразованные версии) хранились как можно меньше.
Подводить итоги
- сгенерировать пару ключей EC
- encryptionKey = scryptDeriveBytes (пароль, соль, стоимость, 32)
- encryptedPrivateKey = AES256 (privateKey, encryptionKey)
- passwordHash = scryptHashPassword (пароль, соль, стоимость)
и загрузить
- encryptedPrivateKey
- хэш паролей
person
Ian Boyd
schedule
16.11.2016