Generator liczb losowych AVR

12

Przeczytałem notatkę z TI ( slaa338 ), która opisuje technikę generowania „rzeczywistych” (w przeciwieństwie do „pseudo”) liczb losowych. Wykorzystuje nieco egzotyczny podsystem zegara MSP430, aby osiągnąć ten cel. Czy ktoś wie o technice, która może być zaimplementowana w AVR (interesuję się w szczególności XMegą) do generowania liczb „rzeczywistych”?

vicatcu
źródło
1
psuedo random działa na gry w kości. Myślę, że chce kryptograficznie bezpieczny.
Kortuk
2
Czy możesz wskazać aplikację i / lub wymagany stopień losowości? Jeśli chodzi o kryptografię, oprócz jakości materiału siewnego istnieją dodatkowe kwestie. Niektóre z już przedstawionych sugestii - na przykład pobieranie próbek danych wejściowych do środowiska różnych typów mogą, ale nie muszą być odpowiednie w zależności od twoich wymagań.
Windell Oskay

Odpowiedzi:

6

Jak źle używasz XMega? Jeśli generowanie liczb kryptograficznych i liczb losowych stanowi dużą część Twojego projektu, seria SecureAVR firmy Atmel ma wbudowany sprzętowy numer losowy i jest przeznaczony do zastosowań kryptograficznych.

Niezależnie od tego wątpię, czy znajdziesz przypadkowe źródło nasion o dobrej dystrybucji. Będziesz chciał uruchomić go kilka razy przez generator pseudolosowych liczb. Jeśli zaczniesz za każdym razem z innym ziarnem, da ci to niezły zestaw liczb losowych. LGC to szybki i łatwy pseudolosowy generator:

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;
} 
Kevin Vermeer
źródło
1
To niesamowite, nie zdawałem sobie sprawy z istnienia linii SecureAVR, dzięki za wskaźnik!
vicatcu
BTW: Jeśli NAPRAWDĘ potrzebujesz bezpieczeństwa, prosta, skuteczna i szybka metoda LCG, którą przedstawiłem, nie jest tym, czego chcesz: Wiele LCG można złamać; po prostu uzyskaj 2-3 wartości z rzędu i podłącz je do generatora LCG z zestawem znanych stałych - to obejmie wszystko na stronie Wikipedii. Dopasowany wzór pozwoli atakującemu przewidzieć, jaki będzie następny numer. Możliwe jest (ale trudniejsze) ustalenie, jakie są stałe z niczego.
Kevin Vermeer
1
@reemrevnivek FYI, Atmel sprzedaje swoją linię SecureAVR ... polecają swoje 32-bitowe procesory ARM, jeśli chcesz kryptograficznych rzeczy, które są zupełnie inną grą pod względem środowiska programistycznego niż AVR. Mają jednak parę z True RNG, może kiedyś z nimi zagram.
vicatcu
7

Podłącz ADC do sprzętowego źródła szumu i użyj oprogramowania do „wybielania” liczb losowych, jeśli to konieczne.

Oto projekt oparty na AVR, który to robi: Mini przenośny generator liczb losowych Leona (mPRNG)

W zależności od tego, jak bezpieczne musi być kryptograficznie, możesz użyć szumu uziemionego wejścia analogowego lub „ wewnętrznego czujnika temperatury ” jako materiału losowego zamiast zewnętrznego sprzętu.

Aktualizacja : Później napisałem program dla Arduino, który używa zegarów układu jako źródła entropii (ADC okazało się bezużyteczne, ponieważ hałaśliwe bity są obcięte), co zainspirowało stworzenie biblioteki Entropy .

W obu przypadkach losowość nie wynika na przykład z samej wartości temperatury, która zmienia się tylko powoli, ale z najmniej znaczących bitów , które zmieniają się losowo od jednego odczytu do następnego. Czytam tę wartość wiele razy, raz dla każdego bitu wyjściowego, przesunięcia bitów i XOR z poprzednim odczytem. XOR prawdziwie losowy bit z nieskorelowanym bitem zachowuje losowość , więc losowość rozprzestrzenia się na wszystkie bity i staje się prawdziwym białym szumem. Szybkość transmisji nie będzie jednak bardzo wysoka, ponieważ otrzymujesz tylko jeden bit mocy wyjściowej na czas akwizycji lub cykl timera. Dzięki metodzie timera uzyskiwałem około 64 bitów / s.

endolit
źródło
5
Nazywanie (mniej lub bardziej prawdziwego) RNG, „-PRNG” jest niefortunne.
Nick T
+1 dla ADC, myślę, że prawdopodobnie szukasz czegoś, co zmienia się z większą częstotliwością niż czujnik temperatury.
Octopus,
1
@Octopus Cóż, nie używasz temperatury jako źródła entropii, używasz hałaśliwych najmniej znaczących bitów, które zmieniają się losowo za każdym razem, gdy czytasz ADC, nawet jeśli temperatura jest stała. Kiedy testowałem na Arduino, te bity zawsze miały wartość 0, więc nie było to wykonalne i zamiast tego musiałem użyć wariacji timera. Na innym MCU, na którym zastosowałem tę metodę, LSB ADC były głośne i użyteczne.
endolith,
3

