รับตัวเลขสุ่มอย่างแท้จริงใน Arduino


13

อะไรคือวิธีที่ดีที่สุดในการรับจำนวนสุ่มอย่างแท้จริง (ตรงข้ามกับหลอก) ใน Arduino หรืออย่างน้อยที่สุดก็ประมาณที่ดีที่สุด? จากความเข้าใจของฉันฟังก์ชั่น randomSeed (analogRead (x)) มันไม่สุ่มพอ

หากเป็นไปได้ควรใช้วิธีการตั้งค่า Arduino พื้นฐานเพียงอย่างเดียว (ไม่มีเซ็นเซอร์เพิ่มเติม) โซลูชั่นที่มาพร้อมกับเซ็นเซอร์ภายนอกสามารถใช้ได้หากพวกเขาปรับปรุงการสุ่มอย่างมีนัยสำคัญมากกว่าการตั้งค่าพื้นฐาน


แอปพลิเคชันคืออะไร มันจะต้องปลอดภัยหรือไม่? ตอนนี้คุณกำลังทำอะไรกับการสุ่ม? จากนั้นหากไม่มีชิปภายนอกที่ใช้ TRNG จากแหล่งข้อมูลเอนโทรปีทางกายภาพคุณไม่มีโชค คุณยังสามารถใช้ RNG แบบ determenistic เช่น HMAC DRBG และเมล็ดจากสิ่งคงที่และแหล่งข้อมูลเอนโทรปีคุณภาพต่ำ แต่ก็ยังไม่ปลอดภัยจากการเข้ารหัส
Maximilian Gerhardt

ใช่ฉันต้องการตัวเลขสุ่มสำหรับแอปพลิเคชันที่ปลอดภัยด้วยการเข้ารหัส
Rexcirus

คำตอบ:


10

เอนโทรปีห้องสมุดใช้:

ตัวกระวนกระวายใจตามธรรมชาติของสุนัขเฝ้าบ้านในการผลิตกระแสสุ่มตัวเลขที่เชื่อถือได้จริง

ฉันชอบวิธีนี้เพราะมันไม่ได้ใช้พินของไมโครคอนโทรลเลอร์และไม่ต้องใช้วงจรภายนอก สิ่งนี้ยังทำให้ความล้มเหลวภายนอกน้อยลง

นอกจากห้องสมุดแล้วพวกเขายังให้ภาพร่างที่แสดงให้เห็นถึงการใช้เทคนิคเดียวกับที่ใช้ในการสร้างเมล็ดพันธุ์แบบสุ่มสำหรับ PRNG ของไมโครคอนโทรลเลอร์โดยไม่มีห้องสมุด: https://sites.google.com/site/astudyofentropy/project-definition / ตั้งเวลากระวนกระวายใจเอนโทรปีแหล่งที่มา / เอนโทรปีห้องสมุด / Arduino สุ่มเมล็ด


8

randomSeed(analogRead(x))จะสร้างตัวเลขขึ้นมา 255 ลำดับเท่านั้นซึ่งทำให้มันยากที่จะลองคอมโบทั้งหมดและสร้าง oracle ที่สามารถจับคู่กับเอาต์พุตสตรีมของคุณและทำนายผลลัพธ์ทั้งหมดได้ 100% คุณอยู่ในเส้นทางที่ถูกต้อง แต่เป็นเพียงเกมตัวเลขและคุณต้องการมากกว่านั้น ตัวอย่างเช่นการอ่านอะนาล็อก 100 ครั้งจาก 4 ADCs รวมพวกเขาทั้งหมดและให้อาหารที่randomSeedจะดีกว่ามาก เพื่อความปลอดภัยสูงสุดคุณต้องมีทั้งอินพุตที่ไม่แน่นอนและการผสมที่ไม่สามารถกำหนดได้

ฉันไม่ใช่นักเขียนรหัส แต่ฉันใช้เวลาหลายพันชั่วโมงในการค้นคว้าและสร้างเครื่องกำเนิดไฟฟ้าแบบสุ่มฮาร์ดแวร์และซอฟต์แวร์ดังนั้นให้ฉันแบ่งปันสิ่งที่ฉันได้เรียนรู้:

อินพุตที่คาดเดาไม่ได้:

  • analogRead () (บนหมุดลอย)
  • GetTemp ()

