Introducere

Generarea numerelor aleatoare are o serie de aplicații în criptografie, testarea sistemelor, debugging, trageri la sorți, jocuri RPG, în general situații în care sunt de preferat evenimente imprevizibile. Pentru acest scop se folosesc fie numere pseudoaleatoare (cum sunt cele întoarse de funcția rand(), de exemplu), sau numere produse de un generator hardware (true random numbers). Dezavantajul primelor este că, în unele condiții, se poate afla următorul număr generat aleator chiar dacă nu se cunoaște seed-ul sau algoritmul, analizând secvența de numere.

Generatoarele de numere aleatoare hardware nu sunt influențate de evenimente macroscopice, și de aceea sunt utile în aplicații în care securitatea este vitală (generarea de chei publice sau de chei de sesiune) Ele folosesc ca suport pentru generare un fenomen fizic microscopic: se pot servi, de exemplu, de zgomotul produs de diverse fenomene electrice, de descompunerea radioactivă, de zgomot atmosferic sau de fenomene cuantice.

Mi-am propus să realizez un astfel de generator de numere aleatoare, folosind ca sursă de zgomot o joncțiune PN polarizată invers.

Descriere generală

Sursa de zgomot va produce tensiuni mici variabile. Ele vor fi amplificate și apoi, cu ajutorul unui inversor, transformate în impulsuri digitale. Impulsurile vor fi citite de microcontroller, unde vor fi folosite ca suport pentru obținerea unei secvențe de biți random. Aceasta va fi prelucrată mai departe pentru a elimina diversele neajunsuri impuse de sursa de zgomot, obținând byte stream-ul final.

Webserver-ul va primi cereri de numere aleatoare și se va folosi de byte stream pentru a răspunde la ele.

Hardware Design

Generarea de numere aleatoare:

Schema 1:

  • 3 tranzistor 2N3904
  • 2 rezistențe 4k7
  • 1 rezistență 10k
  • 1 capacitate 100nF

schema1.jpg

Circuitul folosește ca sursă de zgomot jonctiunea BE a primului tranzistor, polarizată invers, iar tranzistorii 2 și 3 amplifică zgomotul joncțiunii.

Am realizat montajul de mai sus, am conectat circuitul pe un input de ADC de la microcontroller și am făcut sampling la diverse intervale de timp (cu ajutorul timerului 1). Am alimentat întâi direct de la un adaptor (are tensiunea nominală de 12V, dar output-ul real e cam de 17V) dar se vedeau variațiile de tensiune de pe alimentare și nu zgomotul. Apoi am folosit un stabilizator de 12V și nu am detectat variații semnificative ale tensiunii (chiar și după amplificarea dată). Am decis să încerc și o altă schemă.

Schema 2:

  • 1 hex inverter 74HCT04
  • 2 tranzistori 2N3904
  • 2 rezistențe 1M
  • 1 rezistență 10k
  • 1 rezistență 15k
  • 2 capacități 100nF

schema2.jpg

Această schemă folosește tot un tranzistor pentru generarea noise-ului, dar pentru amplificare folosește inversoare aduse în zona liniară cu ajutorul unor rezistențe de valoare foarte mare. Ultimul inversor nu e folosit ca amplificator; rolul lui e de a prelua spike-urile din noise-ul amplificat de celelalte două și de a le aduce la 5V.

Schema originală era cu inversoare TTL și rezistențe de 2.7k în paralel dar mi s-au părut prea mici; am simulat un inversor CMOS cu o rezistență de 1M în paralel și avea o amplificare cam de 150x, deci asta am folosit și eu.

Circuitul integrat e alimentat la 5V, iar restul direct de la adaptor (tensiunea e folosită doar pentru polarizarea inversă deci e bine să fie cât mai mare, și nu se regăsește pe ieșire).

Această schemă a funcționat din prima, cam la orice sample rate genera spike-uri de 5V la intervale de timp neregulate.

Interfatarea cu ATMEGA16:

Am conectat iesirea ultimului inversor la pinul ADC5 (PA5) al microcontrollerului.

Interfatarea ENC28J60:

  • 1 controller ethernet ENC28J60
  • 1 stabilizator 3.3V
  • 2 leduri
  • 1 capacitate 10uF
  • 1 mufa mama RJ45
  • 1 cuarț 20MHZ (n-am gasit de 25)
  • rezistențe

schema_eth.jpg

Am realizat montajul conform datasheet-ului și am conectat pinii SPI la microcontroller. Se execută funcțiile de inițializare din laboratorul 6, și led-ul A pâlpâie dar nu are link.

Va trebui să scad viteza de generare a numerelor random pentru a nu încurca funcționarea webserverului.

Software Design

Programare: PonyProg 2000 Conectare pe interfața serială: minicom

Am folosit interfața serială pentru a verifica output-ul generatorului (9600 baud, 8 biți de date, 2 biți de stop). Am salvat un fișier de 29k cu random bytes pentru analiză, cu minicom -C (capture file)

Prelucrarea noise-ului:

Pentru fiecare succesiune de măsurători LOW-HIGH-HIGH-…-HIGH-LOW, am considerat un spike.

În varianta finală a algoritmului (vezi Jurnal pentru variante intermediare), am folosit o rată de sampling de 8MHZ (Timer1 fără prescaling și OCR1A = 1) pentru a citi intrarea ADC a microcontrollerului și a detecta spike-uri. Pentru obținerea unui bit random, am folosit paritatea numărului de măsurări între două spike-uri succesive (la fiecare măsurare, se incrementează un contor, iar când se detectează un spike, se generează bitul contor % 2 după care se resetează contorul). Viteza de generare cu această metodă s-a dovedit a fi foarte bună (cam 20 bytes/sec), iar distribuția numerelor este suficient de uniformă pentru a nu fi nevoie de aplicarea unui algoritm de debiasing.

