Да, спасибо, я использовал clap, вы можете посмотреть мой вариант исполнения на GitHub, ссылка есть в статье, Возможно вы мне объясните, как можно указать, что бы пользователь выбрал хотя бы один из обязательных параметров с помощью clap, Я не знаю как это сделать в clap, именно поэтому там такая проверка
if !cli.lowercase && !cli.uppercase && !cli.numbers && !cli.symbols {
Cli::command()
.error(ClapErrorKind::MissingRequiredArgument, "Specify at least one: -L, -U, -n, -s")
.exit();
}
Так как в clap я могу указать, что этот параметр обязательный, и его нужно будет указать обязательно, А мне нужно, что бы валидация была пройдена если введен 1 и более обязательных параметром. Но если они все не обязательные, то пользователь может ничего не выбрать, что не правильно, а если все обязательные, то нужно указать все, что тоже не правильно. Потому я написал валидацию сам.
Тем, что его нужно устанавливать, tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 16 устанавливать не нужно. Тем, что у него свои алгоритмы генерации. Хотя на линукс это избыточно. Так как можно прийти к такому же результату, стандартными инструментами ядра.
Я не говорю, что это кому то нужно. Я говорил, что у меня своя параноя.
Просто увидеть эфективность кода на 10-20 символах тяжело. Потому сделал по больше поток данных, что бы было видно результат.
В моих примерах действительно мало цифр, так как это связано на прямую с /dev/random
Именно из этого источника беруться данные. Плюс, если вы читали статью, из 255 байт около около 150 игнорируються фильтром. Отфильтрированный набор символов из энтропии ядра... Не я генерирую данные, а ядро.
В этом суть поста, что бы не придумывать велосипед, а брать уже готовые данные из ядра. Не писать генераторы, не писать каке то балансиры соотношения символов, цифр, букв..
Я привел три примера, с одной pipe командой, скриптом и утилитой.
Возможно большинству читатилей будет достаточно первой команды... Так как это быстро, эфективно и вообще не требует установки пакетов. Так сказать генератор пароля из коробки на голом ядре.
Остальное по желанию, просто немного развил pipe команду.
Да, я видел эту библиотеку. Особо не увидел разницы в производительности и решил оставить Reader вместо библиотеки. Но как я уже сказал, я новичок в Rust. И если мои выводы были ориентированны лишь на скорость. То... Действительно стоило бы дождаться инициализации источника энтропии. Может мне выкладывать все свои проекты ? Лучший code-review )))
Все, до меня дошло. Вы правы. Что же, стоит исправить read_buf[..] на read_buf[..n].
А разве объявление let mut stdout = io::BufWriter::with_capacity(cli.buffer_size, io::stdout().lock());
не указывает на то, что при вызове stdout.write_all(&[charset[idx as usize]])?; данные будут заполнять внутренний буфер, и только при его переполнении выведутся в терминал ?
Имею в виду, какая разница, создать свой буфер, записать в него данные и вызвать write_all с буфером. Или инициализировать io::BufWriter::with_capacity с внутренним буфером. И он будет делать то же самое ?
Эту проблему я даже не рассматривал. Хотя конечно можно... Использовать слова и их корни, для генерации... У меня пароли хранятся в хранилище, потому, я их в принципе не запоминаю. Разве что мастер пароль помню ) Но... Идея не плохая, как вы думаете ? Если брать слова или корни слов и комбинировать их с цифрами, символами... Будет ли это... Полезно ? Или можно создавать несуществующие слова, главное что бы чередовались гласные и согласные, для удобства произношения и запоминания...
Так и есть, и смысл теряется, по крайней мере для меня. Вместо того, что бы сделать минимально нагрузки, берется цитата, конвертируется в base64 (нагрузка), потом еще хешируется (нагрузка), и только потом выдается. Хотя в действительности достаточно убрать лишние символы.
Немного заморачиваюсь с нагрузкой, приложение на расте выдавало 10 млн симполов за 0.2 секунды, я его оптимизировал, теперь выдает 10 млн за 0.06 секунды. (Еще не отправлял на гит изменения). Это конечно не имеет большого значения, ибо там у всех 8-10 ядер, много ОЗУ, в принципе люди могут позволить себе писать плохой код...
Но все же мне кажется, что лучше экономить ресурсы... У каждого своя параноя ))))
while written_total < cli.length {
let n = entropy_source.read(&mut read_buf)?;
if n == 0 {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
format!("Insufficient entropy available in {}. Try using /dev/urandom (remove -R) or wait for more system interrupts.", path)
));
}
for &byte in &read_buf[..] {
if written_total >= cli.length as usize { break; }
let idx = (byte as u32) % charset_len;
stdout.write_all(&[charset[idx as usize]])?;
written_total += 1;
}
}
По поводу странной логики. В данном листинге, на строке 1, цикл while ни как не связан с ни с буфером ввода ни с буфером вывода, он остановится, когда written_total будет >= cli.length. Далее, я передаю read_buf для заполениня в файловый дискриптор let n = entropy_source.read(&mut read_buf). Метод read возвращает реальное количество прочитаннх байт и это n. Далее это n проверяется, равен ли он 0. 0 я выбрал потому, что если там есть хоть какие то данные, они выведутся на экран, если же данные в /dev/random закончились, будет выведено соответствующее сообщение. Так как там в проверке есть return. Что же касается шанса такого развития событий, выше я писал, что : "В свою очередь /dev/urandom - бесконечный источник псевдослучайных байт, так как использует CSPRNG на базе /dev/random" - это означает, что используя /dev/urandom, буфер будет заполнен всегда, и только при использовании /dev/random есть вероятность, что буфер не будет заполнен. В таком случае при исчерпании данных - выдаст ошибку.
Взять текст, конвертировать в base64 строку и посчитать хеш такой строки.
Это будет означать, что хеш всегда одинаковый.
То есть, что бы "пароль" был разный, изначальная "цитата" тоже должна быть разная. Что как бы намекает на то, что нужно придумать цитату... Можно конечно взять текущее время вместо цитаты...
Это действительно круто. Особенно идея с сервером на Rust.
Я только начал изучать Rust, мне он сильно понравился. А вообще я .NET разработчик...
Много кто пользуется разными инструментами, но я все же за комфорт... Иметь сильный инструмент в любимом редакторе - это кайф, а написать его самому - это круто.
Тут так много коментариев, что в своем особо смысла не вижу.
Раст хороший, автор тупой. Если автор не готов к критике, для чего вообще делать пост. Главное что бы были аргументы.
Зачем выкатывать язык, если много не готово, на взгляд автора. Ответ - потому что это работает. Да, не удобно, да, не красоно, но работает и работает хорошо.
Это банальный синтаксический сахар. Не больше не меньше. Фронтэндеровская тема плакать за синтаксическим сахаром. Ой писать не удобно, что делать...
Язык молод... Вспомните С# 1.0, да даже 4.0... Он сильно отличался от последних версий... И сахара добавили достаточно...
Только вот сколько лет прошло...
Не знаю, никогда не плакал за синтаксисом. Как сделано так сделано. Работает ? Работает быстро. Мне этого достаточно.
Не могу сказать что на С# много всего удобного. Опять же, половины синтаксиса не было раньше...
Врядли мое негодование на хабре вообще как то повлияет на судьбу С#... Разве только если разрабы майков следят за хабром )))
Да, не обратил внимание, спасибо, это очень удобно !
Да, спасибо, я использовал clap, вы можете посмотреть мой вариант исполнения на GitHub, ссылка есть в статье,
Возможно вы мне объясните, как можно указать, что бы пользователь выбрал хотя бы один из обязательных параметров с помощью clap,
Я не знаю как это сделать в clap, именно поэтому там такая проверка
Так как в clap я могу указать, что этот параметр обязательный, и его нужно будет указать обязательно, А мне нужно, что бы валидация была пройдена если введен 1 и более обязательных параметром.
Но если они все не обязательные, то пользователь может ничего не выбрать, что не правильно, а если все обязательные, то нужно указать все, что тоже не правильно. Потому я написал валидацию сам.
Жалко, на установку pwgen ))
Тем, что его нужно устанавливать,
tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 16устанавливать не нужно.Тем, что у него свои алгоритмы генерации. Хотя на линукс это избыточно.
Так как можно прийти к такому же результату, стандартными инструментами ядра.
Я не говорю, что это кому то нужно. Я говорил, что у меня своя параноя.
Просто увидеть эфективность кода на 10-20 символах тяжело. Потому сделал по больше поток данных, что бы было видно результат.
В моих примерах действительно мало цифр, так как это связано на прямую с /dev/random
Именно из этого источника беруться данные. Плюс, если вы читали статью, из 255 байт около около 150 игнорируються фильтром. Отфильтрированный набор символов из энтропии ядра... Не я генерирую данные, а ядро.
В этом суть поста, что бы не придумывать велосипед, а брать уже готовые данные из ядра. Не писать генераторы, не писать каке то балансиры соотношения символов, цифр, букв..
Я привел три примера, с одной pipe командой, скриптом и утилитой.
Возможно большинству читатилей будет достаточно первой команды... Так как это быстро, эфективно и вообще не требует установки пакетов. Так сказать генератор пароля из коробки на голом ядре.
Остальное по желанию, просто немного развил pipe команду.
Я думал Вы об этом:
https://docs.rs/getrandom/latest/getrandom/
Да, я видел эту библиотеку. Особо не увидел разницы в производительности и решил оставить Reader вместо библиотеки.
Но как я уже сказал, я новичок в Rust. И если мои выводы были ориентированны лишь на скорость. То... Действительно стоило бы дождаться инициализации источника энтропии.
Может мне выкладывать все свои проекты ? Лучший code-review )))
Все, до меня дошло. Вы правы.
Что же, стоит исправить read_buf[..] на read_buf[..n].
А разве объявление
let mut stdout = io::BufWriter::with_capacity(cli.buffer_size, io::stdout().lock());не указывает на то, что при вызове
stdout.write_all(&[charset[idx as usize]])?;данные будут заполнять внутренний буфер, и только при его переполнении выведутся в терминал ?
Имею в виду, какая разница, создать свой буфер, записать в него данные и вызвать write_all с буфером.
Или инициализировать
io::BufWriter::with_capacityс внутренним буфером. И он будет делать то же самое ?Эту проблему я даже не рассматривал. Хотя конечно можно... Использовать слова и их корни, для генерации... У меня пароли хранятся в хранилище, потому, я их в принципе не запоминаю. Разве что мастер пароль помню )
Но... Идея не плохая, как вы думаете ? Если брать слова или корни слов и комбинировать их с цифрами, символами... Будет ли это... Полезно ?
Или можно создавать несуществующие слова, главное что бы чередовались гласные и согласные, для удобства произношения и запоминания...
Так и есть, и смысл теряется, по крайней мере для меня.
Вместо того, что бы сделать минимально нагрузки, берется цитата, конвертируется в base64 (нагрузка), потом еще хешируется (нагрузка), и только потом выдается.
Хотя в действительности достаточно убрать лишние символы.
Немного заморачиваюсь с нагрузкой, приложение на расте выдавало 10 млн симполов за 0.2 секунды, я его оптимизировал, теперь выдает 10 млн за 0.06 секунды. (Еще не отправлял на гит изменения).
Это конечно не имеет большого значения, ибо там у всех 8-10 ядер, много ОЗУ, в принципе люди могут позволить себе писать плохой код...
Но все же мне кажется, что лучше экономить ресурсы... У каждого своя параноя ))))
Очень круто, Вы тоже используете /dev/urandom )))
Я как только об этом узнал, не смог сдержать восторга, сразу решил поделиться с миром вокруг )))
По поводу странной логики.
В данном листинге, на строке 1, цикл while ни как не связан с ни с буфером ввода ни с буфером вывода, он остановится, когда written_total будет >= cli.length.
Далее, я передаю read_buf для заполениня в файловый дискриптор
let n = entropy_source.read(&mut read_buf).
Метод read возвращает реальное количество прочитаннх байт и это n.
Далее это n проверяется, равен ли он 0.
0 я выбрал потому, что если там есть хоть какие то данные, они выведутся на экран, если же данные в /dev/random закончились, будет выведено соответствующее сообщение.
Так как там в проверке есть return.
Что же касается шанса такого развития событий, выше я писал, что :
"В свою очередь
/dev/urandom- бесконечный источник псевдослучайных байт, так как использует CSPRNG на базе/dev/random" - это означает, что используя /dev/urandom, буфер будет заполнен всегда, и только при использовании /dev/random есть вероятность, что буфер не будет заполнен. В таком случае при исчерпании данных - выдаст ошибку.Поправьте меня, если я не прав.
Идея понятна.
Взять текст, конвертировать в base64 строку и посчитать хеш такой строки.
Это будет означать, что хеш всегда одинаковый.
То есть, что бы "пароль" был разный, изначальная "цитата" тоже должна быть разная. Что как бы намекает на то, что нужно придумать цитату... Можно конечно взять текущее время вместо цитаты...
Как молодой юзер хабра, скажу спасибо !)
Это действительно круто. Особенно идея с сервером на Rust.
Я только начал изучать Rust, мне он сильно понравился. А вообще я .NET разработчик...
Много кто пользуется разными инструментами, но я все же за комфорт... Иметь сильный инструмент в любимом редакторе - это кайф, а написать его самому - это круто.
Тут так много коментариев, что в своем особо смысла не вижу.
Раст хороший, автор тупой. Если автор не готов к критике, для чего вообще делать пост. Главное что бы были аргументы.
Зачем выкатывать язык, если много не готово, на взгляд автора. Ответ - потому что это работает. Да, не удобно, да, не красоно, но работает и работает хорошо.
Это банальный синтаксический сахар. Не больше не меньше. Фронтэндеровская тема плакать за синтаксическим сахаром. Ой писать не удобно, что делать...
Язык молод... Вспомните С# 1.0, да даже 4.0... Он сильно отличался от последних версий... И сахара добавили достаточно...
Только вот сколько лет прошло...
Не знаю, никогда не плакал за синтаксисом. Как сделано так сделано. Работает ? Работает быстро. Мне этого достаточно.
Не могу сказать что на С# много всего удобного. Опять же, половины синтаксиса не было раньше...
Врядли мое негодование на хабре вообще как то повлияет на судьбу С#... Разве только если разрабы майков следят за хабром )))
Так что всем добра. С наступающим новым годом.