Я работаю над проектом с STM32F103E arm cortex-m3 MCU в Keil Microvision IDE.
Мне нужно генерировать случайные числа для некоторых целей, но я не хочу использовать псевдослучайные числа, которые генерируют стандартные библиотеки c ++, поэтому мне нужен способ генерировать РЕАЛЬНЫЕ случайные числа с использованием аппаратных функций, но я не знаю, как Я могу сделать это.
Любая идея? (Я инженер-программист & не электронный профессионал, поэтому, пожалуйста, опишите это просто: P)
Как уже указывалось, чип не имеет аппаратного RNG.
Но вы можете свернуть свои собственные. Обычный подход заключается в измерении джиттера между независимыми часами. Независимость означает, что эти два часа поддерживаются разными Christals или RC-генераторами и не являются производными от одного и того же.
Я хотел бы использовать:
Установите счетчик на RC-генераторе в кГц-диапазоне, чтобы прерывать его несколько раз в секунду. В обработчике прерываний вы читаете текущее значение счетчика SysTick. Независимо от того, используется ли SysTick для других целей (планирование), младшие 5 или около того битов непременно непредсказуемы.
Для получения случайных чисел используйте обычный псевдо-ГСЧ. Используйте собранную выше энтропию, чтобы непредсказуемо изменить внутреннее состояние псевдо-ГСЧ. Для генерации ключей не читайте все биты одновременно, но допускайте пару мутаций.
Атаки против этого очевидны: если злоумышленник может измерить или контролировать RC-генератор в кГц-диапазоне с точностью до МГц, случайность исчезнет. Если вас это беспокоит, используйте смарт-карту или другой сопроцессор безопасности.
Это старый вопрос, с которым я только что столкнулся, но я хочу ответить, потому что другие ответы меня не удовлетворяют.
«Мне нужны случайные числа для генерации ключа RSA».
Это означает, что подпрограмма ГСЧ (слишком часто ошибочно называемая ГСЧ, моя любимая мозоль) является НЕПРИЕМЛЕМОЙ и не обеспечивает желаемой безопасности.
Внешний истинный RNG приемлем, но самый элегантный ответ — перейти на микроконтроллер STM32F2xx или STM32F4xx, который имеет встроенный генератор случайных чисел TRUE, предназначенный именно для таких приложений, как этот. Для разработки, я полагаю, вы могли бы использовать thr F1 и любой PRNG, но соблазн был бы «это работает, давайте отправим его», прежде чем использовать настоящий RNG, отправляя неисправный продукт, когда компонент RIGHT (конечно, ST F4, и я думаю, также чипы F2 были вокруг, так как до того, как этот вопрос был задан) доступен.
Этот ответ может быть неприемлемым по нетехническим причинам (микросхема уже была указана, у ОП не было ввода необходимых функций), но тот, кто выбрал микросхему, должен был выбрать ее, исходя из того, какие встроенные периферийные устройства и функции необходимы для приложения. ,
Серия F1, похоже, не имеет RNG (аппаратного генератора случайных чисел), поэтому ваши единственные варианты — использовать псевдораслучения или запрашивать внешний ввод (некоторые считают, например, случайное движение человеческой руки). Вы часто получаете лучшие псевдо-случайные числа, используя некоторую криптографическую библиотеку вместо стандартных библиотек C ++.
Есть еще один метод, который я нашел и протестировал, который работает довольно хорошо. Он может генерировать истинные случайные 32-битные числа, я никогда не проверял, насколько это быстро, может занимать несколько миллисекунд на число. Вот как это происходит:
Повторите несколько раз, я обнаружил, 8 раз дает довольно хорошую случайность. Я проверил случайность, отсортировав выходные значения в порядке возрастания и нанеся их на график в Excel, с хорошими случайными числами это генерирует прямую линию, плохая случайность или «слипание» определенных чисел сразу же видно.
Вот код для STM32F03:
uint32_t getTrueRandomNumber(void) {
ADC_InitTypeDef ADC_InitStructure;
//enable ADC1 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// Initialize ADC 14MHz RC
RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
RCC_HSI14Cmd(ENABLE);
while (!RCC_GetFlagStatus(RCC_FLAG_HSI14RDY))
;
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO; //default
ADC_Init(ADC1, &ADC_InitStructure);
//enable internal channel
ADC_TempSensorCmd(ENABLE);
// Enable ADCperipheral
ADC_Cmd(ADC1, ENABLE);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN) == RESET)
;
ADC1->CHSELR = 0; //no channel selected
//Convert the ADC1 temperature sensor, user shortest sample time to generate most noise
ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor, ADC_SampleTime_1_5Cycles);
// Enable CRC clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
uint8_t i;
for (i = 0; i < 8; i++) {
//Start ADC1 Software Conversion
ADC_StartOfConversion(ADC1);
//wait for conversion complete
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) {
}
CRC_CalcCRC(ADC_GetConversionValue(ADC1));
//clear EOC flag
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
}
//disable ADC1 to save power
ADC_Cmd(ADC1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);
return CRC_CalcCRC(0xBADA55E5);
}