Kolejną sztuczką w generowaniu losowego materiału siewnego jest policzenie liczby cykli zegara do zdarzenia zewnętrznego. Na przykład, jeśli jest to urządzenie, z którego ma korzystać osoba, policz liczbę cykli zegara, aż naciśnie przycisk „idź”, i użyj go jako losowego ziarna.

davr
źródło
4
Może to nie być bardzo bezpieczne przed atakami z kanału bocznego, ponieważ mogą się włamać, zapewniając kontrolę nad jednym urządzeniem, ale podobnie jak w przypadku całej kryptografii, aplikacja określa wykonalność.
Kortuk
3

Aby upewnić się, że nie uruchomię się ponownie w tej samej sekwencji, używam bajtu somme w eepromie:

#include <avr/eeprom.h>
#include <stdlib.h> // rand

u16  EEMEM randinit; 

int main(void) {
        srand(eeprom_read_word(&randinit));
        eeprom_write_word(&randinit,rand());
        [...]
 }

Daje to całkiem dobrą losowość i nie kosztuje dużo w programie / pamięci.

jojo l'abricot
źródło
2
Czyta bajt 0 za każdym razem. Jakie masz dowody, że ten bajt jest losowy? Jeśli tak, to świetna technika!
Kevin Vermeer
To słowo (w rzeczywistości bajt 0 i 1) będzie losowe, ponieważ przy każdym uruchomieniu inicjuję generator losowy z jego zawartością. Następnie przesyłam go za pomocą nowego rand (). Więc następny init będzie wyglądał losowo od bieżącego ... i tak dalej ... Ale jeśli zresetuję randinit na ffff (lub 0000?), Będę miał tę samą sekwencję randinit! Więc to nie jest idealne. Zapomniałem ostrzeżenia o bezpieczniku, który wymazuje eeprom podczas przesyłania pliku * .hex;)
jojo l'abricot
3

Stworzyłem bibliotekę, która choć oryginalnie zaprojektowana dla Arduino, działa również jako klasa w implementacji C ++ przy użyciu g ++ na avr, ale ostatnio została również przeniesiona do architektury ARM.

Wykorzystuje jitter między zegarem nadzorującym a zegarem systemowym i został przetestowany na wielu różnych układach scalonych (udokumentowane na stronie wiki)

http://code.google.com/p/avr-hardware-random-number-generation/wiki/WikiAVRentropy

Walter Anderson
źródło
2

Czy zastanawiałeś się nad użyciem czegoś takiego jak randomSeed () ? - stosowany w Arduino IDE

Można używać tej funkcji do próbki ruchomy bolec (wolny) analogowego Atmel AVR, to wtedy wykorzystuje się wartość do tworzenia dowolnego punktu wyjścia do pseudo losową funkcją numeru - losowo ().

Wartość utworzona przez random () może być pseudolosową liczbą - ale dowolny punkt początkowy utworzony przez randomSeed () powinien być tak rzeczywistą liczbą losową / wartością, jak to tylko możliwe.

Jim
źródło
2
Próbkowanie rzeczy takich jak piny analogowe jest zbliżone do losowego, ale nie będzie miało równomiernego rozkładu. Przeprowadź jednak ziarno kilka razy losowo i tak się stanie.
Kevin Vermeer
.... przez pseudo losowy generator liczb kilka ... <- Jak to zaginęło? NTS: Najpierw zaangażuj mózg, a potem palce.
Kevin Vermeer
Dokładnie - nie jest też najbezpieczniejszy, jeśli używasz go do szyfrowania / ochrony itp., Ale da ci ładną losową liczbę dla czegoś takiego jak generatywna muzyka lub gry w kości. Jest także dobry i łatwy do wdrożenia :)
Jim
1

Jest artykuł na temat tego, jak to osiągnąć za pomocą sprzętu AVR. Polega na poleganiu na wahaniach zegara. Zasadniczo używasz przerwania timera opartego na jednym źródle zegara, aby próbkować dolne bity osobnego timera, który jest taktowany oddzielnym niezależnym źródłem zegara. Oba zegary będą powiązane z jakimś przypadkowym jitterem, a próbkowanie nie będzie idealnie okresowe.

Zrobiłem mały dowód tego na mikrokontrolerze STM32, kod jest tutaj na github . Otrzymał kilka dobrych wyników w oparciu o zestaw testów losowych.

Moim zdaniem myślę, że jest to lepsze niż próbkowanie pływającego pinu za pomocą ADC, który jest niezwykle łatwy do ataku (przywiązanie pinu do ziemi, a twój numer nie jest już tak losowy!). Jestem pewien, że istnieje sposób na manipulowanie RNG opartym na flukcie zegara, ale to sprawia, że ​​czuję się trochę lepiej, że mogę to zrobić w oparciu o wewnętrzne źródła zegara.

Jon L.
źródło