randomSeed(analogRead(x))
केवल संख्याओं के 255 अनुक्रमों का उत्पादन करेगा, जो सभी कॉम्बो की कोशिश करने के लिए तुच्छ बनाता है और एक आउटपुट पैदा करता है जो आपके आउटपुट स्ट्रीम में जोड़े जा सकता है, सभी आउटपुट 100% की भविष्यवाणी करता है। आप हालांकि सही रास्ते पर हैं, यह सिर्फ एक नंबर का खेल है, और आपको उनमें से बहुत कुछ चाहिए। उदाहरण के लिए, 4 एडीसी से 100 एनालॉग रीडिंग लेना, उन सभी को समेटना, और खिलाना जो randomSeed
बहुत बेहतर होगा। अधिकतम सुरक्षा के लिए, आपको अप्रत्याशित इनपुट और गैर-नियतात्मक मिश्रण दोनों की आवश्यकता होती है।
मैं एक क्रिप्टोग्राफर नहीं हूं, लेकिन मैंने हार्डवेयर और सॉफ़्टवेयर यादृच्छिक जनरेटर पर शोध और निर्माण करने में हजारों घंटे बिताए हैं, इसलिए मुझे जो कुछ मैंने सीखा है उसे साझा करने दें:
अप्रत्याशित इनपुट:
- analogRead () (फ्लोटिंग पिन पर)
- GetTemp ()
संभावित अप्रत्याशित इनपुट:
- माइक्रो () (डब्ल्यू / एक गैर-नियतात्मक नमूना अवधि)
- घड़ी घबराना (कम बैंडविड्थ, लेकिन प्रयोग करने योग्य)
- readVCC () (यदि बैटरी चालित नहीं है)
बाहरी अप्रत्याशित इनपुट:
- अस्थायी, आर्द्रता और दबाव सेंसर
- माइक्रोफोन
- LDR वोल्टेज डिवाइडर
- रिवर्स-बायस ट्रांजिस्टर शोर
- कम्पास / त्वरण घबराना
- esp8266 वाईफाई हॉटस्पॉट स्कैन (ssid, db, आदि)
- एस्प 8266 समय (पृष्ठभूमि वाईफ़ाई कार्य शेड्यूल किए गए माइक्रोक्रेट्स बनाते हैं)
- esp8266 HWRNG -
RANDOM_REG32
पूरी तरह से तेज और अप्रत्याशित, 1-स्टॉप
एकत्रित
आखिरी बात आप क्या करना चाहते है साथ आता है बाहर एन्ट्रापी थूक है। सिक्कों की एक बाल्टी की तुलना में एक सिक्का फ्लिप करना आसान है। सममिंग अच्छी है। unsigned long bank;
फिर बाद bank+= thisSample;
में अच्छा है; यह लुढ़क जाएगा। bank[32]
और भी बेहतर है, पर पढ़ें। आप आउटपुट के प्रत्येक भाग के लिए इनपुट के कम से कम 8 नमूने एकत्र करना चाहते हैं, आदर्श रूप से बहुत अधिक।
विषाक्तता से बचाव
अगर बोर्ड को गर्म करने से एक निश्चित अधिकतम घड़ी घबराहट होती है, तो यह एक हमला वेक्टर है। RFR को analogRead () इनपुट की ओर नष्ट करने के साथ ही। एक और आम हमला बस यूनिट को अनप्लग करना है ताकि सभी संचित एन्ट्रॉपी को डंप किया जा सके। आपको संख्याओं का उत्पादन तब तक नहीं करना चाहिए जब तक कि आपको पता न हो कि ऐसा करना सुरक्षित है, यहां तक कि गति की कीमत पर भी।
यही कारण है कि आप EEPROM, SD, आदि का उपयोग करते हुए दीर्घावधि के आस-पास कुछ एन्ट्रापी रखना चाहते हैं, Fortuna PRNG में देखें , जो कि 32 बैंकों का उपयोग करता है, प्रत्येक एक आधे अपडेट किया गया है, जो कि पहले एक था। जिससे उचित समय में सभी 32 बैंकों पर हमला करना मुश्किल हो जाता है।
प्रसंस्करण
एक बार जब आप "एन्ट्रॉपी" एकत्र करते हैं, तो आपको इसे साफ करना होगा और इसे इनपुट से हार्ड-टू-रिवर्स तरीके से तलाक देना होगा। SHA / 1/256 इसके लिए अच्छा है। जब से आपके पास एक प्लेटेक्स्ट भेद्यता नहीं है, आप गति के लिए SHA1 (या यहां तक कि एमडी 5 वास्तव में) का उपयोग कर सकते हैं। कटाई करने के लिए, कभी भी पूर्ण एन्ट्रापी बैंक का उपयोग न करें, और ALWAYS ALWAYS आउटपुट में एक "नमक" मिलाते हैं जो कि हर बार अलग-अलग समान आउटपुट को रोकने के लिए दिया जाता है ताकि कोई एंट्रॉपी बैंक परिवर्तन न हो: output = sha1( String(micros()) + String(bank[0]) + [...] );
शेक फ़ंक्शन दोनों इनपुट और वाइटन्स आउटपुट को छुपाता है, कमजोर बीज की रक्षा करता है। कम संचित प्रवेश, और अन्य सामान्य मुद्दे।
टाइमर इनपुट का उपयोग करने के लिए, आपको उन्हें अनिश्चितकालीन बनाने की आवश्यकता है। यह एक सरल है delayMicroseconds(lastSample % 255)
; जो अप्रत्याशित समय को रोक देता है, जिससे "क्रमिक" घड़ी अंतर में गैर-समान हो जाती है। ऐसा करें कि अर्ध-नियमित रूप से, जैसे कि if(analogRead(A1)>200){...}
A1 एक शोर है या एक गतिशील इनपुट से जुड़ा हुआ है। आपके प्रवाह के प्रत्येक कांटे को निर्धारित करना मुश्किल है, यह विघटित / चीरने वाले आउटपुट पर क्रिप्टोकरंसी को रोक देगा।
वास्तविक सुरक्षा तब है जब हमलावर आपके पूरे सिस्टम को जानता है और इसे दूर करने के लिए अभी भी असहाय है।
अंत में, अपने काम की जाँच करें। ENT.EXE (nix / mac के लिए भी उपलब्ध) के माध्यम से अपना आउटपुट चलाएँ और देखें कि क्या यह कोई अच्छा है। सबसे महत्वपूर्ण ची वर्ग वितरण है, जो आमतौर पर 33% और 66% के बीच होना चाहिए। अगर आपको 1.43% या 99.999% या ऐसा कुछ नुकीला मिलता है, जो एक पंक्ति में एक से अधिक परीक्षण करता है, तो आपका रैंडम बकवास है। आप यह भी चाहते हैं कि एंट्रॉपी ईएनटी रिपोर्ट 8 बिट प्रति बाइट के करीब हो,> 7.9 निश्चित रूप से।
TLDR: सबसे सरल मूर्खतापूर्ण तरीका है ESP8266 का HWRNG। यह तेज़, एकसमान और अप्रत्याशित है। ESP8266 पर इस तरह से कुछ चलाएं कि अर्दीनियो कोर चल रहा है, और 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 सीरियल पोर्ट से बाहर थूक रहा था। यह एक मिनी के लिए बनाया गया है, लेकिन आसानी से अन्य बोर्डों के लिए अनुकूल होना चाहिए। आप सिर्फ फ्लोटिंग एनालॉग पिन का उपयोग कर सकते हैं, लेकिन उनमें सामान जोड़ना बेहतर है, अधिमानतः अलग चीजें। माइक्रोफोन की तरह, LDRs, थर्मिस्टर्स (कमरे के अस्थायी के आसपास अधिकतम फैलाने के लिए छंटनी), और यहां तक कि लंबे तार भी। यह ईएनटी में बहुत अच्छा करता है यदि आपके पास मध्यम शोर है।
स्केच ने अपने उत्तर और अनुवर्ती टिप्पणियों में मेरे द्वारा उल्लिखित कई धारणाओं को एकीकृत किया है: एंट्रॉपी को जमा करना, कम से कम-आदर्श एंट्रोपी (वॉन न्यूमैन ने कहा कि यह अच्छा है) द्वारा खींचकर, और एकरूपता के लिए हैशिंग। यह क्रिप्टोग्राफिक आदिम का उपयोग करके "जिमी कुछ भी गतिशील" के पक्ष में एन्ट्रापी गुणवत्ता के अनुमान को भूल जाता है।
// 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()