อินพุตที่คาดเดาไม่ได้:

  • micros () (w / a ช่วงเวลาตัวอย่างที่ไม่ได้กำหนดค่า)
  • clock jitter (แบนด์วิธต่ำ แต่ใช้ได้)
  • readVCC () (หากไม่ใช่แบตเตอรี่)

อินพุตที่คาดเดาไม่ได้ภายนอก:

  • เซ็นเซอร์อุณหภูมิความชื้นและความดัน
  • ไมโครโฟน
  • ตัวแบ่งแรงดัน LDR
  • เสียงทรานซิสเตอร์อคติย้อนกลับ
  • เข็มทิศ / กระวนกระวายใจเร่ง
  • สแกนฮอตสปอตไร้สาย esp8266 (ssid, db, ฯลฯ )
  • esp8266 เวลา (งาน wifi พื้นหลังทำให้ micros ที่กำหนดไว้ () นำมาซึ่งไม่แน่นอน)
  • esp8266 HWRNG - RANDOM_REG32รวดเร็วมากและคาดเดาไม่ได้หยุด 1 ครั้ง

การรวบรวม สิ่งสุดท้ายที่คุณต้องการทำคือคายเอนโทรปีออกมา ง่ายกว่าที่จะคาดเดาการพลิกเหรียญมากกว่าการฝากเหรียญ ข้อสรุปเป็นสิ่งที่ดี unsigned long bank;หลังจากbank+= thisSample;นั้นก็ดี มันจะเกลือกกลิ้ง bank[32]ดียิ่งขึ้นอ่านต่อ คุณต้องการรวบรวมตัวอย่างอย่างน้อย 8 ตัวอย่างสำหรับแต่ละชิ้นของผลลัพธ์

การป้องกันการเป็นพิษ หากการให้ความร้อนแก่บอร์ดทำให้เกิดสัญญาณนาฬิกาสั่นมากนั่นเป็นเวคเตอร์การโจมตี เช่นเดียวกันกับการระเบิด RFI ไปยังอินพุต analogRead () การโจมตีทั่วไปอื่น ๆ เพียงแค่ถอดปลั๊กดังนั้นจึงทิ้งเอนโทรปีที่สะสมไว้ทั้งหมด คุณไม่ควรส่งออกหมายเลขจนกว่าคุณจะรู้ว่าปลอดภัยที่จะทำเช่นนั้นแม้จะใช้ความเร็ว

นี่คือเหตุผลที่คุณต้องการให้เอนโทรปีในระยะยาวโดยใช้ EEPROM, SD และอื่น ๆ ดูที่Fortuna PRNGซึ่งใช้ 32 ธนาคารแต่ละแห่งอัพเดทครึ่งหนึ่งบ่อยเท่าที่เคยเป็นมา ทำให้เป็นการยากที่จะโจมตีธนาคารทั้ง 32 แห่งในเวลาที่เหมาะสม

การประมวลผล เมื่อคุณรวบรวม "เอนโทรปี" คุณต้องทำความสะอาดและหย่าจากการป้อนข้อมูลในวิธีที่ยากต่อการย้อนกลับ SHA / 1/256 ดีสำหรับเรื่องนี้ คุณสามารถใช้ SHA1 (หรือแม้กระทั่ง MD5 จริง ๆ ) เพื่อความเร็วเนื่องจากคุณไม่มีช่องโหว่แบบธรรมดา ในการเก็บเกี่ยวอย่าใช้ธนาคาร entopy เต็มรูปแบบและทำการเพิ่ม "เกลือ" ลงในเอาต์พุตที่แตกต่างกันในแต่ละครั้งเพื่อป้องกันผลลัพธ์ที่เหมือนกันเนื่องจากไม่มีการเปลี่ยนแปลงของเอนโทรปี: output = sha1( String(micros()) + String(bank[0]) + [...] );ฟังก์ชัน sha จะซ่อนอินพุตและขาวเอาท์พุท การสะสมต่ำและปัญหาทั่วไปอื่น ๆ

ในการใช้อินพุตไทม์เมอร์คุณต้องกำหนดค่าอินสแตนซ์ นี่เป็นเรื่องง่ายเหมือนdelayMicroseconds(lastSample % 255); ซึ่งหยุดระยะเวลาที่คาดเดาไม่ได้ทำให้นาฬิกา "ต่อเนื่อง" อ่านไม่เหมือนกัน ทำแบบกึ่งประจำเช่นที่if(analogRead(A1)>200){...}จัดไว้ให้ A1 มีเสียงดังหรือติดอยู่กับอินพุตแบบไดนามิก การแยกแต่ละส่วนของการไหลของคุณค่อนข้างยากที่จะตรวจสอบจะป้องกันการเข้ารหัสลับในเอาต์พุตที่แยกส่วน / ฉีกขาด

