7

私は、keil microvision IDE で STM32F103E arm cortex-m3 MCU を使用したプロジェクトに取り組んでいます。
何らかの目的で乱数を生成する必要がありますが、標準の C++ ライブラリが生成する疑似乱数を使用したくないため、ハードウェア機能を使用して REAL 乱数を生成する方法が必要ですが、方法がわかりません。できます。
何か案が?(私はソフトウェア エンジニアであり、電子の専門家ではありません。簡単に説明してください :P)

4

4 に答える 4

14

これは私が遭遇したばかりの古い質問ですが、他の回答が満足のいくものではないため、回答したいと思います。

「RSA キーの生成に乱数が必要です。」

これは、PRNG ルーチン (RNG と誤って呼ばれることがあまりにも多い、私のペットの怒り) は受け入れられず、必要なセキュリティを提供しないことを意味します。

外部の真の RNG は受け入れられますが、最も洗練された答えは、真の乱数発生器が組み込まれている STM32F2xx または STM32F4xx マイクロコントローラーに切り替えることです。これは、まさにこのようなアプリケーション向けです。開発には、F1 と任意の PRNG を使用できると思いますが、正しいコンポーネント (確かに ST F4、また、F2 チップは、この質問がされる前から存在していました) が利用可能です。

この回答は、非技術的な理由で受け入れられない場合があります (チップは既に指定されており、OP には必要な機能への入力がありませんでした)。しかし、チップを選択した人は、アプリケーションに必要なオンチップ周辺機器と機能に基づいてチップを選択する必要がありました。 .

于 2014-10-10T19:14:55.383 に答える
10

指摘したように、チップにはハードウェア RNG がありません。

しかし、あなたは自分で転がすことができます。通常のアプローチは、INDEPENDENT クロック間のジッターを測定することです。独立とは、2 つのクロックが異なるクリスタルまたは RC オシレーターによってサポートされており、同じものから派生していないことを意味します。

私は使うだろう:

  • システム クロックから派生した SysTick タイマー/カウンター (MHz 範囲)
  • kHz範囲のRC発振器の1つ

kHz 範囲の RC オシレーターにカウンターをセットアップして、1 秒間に数回割り込みを発生させます。割り込みハンドラーで、SysTick カウンターの現在の値を読み取ります。SysTick が他の目的 (スケジューリング) に使用されるかどうかにかかわらず、下位 5 ビット程度はどうしても予測できません。

これから乱数を取得するには、通常の疑似 RNG を使用します。上記で収集したエントロピーを使用して、疑似 RNG の内部状態を予期せず変更します。キー生成では、一度にすべてのビットを読み取らず、いくつかの変更が発生することを考慮してください。

これに対する攻撃は明らかです。攻撃者が kHz 範囲の RC 発振器を最大 MHz の精度で測定または制御できる場合、ランダム性はなくなります。それが心配な場合は、スマート カードまたはその他のセキュリティ コプロセッサを使用してください。

于 2013-02-10T11:13:27.753 に答える
4

F1シリーズにはRNG(ハードウェア乱数ジェネレーター)がないようです。したがって、唯一のオプションは、疑似乱数を使用するか、外部入力を要求することです(たとえば、人間の手の動きをランダムと見なす場合もあります)。多くの場合、標準C++ライブラリの代わりにいくつかの暗号ライブラリを使用してより良い疑似ランダムを取得します。

于 2013-02-10T10:06:22.243 に答える
3

私が見つけてテストした別の方法があり、非常にうまく機能します。それは真のランダムな 32 ビット数を生成できます。私はその速さを確認したことがありません。数値ごとに数ミリ秒かかる場合があります。方法は次のとおりです。

  • ノイズの多い内部温度を可能な限り高速で読み取り、最大の ADC ノイズを生成します。
  • ほとんどの (すべての?) STM32 チップで使用可能なハードウェア CRC ジェネレーターを介して値を実行します。

数回繰り返すと、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);

}

于 2015-10-11T16:47:48.450 に答える