Pentru codul final și câteva progrămele de analiza output-ului, vezi secțiunea Download.

Webserver-ul

Nu am mai ajuns acolo.

Probleme

Încă de la început, curentul prin circuit era de câteva zeci de mA (stabilizatorul se încălzea foarte tare) dar nu am reușit să îmi dau seama de ce (am încercat să fac debug, să înlocuiesc capacități / tranzistoare / microcontrollerul / alte integrate, dar degeaba). L-am lăsat așa cât timp am făcut partea de generare a numerelor aleatoare. După ce am lipit enc28j60, în timp ce integram codul webserverului, s-a ars microcontrollerul - doar partea de ADC (măsura 5V orice i-aș fi pus acolo), USART încă mergea. Am cumpărat alt microcontroller pe care mergeau timerele dar nu și interfațarea serială (exact cu codul vechi despre care știam că era corect pentru că mergea pe microcontrollerul semi-ars). Pentru că n-am putut să îl fac să scoată output pe serială, nu aveam cum să-mi dau seama dacă merge ADC-ul (nu că mi-ar fi folosit la mare lucru). Am împrumutat un microcontroller care mergea și am mai încercat o dată să îmi dau seama care e cauza curentului mare dar nu am reușit, și am renunțat.

Rezultate Obţinute

Experiență.

schema_toata.jpg

Concluzii

Se poate face destul de simplu acasă un generator hardware de numere aleatoare, cu piese comune, dar partea dificilă este a-l face fiabil și a-l calibra astfel încât să aibă o viteză decentă de generare și să obțină rezultate bune la testele de randomness. E nevoie și de mai mult timp pentru a-l testa (pentru a obține un output suficient de mare încât să fie relevant).

Download

Jurnal

23.05

  • am căutat diverse variante de surse de randomness și cum s-ar folosi

24.05

  • am cumpărat o parte din piese (erau Rusaliile, la Syscom era închis și n-am găsit nici enc28j60, nici hex inverter)
  • am început să experimentez cu prima variantă de generator de zgomot dar nu am reușit să scot nimic din ea

25.05

  • am cumpărat restul de piese și am făcut a doua schemă (cu inversorul integrat)
  • am obținut variații în output dar măsuram mult prea rar (cam o dată pe secundă) și nu am obtinut nimic concret

26.05

  • am încercat diverse viteze de sampling
  • am nimerit până la urmă o viteză suficient de mare și am obținut prima dată spike-uri random

27.05

  • am încercat (fără succes) să rezolv problema curentului mare

28.05: algoritmul de conversie

  • am pornit de la algoritmul de aici : pentru un număr fix de sampling-uri (cnt = 100) cu o rată de sampling [OCR1A = 100, prescaling = clk/1024], numărul de spike-uri întâlnite % 2 ⇒ un bit random. Pentru aceste valori, aveam cam 5-13 spike-uri pentru cnt sampling-uri; ponderea 0-1 era aproximativ egală dar viteza de generare era foarte mică.
  • am crescut rata de sampling la [OCR1A = 5, prescaling = clk/1024] pentru a mări viteza; numărul de spike-uri era aproximativ același. Am grupat biții câte 4 și am calculat proporțiile de cifre hexazecimale care se generau, dar am descoperit că bias-ul era foarte mare (unele nu apăreau deloc, iar altele foarte mult).
  • pentru a elimina problema asta, am aplicat algoritmul John von Neumann (pentru fiecare pereche de biți, dacă sunt identici îi ignoră, dacă sunt 01 consideră un 0, iar dacă sunt 10 consideră un 1); a scăzut mult viteza de generare, dar proporția 0-1 era bună
  • pentru a aduce viteza la ordinul zeci de bytes / secundă, am încercat să nu mai folosesc numărarea spike-urilor, ci să folosesc direct output-ul circuitului de generare la sample rate maxim (fără prescaling, OCR1A = 1) împreună cu algoritmul von Neumann (output-ul pur era, teoretic, de forma 00000111000000000111000000). Am grupat biții în octeți și am observat că 85 (01010101) și 170 (10101010) apar foarte des, pentru că se detectau alternativ fronturile crescătoare și descrescătoare ale spike-urilor, dar viteza de generare era foarte mare, deci eram pe drumul cel bun
  • urmărind o idee de aici, am încercat ca, păstrând rata maximă de sampling, să număr ciclii de ceas între două spike-uri succesive și să folosesc paritatea acelui număr pentru a produce biți random. Deoarece intervalele de timp între două spike-uri erau suficient de mari și uniform distribuite, nu a mai fost nevoie de algoritmul von Neumann, ceea ce a adus rata finală de generare la 20 bytes / secundă; am păstrat aceasta ca variantă finală a algoritmului
  • am vrut să supun output-ul generatorului unor teste de randomness (vezi Resurse), dar testele necesitau un stream de 10-12 milioane de bytes și obținerea unui output de asemenea dimensiuni ar fi luat cam o săptămână.

29.05

  • am lipit controllerul de ethernet și piesele adiționale, conform datasheet-ului și schemei de la Embedded web server (vezi Resurse)
  • am încercat fără succes să obțin link

30.05

  • cred că am ars microcontrollerul, nu mai merge ADC-ul

31.05

  • am renunțat la continuarea proiectului (cel puțin deocamdată) (vezi Probleme)

Bibliografie/Resurse

pm/prj2010/dtudose/my_rng.txt · Last modified: 2021/04/14 17:07 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0