การรักษาความปลอดภัยที่แท้จริงคือเมื่อผู้โจมตีรู้จักทั้งระบบของคุณและยังไม่มีทางเอาชนะมันได้

สุดท้ายตรวจสอบงานของคุณ รันเอาต์พุตของคุณผ่านENT.EXE (มีให้สำหรับ nix / mac) และดูว่ามันดีหรือไม่ ที่สำคัญที่สุดคือการแจกแจงแบบไคสแควร์ซึ่งโดยปกติควรอยู่ระหว่าง 33% ถึง 66% หากคุณได้รับ 1.43% หรือ 99.999% หรืออะไรทำนองนั้นการทดสอบมากกว่าหนึ่งครั้งในหนึ่งแถวการสุ่มของคุณจะไร้สาระ คุณยังต้องการรายงานเอนโทรปี ENT ที่ใกล้เคียงกับ 8 บิตต่อไบต์มากที่สุด> 7.9 อย่างแน่นอน

TLDR: วิธีป้องกันคนโง่ที่ง่ายที่สุดคือ HWRNG ของ uthe ESP8266 มันรวดเร็วสม่ำเสมอและคาดเดาไม่ได้ เรียกใช้สิ่งนี้บน ESP8266 ที่รัน Ardunio core และใช้ซีเรียลเพื่อพูดคุยกับ AVR:

// ESP8266 Arduino core code:
void setup(){
 Serial.begin(9600); // or whatever
}

void loop() {
  // Serial.write((char)(RANDOM_REG32 % 256)); // "bin"
  Serial.print( String(RANDOM_REG32, HEX).substring(1)); // "hex"
}

** แก้ไข

ที่นี่เป็นกระดานร่าง HWRNG ที่เปลือยเปล่าที่ฉันเขียนไปสักพักใช้งานไม่ได้เป็นแค่นักสะสม แต่ CSPRNG ทั้งหมดแยกออกจากพอร์ตอนุกรม มันถูกสร้างขึ้นสำหรับ pro-mini แต่ควรปรับให้เข้ากับบอร์ดอื่นได้ง่าย คุณสามารถใช้เพียงหมุดอะนาล็อกที่ลอยได้ แต่มันจะเป็นการดีกว่าถ้าคุณเพิ่มสิ่งต่าง ๆ ลงไปมันจะมีสิ่งที่แตกต่างกัน เช่นเดียวกับไมโครโฟน LDRs เทอร์มิสเตอร์ (ตัดให้มีอุณหภูมิสูงสุดถึงอุณหภูมิห้อง) และแม้แต่สายที่ยาว มันค่อนข้างดีใน ENT ถ้าคุณมีเสียงรบกวนปานกลาง

ร่างรวมความคิดหลายอย่างที่ฉันได้กล่าวถึงในคำตอบและความคิดเห็นติดตามของฉัน: การสะสมเอนโทรปีการยืดโดยเอนโทรปีที่มีการสุ่มตัวอย่างน้อยเกินไป (ฟอนนอยมันน์บอกว่ามันเท่ห์) มันลืมการประเมินคุณภาพเอนโทรปีในความโปรดปรานของ "Gimme อะไรที่อาจเป็นไปได้แบบไดนามิก" และการผสมโดยใช้การเข้ารหัสแบบดั้งเดิม

// AVR (ardunio) HWRNG by dandavis. released to public domain by author.
#include <Hash.h> 

unsigned long read[8] = {0, 0, 0, 0, 0, 0, 0, 0};
const int pincount = 9; // adjust down for non pro-mini boards
int pins[9] = {A0, A1, A2, A3, A4, A5, A6, A7, A0}; // adjust for board, name analog inputs to be sampled
unsigned int ticks = 0;
String buff = ""; // holds one round of derivation tokens to be hashed.
String cache; // the last read hash



