Задать вопрос
Q2W
@Q2W

Как шифровать по паролю на golang ассиметричным шифром?

Хочется в приложении юзать пароли, а не файлы с ключами.
Нагуглил, что для этого используют https://pkg.go.dev/golang.org/x/crypto/pbkdf2 - генерят ключ из пароля хешированием.
И ещё есть argon2.

Но это годится только для симметричного шифрования (AES, например).
Для ассиметричного шифрования RSA это не работает, т.к. приватный ключ должен быть не просто набором рандомных байтов, а ещё и удовлетворять некоторым условиям.
Естественно, результат работы pbkdf2 и argon2 в виде относительно рандомных байт не подходит.
  • Вопрос задан
  • 720 просмотров
Подписаться 2 Средний 9 комментариев
Пригласить эксперта
Ответы на вопрос 1
Q2W
@Q2W Автор вопроса
1. Сделал так:
func (kbr keyBytesReader) Read(p []byte) (n int, err error) {
	n = copy(p, (*kbr.key)[*kbr.offset:])
	if n < len(p) {
		err = bytes.ErrTooLarge
	}
	*kbr.offset += n
	return
}

func PasswordToPrivateKey(password string) (privateKey *rsa.PrivateKey, err error) {
	dk := pbkdf2.Key([]byte(password), []byte(salt), 1024, 512*1024, sha512.New)
	kbr := keyBytesReader{&dk, new(int)}
	privateKey, err = rsa.GenerateKey(kbr, 4096)
	return
}


И это не работает, т.к.:
1. (решаемо) нет повторяемости результата генерации ключа по результату работы pbkdf2.Key в качестве рандома.
2. (не решаемо или сложно решаемо) в RSA-ключе должны быть простые числа. Т.е. далеко не всякий рандомный набор байт подойдёт.

Ну и чисто в теории пароль обладает много меньшей энтропией, чем 4096-битный RSA-ключ.

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

2. За то работает для криптографии на эллиптических кривых:
argon2Key := argon2.IDKey([]byte(password), []byte(salt), 1, 64*1024, 4, 128)
privateKey, err = ecdsa.GenerateKey(elliptic.P521(), bytes.NewReader(argon2Key))
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы