TIのappnote(slaa338)を読んで、「擬似」ではなく「実数」の乱数を生成する手法について説明しています。この目標を達成するために、MSP430のややエキゾチックなクロックサブシステムを活用します。「実際の」乱数を生成するために、AVR(特にXMegaに興味があります)に実装できる手法を知っている人はいますか?
TIのappnote(slaa338)を読んで、「擬似」ではなく「実数」の乱数を生成する手法について説明しています。この目標を達成するために、MSP430のややエキゾチックなクロックサブシステムを活用します。「実際の」乱数を生成するために、AVR(特にXMegaに興味があります)に実装できる手法を知っている人はいますか?
回答:
XMegaを使用するのはどれほど悪いですか?暗号と乱数の生成がプロジェクトの大きな部分を占める場合、AtmelのSecureAVRシリーズにはハードウェア乱数が組み込まれており、暗号アプリケーション用に設計されています。
とにかく、良い分布を持つランダムなシードソースを見つけることを疑います。疑似乱数ジェネレーターを数回実行する必要があります。毎回異なるシードから開始する限り、これにより素敵な乱数のセットが得られます。LGCは、すばやく簡単な擬似ランダムジェネレーターです。
static unsigned long Seed;
/* Call before first use of NextVal */
unsigned long InitSeed()
{
//Your code for random seed here
// Correct distribution errors in seed
NextVal();
NextVal();
NextVal();
return NextVal();
}
/* Linear Congruential Generator
* Constants from
* "Numerical Recipes in C"
* by way of
* <http://en.wikipedia.org/wiki/Linear_congruential_generator#LCGs_in_common_use>
* Note: Secure implementations may want to get uncommon/new LCG values
*/
unsigned long NextVal()
{
Seed=Seed*1664525L+1013904223L;
return Seed;
}
ADCをハードウェアノイズソースに接続し、必要に応じてソフトウェアを使用して乱数を「ホワイトニング」します。
これを行うAVRベースのプロジェクトを次に示します。Leonのミニポータブルランダムナンバージェネレーター(mPRNG)
暗号化の必要性に応じて、外部ハードウェアの代わりに、接地されたアナログ入力または「内部温度センサー」のノイズをランダム性シードとして使用できます。
更新:後でチップのタイマーをエントロピーソースとして使用するArduino用のプログラムを作成し(ノイズの多いビットが切り捨てられるためADCは役に立たないことが判明しました)、これがEntropyライブラリの作成に影響を与えました。
どちらの場合も、ランダム性は、たとえば温度値自体からのものではなく、ゆっくりと変化するだけでなく、読み取りごとにランダムに変化する最下位ビットからのものです。出力のビットごとに1回、値を複数回読み取り、前の読み取りとビットシフトおよびXORします。 真にランダムなビットと無相関のビットを排他的論理和すると、ランダム性が保持されるため、ランダム性がすべてのビットに広がり、真のホワイトノイズになります。ただし、取得時間またはタイマーサイクルごとに1ビットの出力しか得られないため、ビットレートはそれほど高くありません。タイマー方式では、約64ビット/秒を取得していました。
同じシーケンスで再起動しないようにするには、eepromでsommeバイトを使用します。
#include <avr/eeprom.h>
#include <stdlib.h> // rand
u16 EEMEM randinit;
int main(void) {
srand(eeprom_read_word(&randinit));
eeprom_write_word(&randinit,rand());
[...]
}
これは非常に良いランダムを与え、プログラム/メモリに多くの費用はかかりません。
Arduino用に設計されたオリジナルがavrでg ++を使用するC ++実装のクラスとして機能するライブラリを作成しましたが、実際には最近ARMアーキテクチャにも移植されています。
ウォッチドッグタイマーとシステムクロック間のジッターを利用し、さまざまなチップでテストされています(wikiページに記載)
http://code.google.com/p/avr-hardware-random-number-generation/wiki/WikiAVRentropy
randomSeed()のようなものを使用して見ましたか?-Arduino IDEで使用
この関数を使用して、atmel AVRのフローティング(フリー)アナログピンをサンプリングし、その値を使用して、擬似乱数関数-random()の任意の開始点を作成できます。
random()によって作成された値は、擬似乱数の場合があります-ただし、randomSeed()によって作成された任意の開始点は、取得できる限り実数の乱数/値である必要があります。
AVRハードウェアでこれを達成する方法に関する論文があります。クロックジッターに依存します。基本的に、1つのクロックソースに基づくタイマー割り込みを使用して、独立した独立したクロックソースからクロックされる独立したタイマーの下位ビットをサンプリングします。2つのクロックにはランダムなジッターが関連付けられており、サンプリングは完全に周期的ではありません。
STM32マイクロコントローラーでこれの概念実証を少し行いました。コードはgithubにあります。一連のランダム化テストスイートに基づいて、いくつかの良い結果が得られました。
私の意見では、これは非常に攻撃しやすいADCでフローティングピンをサンプリングするよりも良いと思います(ピンをグランドに接続すると、番号はランダムではなくなります!)。クロックジッタベースのRNGを操作する方法があると確信していますが、オンチップの内部クロックソースに基づいて純粋にこれを行うことができると、少し気分が良くなります。