void harvest() { // String() slows down the processing, making micros() calls harder to recreate
  unsigned long tot = 0; // the total of all analog reads
  buff = String(random(2147483647)) + String(millis() % 999);
  int seed =  random(256) + (micros() % 32);
  int offset =  random(2147483647) % 256;

  for (int i = 0; i < 8; i++) {
    buff += String( seed + read[i] + i + (ticks % 65), HEX );
    buff += String(random(2147483647), HEX);
    tot += read[i];
  }//next i

  buff += String( (micros() + ticks + offset) % 99999, HEX);
  if (random(10) < 3) randomSeed(tot + random(2147483647) + micros()); 
  buff = sha1( String(random(2147483647)) + buff + (micros()%64) + cache); // used hash to uniform output and waste time
  Serial.print( buff ); // output the hash
  cache = buff;
  spin();
}//end harvest()


void spin() { // add entropy and mix
  ticks++;
  int sample = 128;
  for (int i = 0; i < 8; i++) { // update ~6/8 banks 8 times
    read[ read[i] % 8] += (micros() % 128);
    sample = analogRead(  pins[i] ); // a read from each analog pin
    read[ micros() % 8] += ( read[i] % 64 ); // mix timing and 6LSBs from read
    read[i] += sample; // mix whole raw sample
    read[(i + 1) % 8] += random(2147483647) % 1024; // mix prng
    read[ticks % 8] += sample % 16; // mix the best nibble of the read
    read[sample % 8] += read[ticks % 8] % 2147483647; // intra-mix banks
  }

}//end spin()



void setup() {
  Serial.begin(9600);
  delay(222);
  int mx = 2028 + ((analogRead(A0)  + analogRead(A1) + analogRead(A2)  + analogRead(A3)) % 256);  
  while (ticks < mx) {
    spin();
    delay(1);
    randomSeed(read[2] + read[1] + read[0] + micros() + random(4096) + ticks);
  }// wend
}// end setup()



void loop() {
  spin();
  delayMicroseconds((read[ micros() % 8] %  2048) + 333  );
  delay(random(10));
  //if (millis() < 500) return;
  if ((ticks % 16) == (millis() % 16) ) harvest();
}// end loop()

(ฉันสั้นที่ตัวละครที่นี่ขอโทษ.) ภาพรวมที่ดี! ฉันแนะนำให้ใช้เคาน์เตอร์เกลือ micros () เป็นการสิ้นเปลืองบิตเนื่องจากอาจข้ามหลายขั้นตอนระหว่างการโทร หลีกเลี่ยงบิตสูงในอินพุตแบบอะนาล็อก จำกัด ให้น้อยที่สุดหนึ่งหรือสองบิต แม้จะมีการโจมตีเป้าหมายที่ยากต่อการตรึง (เว้นแต่คุณสามารถวางสายบนอินพุต) "การผสมที่ไม่ได้กำหนด" ไม่ใช่สิ่งที่คุณสามารถทำได้ในซอฟต์แวร์ SHA-1 ผสมเป็นมาตรฐาน: crypto.stackexchange.com/a/6232 อินเท ตัวจับเวลาที่คุณเสนอนั้นสุ่มเท่านั้นตามที่คุณมีอยู่แล้ว ไม่ได้รับมากที่นี่
Jonas Schäfer

sha ลดความซับซ้อนและปกป้องเพื่อให้คุณไม่ต้องกังวลเกี่ยวกับจำนวนบิตที่จะคว้าจากอินพุตแบบอะนาล็อกเช่น ลวดสองสามนิ้วที่เชื่อมต่อกับอะนาล็อก (หรือร่องรอยซีพียู pcb) จะแกว่งมากกว่าสองสามบิต การผสมนั้นไม่สามารถกำหนดได้โดยอาศัยเกลือที่ไม่ได้บันทึกและไม่ทราบค่าที่ป้อนเข้าสู่แฮชพร้อมกับตัวอย่างของค่าสะสม micros () ยากที่จะเล่นซ้ำมากกว่าตัวนับโดยเฉพาะเมื่อถูกไล่ออกตามช่วงเวลา
dandavis

1
ผมมีคำถาม. คุณบอกว่าการวัด 100 ครั้งดีกว่า แต่การวัดแบบ "เฉลี่ย" ไม่มากนักที่ จำกัด ประสิทธิภาพของการใช้ข้อมูล "แบบสุ่ม" เหล่านี้หรือไม่ ฉันหมายถึงโดยปกติแล้วคุณมักจะได้รับการวัดที่มีเสียงรบกวนน้อยลง (น้อยลง "สุ่ม") ...
frarugi87

