ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
11 июля
350689 Топик полностью
fk0, легенда (31.08.2012 13:45 - 13:50, просмотров: 160) ответил 3m_пароль_не_помню на как получать случайные числа в микроконтроллере ? нужны ДЕЙСТВИТЕЛЬНО случайные числа хотя бы 9 бит, псевдослучайная последовательность или шум внутреннего ацп недостаточны. Пытался использовать стабилитрон + оу. Результат плохой, современные
У Брюса Шнайера в прикладной криптографии этот вопрос рассмотрен. Далее последует мой плохой пересказ. Нужен какой-то источник случайных данных. Это может быть, например, АЦП. Сам по себе этот источник может быть исключительно плохим ГСЧ, это не слишком важно, важно лишь, чтоб в получаемых от него данных действительно была случайная составлающая. Далее нужен какой-то хеш, сойдёт для примера MD5. Кстати не плохой вариант для 8-битных контроллеров, вопреки повсеместно написанному (MD5 позволяет развернуть циклы и получить достаточно быстрый код, а MD2 несмотря на всё считается в итоге гораздо дольше). И далее, каждый раз, когда нужно получить случайное число (64 бита, например) -- берётся предыдущее число, к нему добавляются плохие случайные данные, считается очередное значение хеша и выдаётся как случайное число. Всё просто. Но есть ньюансы которые лучше почерпнуть в упомянутой литературе. Есть и другие методы. Например, на основе LFSR. Есть неплохой application note у maxim: http://www.maxim-i …otes/index.mvp/id/4400 Конкретная реализация, опять же сожалею об отсутствии src.caxapa.ru, выглядит примерно так: #define PMASK32 0xB4BCD35C #define PMASK31 0x7A5BC2E3 #ifndef PERSISTENT #define PERSISTENT(v) v #endif PERSISTENT(static uint_fast32_t lfsr32); PERSISTENT(static uint_fast32_t lfsr31); static unsigned shift(uint_fast32_t *lfsr, uint_fast32_t mask, uint_fast8_t xor) { uint_fast8_t fb = (*lfsr ^ xor)&1; *lfsr>>=1; if (fb) *lfsr^=mask; return *lfsr; } static unsigned rand_16(void) { shift(&lfsr32, PMASK32, 0); return (shift(&lfsr32, PMASK32, 0) ^ shift(&lfsr31, PMASK31, 0)) & 0xffff; } unsigned long random_get(void) { return rand_16()<<16 | rand_16(); } void random_feed(unsigned r) { do { r=r*31153; shift(&lfsr32, PMASK32, r>>8); shift(&lfsr31, PMASK31, r>>9); } while (lfsr31==0 || lfsr32==0); /* avoid zeroizing LFSR */ } void random_init(void) { if (lfsr32==0) lfsr32=0xABCDE; if (lfsr31==0) lfsr31=0x23456789; } #ifdef RANDOM_TEST #include <stdio.h> int main() { unsigned long n; random_init(); n=65536; do { random_feed(n); printf("%lu\n", random_get()&0xffff); printf("%lu\n", random_get()>>16); } while (--n); return 0; } #endif /* пример из жизни: в качестве источника "плохих случайных данных" * используется датчик температуры: младшие биты там шумят хорошо. */ void randfeed_fsm(void) { if (clock() - T < 10*CLOCKS_PER_SEC) return; T=clock(); adc_once(TEMP_ADC); while(! adc_ready(TEMP_ADC)); random_feed(adc_val[TEMP_ADC]); } PS: да, можно использовать значение таймера аппаратного и т.п. тоже, но если есть уверенность, что какие-либо события относительно времени действительно имеют случайную составляющую. Время нажатия кнопок пользователем, например. Работа же алгоритма (программы) в целом ни разу не случайная и можно получить очень неслучайные результаты... Нельзя, например, считать случайным момент вызова какой-либо функции (той же rand()).
[ZX]