ผมแนะนำการสุ่มตัวอย่างอย่างต่อเนื่องผมแค่บอกว่า 100 ดีกว่า 1 เพราะมันมีชุดค่าผสมมากกว่า รูปแบบการสะสมเช่น Yarrow / Fortuna ยังดีกว่าอย่างมาก พิจารณาการต่อเชื่อม (ไม่ใช่ข้อสรุป) ตัวอย่างอะนาล็อก 100 ตัวอย่างก่อนการแฮช แข็งแกร่งขึ้นเพราะมันทำให้การสั่งซื้อตัวอย่างมีความสำคัญและการเป็นหนึ่งชาร์ตทำให้แฮชแตกต่างกันโดยสิ้นเชิง ดังนั้นแม้ว่าจะมีค่าเฉลี่ยตัวอย่างที่จะได้รับเสียงรบกวนน้อยลงผู้โจมตีจะต้องใช้คำต่อคำท่องทุกค่าหรือไม่ตรงกัน ... ประเด็นหลักของฉันคือ "สะสมผสมและตรวจสอบ" มากกว่าเรียกร้องแหล่งเสียงที่เฉพาะเจาะจง
dandavis

4

จากประสบการณ์ของฉันanalogRead()บนขาลอยมีเอนโทรปีต่ำมาก บางทีการสุ่มหนึ่งหรือสองบิตต่อการโทรหนึ่งครั้ง คุณต้องการสิ่งที่ดีกว่าอย่างแน่นอน ตัวกระวนกระวายใจของสุนัขเฝ้าบ้านตามที่เสนอในคำตอบของ per1234 เป็นทางเลือกที่ดี อย่างไรก็ตามมันสร้างเอนโทรปีในอัตราที่ค่อนข้างช้าซึ่งอาจเป็นปัญหาหากคุณต้องการเมื่อโปรแกรมเริ่มทำงาน dandavis มีข้อเสนอแนะที่ดีอยู่บ้าง แต่โดยทั่วไปแล้วพวกเขาต้องการ ESP8266 หรือฮาร์ดแวร์ภายนอก

มีแหล่งข้อมูลเอนโทรปีหนึ่งที่น่าสนใจที่ยังไม่ได้กล่าวถึง: เนื้อหาของแรมที่ไม่ได้กำหนดค่าเริ่มต้น เมื่อ MCU เปิดใช้งานแล้วบิตแรมบางส่วน (ที่เกิดขึ้นจะมีทรานซิสเตอร์แบบสมมาตรมากที่สุด) เริ่มทำงานในสถานะสุ่ม ตามที่กล่าวไว้ใน บทความของแฮ็กกาเดย์นี้สามารถใช้เป็นแหล่งข้อมูลเอนโทรปีได้ มันพร้อมใช้งานในการบูตแบบเย็นเท่านั้นดังนั้นคุณสามารถใช้มันเพื่อเติมพูลเอนโทรปีเริ่มต้นซึ่งคุณจะเติมเต็มจากแหล่งอื่นซึ่งอาจช้า วิธีนี้โปรแกรมของคุณสามารถเริ่มทำงานได้โดยไม่ต้องรอให้พูลเติมเต็มอย่างช้าๆ

นี่คือตัวอย่างของวิธีการนี้สามารถเก็บเกี่ยวได้บน Arduino ที่ใช้ AVR โค้ดด้านล่าง XORs srandom()แรมทั้งเพื่อสร้างเมล็ดพันธุ์ที่ได้ในภายหลังฟีดไป ส่วนที่ยุ่งยากคือการเก็บเกี่ยวจะต้องทำก่อนที่ C runtime จะเริ่มต้นส่วนหน่วยความจำ. data และ. bs จากนั้นเมล็ดจะต้องได้รับการบันทึกในที่ที่ C runtime จะไม่เขียนทับ นี้จะกระทำโดยใช้เฉพาะ ส่วนหน่วยความจำ

uint32_t __attribute__((section(".noinit"))) random_seed;

void __attribute__((naked, section(".init3"))) seed_from_ram()
{
    const uint32_t * const ramstart = (uint32_t *) RAMSTART;
    const uint32_t * const ramend   = (uint32_t *) RAMEND;
    uint32_t seed = 0;
    for (const uint32_t *p = ramstart; p <= ramend; p++)
        seed ^= *p;
    random_seed = seed;
}

void setup()
{
    srandom(random_seed);
}

โปรดทราบว่าในการรีเซ็ตแบบอบอุ่น SRAM จะถูกเก็บรักษาไว้ดังนั้นจึงยังคงมีเนื้อหาทั้งหมดของพูลเอนโทรปีของคุณ รหัสเดียวกันนี้สามารถใช้เพื่อรักษาเอนโทรปีที่เก็บรวบรวมไว้ระหว่างการรีเซ็ต

แก้ไข : การแก้ไขปัญหาในรุ่นแรกของฉันseed_from_ram()ที่ทำงานบนโลกแทนการใช้ในท้องถิ่นrandom_seed seedสิ่งนี้สามารถนำไปสู่เมล็ดที่ถูกแฮคเกอร์ด้วยตัวเองทำลายเอนโทรปีที่เก็บเกี่ยวได้ทั้งหมด


เยี่ยมมาก! ฉันจะขโมยได้ไหม Re: พิน: ไม่ทราบหนึ่งหรือสองบิตก็เพียงพอแล้วหากใช้ถูกต้อง เท่านั้นที่จะ จำกัด ความเร็วในการส่งออกของความลับที่สมบูรณ์แบบ (yuck) แต่ไม่ได้เป็นความลับการคำนวณที่เราต้องการ ...
dandavis

1
@dandavis: ใช่คุณสามารถใช้ซ้ำได้อย่างแน่นอน คุณถูกต้องเกี่ยวกับanalogRead()การใช้งานถ้าคุณรู้ว่าคุณกำลังทำอะไรอยู่ คุณเพียงแค่ต้องระวังอย่าประเมินค่าแบบสุ่มสูงเกินไปเมื่ออัพเดตค่าเอนโทรปีของพูลของคุณ จุดของฉันเกี่ยวกับการanalogRead()มีความหมายส่วนใหญ่เป็นคำวิจารณ์ของยังไม่ดีมักจะซ้ำ“สูตร” : randomSeed(analogRead(0)) เพียงครั้งเดียวในsetup()และถือว่ามันพอ
Edgar Bonet

หากanalogRead(0)มีเอนโทรปี 1 บิตต่อการโทรหนึ่งครั้งการโทรซ้ำ ๆ จะให้ผลตอบแทน 10,000/8 = 1.25 KBytes / วินาทีของเอนโทรปี 150 เท่าของเอนโทรปี
Dmitry Grigoryev

0

หากคุณไม่ต้องการเอนโทรปีจริงๆและต้องการได้รับตัวเลขสุ่มหลอกที่แตกต่างกันในทุกการเริ่มต้นคุณสามารถใช้ EEPROM เพื่อวนซ้ำผ่านเมล็ดติดต่อกัน ในทางเทคนิคแล้วกระบวนการจะกำหนดอย่างสมบูรณ์ แต่ในทางปฏิบัติมันดีกว่าrandomSeed(analogRead(0))พินที่ไม่เชื่อมต่อซึ่งจะทำให้คุณเริ่มต้นด้วยเมล็ดพันธุ์เดียวกันทั้ง 0 หรือ 1,023 การประหยัดเมล็ดพันธุ์ต่อไปใน EEPROM จะรับประกันได้ว่าคุณจะเริ่มต้นด้วย เมล็ดแต่ละครั้ง

#include <EEPROM.h>

const int seed_addr = 0;
unsigned long seed;

void setup() {
    seed = EEPROM.read(seed_addr);
    EEPROM.write(seed_addr, seed+1);
    randomSeed(seed);
}

หากคุณต้องการเอนโทรปีของจริงคุณสามารถรวบรวมได้จากการเลื่อนนาฬิกาหรือโดยการขยายเสียงภายนอก และหากคุณต้องการเอนโทรปีจำนวนมากเสียงจากภายนอกเป็นทางเลือกเดียวที่ทำงานได้ Zener diode เป็นตัวเลือกยอดนิยมโดยเฉพาะถ้าคุณมีแหล่งจ่ายแรงดันสูงกว่า 5-6V (มันจะทำงานกับ 5V เช่นเดียวกันกับ Zener diode ที่เหมาะสม แต่จะทำให้เอนโทรปีน้อยลง):

ป้อนคำอธิบายรูปภาพที่นี่

( แหล่งที่มา )

เอาท์พุทแอมพลิฟายเออร์จะต้องเชื่อมต่อกับขาอะนาล็อกซึ่งจะสร้างเอนโทรปีหลายบิตโดยแต่ละanalogRead()ค่ามีค่าสูงสุดถึงสิบ MHz (เร็วกว่า Arduino สามารถสุ่มตัวอย่างได้)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.