Pytanie:
Dlaczego Math.random () nie jest zaprojektowany do zapewnienia bezpieczeństwa kryptograficznego?
forest
2018-03-15 11:11:06 UTC
view on stackexchange narkive permalink

Funkcja JavaScript Math.random () służy do zwracania pojedynczej wartości zmiennoprzecinkowej IEEE n takiej, że 0 ≤ n < 1. Powszechnie wiadomo (lub przynajmniej powinno być), że dane wyjściowe nie są kryptograficznie bezpieczne. Większość nowoczesnych implementacji wykorzystuje algorytm XorShift128 +, który można łatwo złamać. Ponieważ często zdarza się, że ludzie omyłkowo go używają, gdy potrzebują lepszej losowości, dlaczego przeglądarki nie zastępują jej CSPRNG? Wiem, że przynajmniej Opera to robi *. Jedynym rozumowaniem, jakie mógłbym wymyślić, byłoby to, że XorShift128 + jest szybszy niż CSPRNG, ale na nowoczesnych (i nawet nie tak nowoczesnych) komputerach byłoby trywialne wytwarzanie setek megabajtów na sekundę przy użyciu ChaCha8 lub AES-CTR. Są one często na tyle szybkie, że dobrze zoptymalizowana implementacja może zostać zablokowana jedynie przez szybkość pamięci systemu. Nawet niezoptymalizowana implementacja ChaCha20 jest niezwykle szybka na wszystkich architekturach, a ChaCha8 jest ponad dwa razy szybsza.

Rozumiem, że nie można go ponownie zdefiniować jako CSPRNG, ponieważ standard wyraźnie nie daje gwarancji nadaje się do użytku kryptograficznego, ale wydaje się, że nie ma żadnych wad, aby dostawcy przeglądarek robili to dobrowolnie. Zmniejszyłoby to wpływ błędów w dużej liczbie aplikacji internetowych bez naruszania standardu (wymaga tylko, aby dane wyjściowe były zaokrąglone do najbliższej parzystej wartości IEEE 754), zmniejszając wydajność lub łamiąc kompatybilność z aplikacjami internetowymi.


EDYCJA: Kilka osób zwróciło uwagę, że może to potencjalnie spowodować nadużywanie tej funkcji, nawet jeśli standard mówi, że nie można na niej polegać w zakresie bezpieczeństwa kryptograficznego. Moim zdaniem istnieją dwa przeciwstawne czynniki, które decydują o tym, czy użycie CSPRNG przyniesie korzyści w zakresie bezpieczeństwa netto:

  1. Fałszywe poczucie bezpieczeństwa - liczba osób, które w innym przypadku używałyby funkcji przeznaczonej do tego celu, takiej jak window.crypto zdecyduj się zamiast tego na użycie Math.random () , ponieważ jest on kryptograficznie bezpieczny na zamierzonej platformie docelowej.

  2. Oportunistyczny bezpieczeństwo - liczba osób, które nie znają się lepiej i mimo wszystko używają Math.random () dla wrażliwych aplikacji, które byłyby chronione przed własnym błędem. Oczywiście zamiast tego lepiej byłoby ich uczyć, ale nie zawsze jest to możliwe.

Można bezpiecznie założyć, że liczba osób, które byłyby chronione przed własną błędy znacznie przekroczyłyby liczbę osób, które są uśpione w fałszywym poczuciu bezpieczeństwa.

* Jak wskazuje CodesInChaos, nie jest to już prawdą teraz, gdy Opera jest oparta na Chromium. sub>


W kilku głównych przeglądarkach pojawiły się raporty o błędach sugerujące zastąpienie tej funkcji alternatywą bezpieczną kryptograficznie, ale żadna z sugerowanych bezpiecznych zmian nie wylądowała:

Argumenty dla zmiana zasadniczo pasuje do mojej. Argumenty przeciwko temu są różne, od obniżonej wydajności mikroznaków (z niewielkim wpływem w świecie rzeczywistym) po nieporozumienia i mity, takie jak błędne wyobrażenie, że CSPRNG słabnie z czasem, gdy generowana jest większa losowość. Ostatecznie Chromium stworzył całkowicie nowy obiekt kryptograficzny, a Firefox zastąpił swój RNG algorytmem XorShift128 +. Funkcja Math.random () pozostaje w pełni przewidywalna.

Komentarze nie służą do rozszerzonej dyskusji;ta rozmowa została [przeniesiona do czatu] (https://chat.stackexchange.com/rooms/74736/discussion-on-question-by-forest-why-is-math-random-not-designed-to-be-cryptog).
Stwierdzenie, że cecha ma określone cechy, pociąga za sobą obowiązek.Zobowiązanie wiąże się z kosztami, po pierwsze za wykonanie zobowiązania, po drugie za jego aktualizację, a po trzecie, gdy okaże się, że nie wywiązałeś się ze swojego zobowiązania.Jest to szczególnie ważne, gdy zobowiązałeś się do dostarczenia ** bezpiecznej ** funkcjonalności.
@MichaelK Ale jest tak wiele innych przykładów, w których nie jest to prawdą.Nie musisz mówić, że funkcja ma nigdzie pewne cechy.Zachowaj standard bez zmian i poprawiaj bezpieczeństwo.Dobrym przykładem jest każdy nowoczesny kompilator C.Czy twierdzisz, że kompilator nie obsługuje funkcji „FORTIFY_SOURCE”?Dlaczego nie po prostu edukować ludzi, aby nie tworzyli wrażliwych programów?Dlaczego GCC ich chroni?Nie znam nikogo, kto byłby niedbały w swoim kodzie, ponieważ myślą, że GCC ich ochroni, ale znam wielu ludzi, którzy zostali uratowani przez środki bezpieczeństwa GCC.
Innymi słowy, mówisz, że _fail-safe design_ to zła rzecz.
@forest Opportinistyczne bezpieczeństwo?Słowa, o których nigdy nie myślałem, że ktoś powie.
Może wydajność?Uzyskanie losowej wartości zabezpieczonej kryptograficznie jest o wiele bardziej obciążające procesor niż wartość pseudolosowa.Projektując grę (w C ++) musiałem specjalnie wybrać losowy algorytm oferujący przyzwoitą wydajność.
Blink to silnik renderujący.V8 to implementacja JavaScript używana przez Chrome i Opera.
@Rolf ツ Ten problem został obszernie omówiony w odpowiedziach i komentarzach.Wydajność XorShift128 + w porównaniu do, powiedzmy, ChaCha8 używanego do zwracania pojedynczych liczb zmiennoprzecinkowych.
Porównanie wydajności XorShift128 + z ChaCha8 to tylko część kwestii wydajności.CSPRNG musi zebrać wystarczającą entropię, zanim będzie gotowy do emitowania jakichkolwiek bezpiecznych losowych bitów.Może to zająć dużo czasu.
@JamesKPolk Potrzebujesz tylko 128 bitów, raz (ChaCha zajmuje 256 bitów, ale jest całkowicie dopuszczalne dwukrotne powtórzenie klucza, o ile zmieniasz stałą).Do czasu załadowania dowolnej przeglądarki system będzie miał dostęp do dużej ilości entropii.Na mikrokontrolerach, które z dowolnego powodu uruchamiają interpreter JavaScript i nie mają źródła dobrej entropii, mogą po prostu użyć XorShift128 + (ponieważ nie sugeruję zmiany standardów).
@forest: wystarczająco uczciwy, rzeczywiście nie powinno to stanowić problemu na żadnej nowoczesnej platformie, komputerze stacjonarnym lub telefonie komórkowym.
Jedenaście odpowiedzi:
Eric Lippert
2018-03-15 20:10:44 UTC
view on stackexchange narkive permalink

Byłem jednym z wdrażających JScript i członkiem komisji ECMA od połowy do późnych lat 90., więc mogę tu przedstawić trochę historycznej perspektywy.

Funkcja JavaScript Math.random () ma na celu zwrócenie wartości zmiennoprzecinkowej z zakresu od 0 do 1. Powszechnie wiadomo (a przynajmniej powinno być), że dane wyjściowe nie są zabezpieczone kryptograficznie.

Po pierwsze: projekt wielu liczb losowych Interfejsy API są okropne . Okropny jest fakt, że klasa .NET Random może być w trywialny sposób nadużywana na wiele sposobów do tworzenia długich sekwencji o tej samej liczbie. Interfejs API, w którym naturalny sposób użycia jest również niewłaściwy, jest interfejsem API „dołka niepowodzeń”; Chcemy, aby nasze API były dołkami sukcesu, gdzie naturalny sposób i właściwy sposób są takie same.

Myślę, że można uczciwie powiedzieć, że gdybyśmy wiedzieli to, co wiemy teraz, losowe API JS byłoby inne. Nawet proste rzeczy, takie jak zmiana nazwy na „pseudolosowy”, pomogłyby, ponieważ jak zauważyłeś, w niektórych przypadkach szczegóły implementacji mają znaczenie. Na poziomie architektonicznym istnieją dobre powody, dla których chcesz, aby random () był fabryką zwracającą obiekt reprezentujący losową lub pseudolosową sekwencję, zamiast po prostu zwracać liczby. I tak dalej. Wyciągnięte wnioski.

Po drugie, pamiętajmy, jaki był podstawowy cel projektowania JS w latach 90-tych. Spraw, by małpa tańczyła, gdy poruszasz myszą . Myśleliśmy o skryptach wyrażeń wbudowanych jako o normalnych, myśleliśmy o blokach skryptów składających się z dwóch do dziesięciu wierszy jako powszechnych, a pomysł, że ktoś mógłby napisać sto wierszy skryptu na stronie, był naprawdę bardzo niezwykły. Pamiętam, że pierwszy raz zobaczyłem program JS z dziesięcioma tysiącami wierszy i moje pierwsze pytanie do ludzi, którzy prosili mnie o pomoc, ponieważ był tak wolny w porównaniu z ich wersją w C ++, brzmiało: „czy jesteś szalony ?! 10KLOC JS ?! "

Pomysł, że każdy potrzebowałby krypto losowości w JS był podobnie szalony. Potrzebujesz ruchów małpy, aby kryptowaluta była nieprzewidywalna? Mało prawdopodobne.

Pamiętaj też, że to była połowa lat 90. Gdyby cię tam nie było, to mogę powiedzieć, że był to bardzo inny świat niż dzisiaj , jeśli chodzi o kryptografię ... Zobacz eksport kryptografii.

Nie rozważałbym nawet rozważania umieszczania losowości kryptowalut w czegokolwiek, co zostało dostarczone z przeglądarką bez uzyskania ogromnej ilości porad prawnych od zespołu MSLegal. Nie chciałem dotykać kryptowalut dziesięciostopowym słupem w świecie, w którym kod wysyłkowy był uważany za eksport amunicji do wrogów stanu . Z dzisiejszej perspektywy brzmi to szalenie, ale taki był świat, którym był.

Dlaczego przeglądarki nie zastępują go CSPRNG?

Autorzy przeglądarki nie muszą podawać powodu, aby NIE wprowadzać zmian. Zmiany kosztują i odbierają wysiłek lepszym zmianom; każda zmiana wiąże się z ogromnym kosztem alternatywnym .

Zamiast tego musisz przedstawić argument, nie tylko dlaczego wprowadzenie zmiany jest dobrym pomysłem, ale dlaczego jest to najlepsze możliwe wykorzystanie ich czasu. To niewielka zmiana za grosze.

Rozumiem, że nie można go ponownie zdefiniować jako CSPRNG, ponieważ standard wyraźnie nie daje żadnej gwarancji przydatności do użytku kryptograficznego, ale i tak wydaje się, że nie ma w tym żadnych wad

Minusem jest to, że programiści nadal znajdują się w sytuacji, w której nie mogą wiarygodnie wiedzieć, czy ich losowość jest siłą kryptowalut lub nie, a nawet łatwiej wpaść w pułapkę polegania na nieruchomości, która nie jest gwarantowana przez standard. Proponowana zmiana w rzeczywistości nie rozwiązuje problemu, który jest problemem projektowym.

(Trochę poza tematem) Czy mógłbyś podać odniesienie do „klasy .NET Random można w trywialny sposób nadużywać na wiele sposobów do tworzenia długich sekwencji o tej samej liczbie, jest okropne” ?: Nie słyszałem o tym wcześniej, czy jesteśodnosząc się do klasycznego „Utwórz tysiąc przypadkowych instancji w ścisłej pętli”?
@VisualMelon: Tworzenie tysięcy instancji w ciasnej pętli to klasyka.Ale istnieją również tryby awarii, gdy używasz jednej instancji Random na dwóch wątkach w tym samym czasie.Losowość nie jest bezpieczna dla wątków i istnieje scenariusz, w którym wyścig może spowodować, że na zawsze zwróci zero!
@VisualMelon: Istnieją również bardziej subtelne scenariusze.Załóżmy, że masz dwa wystąpienia Random z różnymi nasionami.Wydaje się w porządku, prawda?Ale przypuśćmy, że w jakiś sposób połączysz te dwa wystąpienia Random.Może używasz ich do wykonania sekwencji rzutów kostką i zsumuj je parami.** Czy te dwie sekwencje są ze sobą skorelowane w sposób nielosowy **?Wydaje się prawdopodobne.W końcu używają tego samego algorytmu „równolegle”, tylko z innym ziarnem.
Dziękuję za rozwinięcie: Przypuszczam, że jestem na tyle ostrożny, aby nie próbować używać _dowolnego_ źródła z wielu wątków, chyba że jest to wyraźnie udokumentowane w tym celu, więc nigdy bym tego nie zauważył.Nie jestem pewien, czy ostatnia kwestia dotyczy konkretnej „implementacji”, a nie algorytmu, który za nią stoi: nie sądzę, abyśmy mogli pociągać do odpowiedzialności projektantów API!
Myślę, że jak dotąd jest to najlepsza odpowiedź, zwłaszcza że pochodzi z tak autorytatywnego źródła.Oznaczę tę odpowiedź jako zaakceptowaną na razie, chyba że nadejdzie lepsza odpowiedź.
@EricLippert Nie rozumiem twoich 2 strumieni z różnymi kluczami dodanymi razem. Przykład.Jeśli jest to CSPRNG, to myślę, że powinno być w porządku.Jeśli nie jest to CSPRNG (tylko plan PRNG), nigdy nie powinieneś go używać ze względów bezpieczeństwa, nawet jeśli masz tylko jedną instancję.
@Buge: Dość łatwo jest wyobrazić sobie (niezbyt dobry) RNG, który generuje liczby całkowite i gdzie dolny bit wyniku jest losowy, ale niezależny od ziarna.Jeśli dodasz dane wyjściowe dwóch takich instancji (niezależnie zainicjowanych), wynik będzie zawsze parzysty.(Uwaga Erica nie miała nic wspólnego z bezpieczeństwem - nie wiem, co sprawiło, że tak sądzisz).
Tak!Dlaczego * wszystkie * losowe interfejsy API na * wszystkich * platformach są tak pomieszane?Myślę, że zespoły idą „pozwól stażyście to zrobić”.
@EricLippert Myślę, że warto dodać konkretny przykład do tej odpowiedzi nadużywalnego `Random` w języku C #.Coś takiego jak ten (pseudo) kod: `while (coś) {int rand = new Random (). NextInt ();doSomething (rand);} `- To się nie powiedzie, ponieważ` Random` w C # używa bieżącego czasu z rozdzielczością kursu jako zarodka, więc jeśli `doSomething` jest szybkie, otrzymasz pierwszą liczbę w sekwencji z tym, czym jest ten czas, w kółkoznowu, a nie inne.(Wiem, że to wiesz; wyjaśniam ludziom, którzy nie pracowali na C # z Microsoftem)
@Buge Właściwie czasami mieszanie wielu złych PRNG razem może dać przyzwoity szyfr, przynajmniej jeśli zostanie wykonany poprawnie.Na przykład E0 (szyfr używany we wszystkich oprócz najnowszych protokołów Bluetooth) obejmuje cztery LFSR.Każdy pojedynczy LFSR jest trywialny do zerwania, ale samo E0 jest trochę silniejsze (ale nadal nie jest świetne).
@MartinBonner Myślałem, że komentarz Erica mówił o CSPRNG, ponieważ jest to security.stackexchange.com i zarówno pytanie, jak i odpowiedź Erica dotyczyły CSPRNG.
@forest Powinienem był ograniczyć moje oświadczenie, mówiąc: „Jeśli to nie jest CSPRNG (tylko zwykły PRNG), to nigdy nie powinieneś używać go do celów bezpieczeństwa, chyba że jesteś ekspertem w dziedzinie kryptografii”.Tak jak ekspert kryptograficzny może utworzyć nowy szyfr przy użyciu niezabezpieczonych prymitywów, takich jak dodawanie, xor i mnożenie, tak ekspert kryptograficzny może również utworzyć nowy CSPRNG za pomocą PRNG.I tak jak laik nigdy nie powinien tworzyć nowego szyfru przy użyciu niezabezpieczonych prymitywów, tak laik nigdy nie powinien używać PRNG dla bezpieczeństwa.
Doskonała, pouczająca odpowiedź.„Koszt alternatywny” to prawdopodobnie jedyne potrzebne wyjaśnienie, ale wszystko inne to prawdziwa gratka
Miałem zamiar udzielić bardzo podobnej odpowiedzi, która grała na tych samych motywach, o których tutaj wspomniałem, w zasadzie krótka, niezadowalająca wersja, która brzmi: „specyfikacja tego nie wymaga, więc implementacje nie muszą czynić tego kryptograficznie losowym”
@Buge Rozumowanie, którego używa Martin, odnosi się do CSPRNG.Nie jest to szczególnie dobre, ale większość CSPRNG używanych przez języki głównego nurtu wcale nie jest niesamowita.
@Voo Jeśli „dolny bit wyniku jest losowy, ale niezależny od ziarna”, to nie jest to CSPRNG.CSPRNG [wymaga] (https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator), że jeśli nie masz wiedzy o ziarnie, to wynik CSPRNG jest nie do odróżnienia od prawdziwej losowości.Ale ten zły PRNG można dość łatwo odróżnić od prawdziwej losowości, nawet bez wiedzy o ziarnie.Po prostu sprawdź, czy dolny bit jest zgodny z wzorem.
@Buge Myślałem o wspólnym źródle losowości (powiedzmy o module sprzętowym).Ale masz rację, że to by nie zadziałało, gdybyś miał dwie sekwencje.
Philipp
2018-03-15 15:22:47 UTC
view on stackexchange narkive permalink

Ponieważ w rzeczywistości istnieje bezpieczna kryptograficznie alternatywa dla Math.random():

window.crypto.getRandomValues ​​(typedArray)

Pozwala to programiście na użycie odpowiedniego narzędzia do pracy. Jeśli chcesz generować ładne obrazki lub łupy do swojej gry, użyj szybkiego Math.random () . Jeśli potrzebujesz zabezpieczonych kryptograficznie liczb losowych, użyj droższego window.crypto .

Dlaczego nie miałbyś używać bezpiecznej funkcji losowej do wypadania łupów?
@xDaizu Ponieważ nie każdy łup jest skrzynką z łupami, z której ktoś zrobi prawdziwą loterię.
Jeśli twój łup musi być zabezpieczony kryptograficznie * i * używasz RNG po stronie klienta do generowania łupu (zamiast pytać serwer „co dostałem?”), Najprawdopodobniej robisz coś nie tak.
To nie odpowiada na pytanie ... las pyta o to, dlaczego `Math.Random ()` jest zaimplementowany tak, jak jest, a nie jak używać CSPRNG w JavaScript
Mówiąc dokładniej, `window.crypto` jest w dużej mierze bezużyteczne, jeśli nie ufasz użytkownikowi.W tym konkretnym przypadku oni (lub ich agent użytkownika lub wszelkie zaufane serwery proxy) mogą po prostu zamienić go na `() => 0,42` przed wykonaniem.Są to narzędzia umożliwiające użytkownikowi ustanowienie zabezpieczeń, a nie Ciebie.
@xDaizu odpowiedź na Twoje pytanie znajduje się w poście, na który odpowiedziałeś: jest to kwestia „szybka kontra [wolna i] droga”
@OrangeDog,, dlatego zawsze musisz używać z nim słowa kluczowego `const`.
@NH.nic, co napiszesz w skrypcie, nie pomoże, użytkownik ma nad tym pełną kontrolę
@OrangeDog, czy to CVE?Jeśli nie, czy możesz zamieścić swoje obawy w osobnym poście (zaczynamy odbiegać od tematu ...)
@OrangeDog To prawda, ale to prawda, ponieważ pytanie dotyczy skryptów po stronie klienta.Nie ma to związku z faktem, że „Math.random” nie jest bezpieczny kryptograficznie.
Luc
2018-03-15 16:13:53 UTC
view on stackexchange narkive permalink

JavaScript (JS) został wynaleziony w 1995 roku.

  1. Potencjalnie nielegalny: kryptografia była nadal pod ścisłą kontrolą eksportu w 1995 roku, więc dobry CSPRNG może nawet nie mieć były legalne do rozpowszechniania w przeglądarce.
  2. Wydajność: historycznie CSPRNG (bezpieczne kryptograficznie generatory liczb pseudolosowych) są znacznie wolniejsze niż PRNG, więc po co domyślnie używać CSPRNG?
  3. Brak nastawienia na bezpieczeństwo: w 1995 r. właśnie wynaleziono SSL. Praktycznie żaden serwer go jeszcze nie wspierał, internet składał się z linii telefonicznych i był używany na forach publicznych ( BBSes) i MUDs. Szyfrowanie było czymś dla agencji wywiadowczych.
  4. Nie ma potrzeby: aplikacje internetowe jeszcze nie istniały, ponieważ właśnie wynaleziono JavaScript. Został zaprojektowany jako interpretowany (a więc powolny) język, aby strony były bardziej dynamiczne. Nikomu nie przyszłoby do głowy, aby domyślnie używać powolnego (i prawie nie istniejącego) CSPRNG dla funkcji losowej.
  5. Tak naprawdę nie ma takiej potrzeby, że nie ma alternatywy: JavaScript nie miał nawet ogólnie obsługiwanego interfejsu API dla CSPRNG do grudnia 2013 r., więc poprawna kryptografia w aplikacjach internetowych była możliwa dopiero kilka lat temu.
  6. Spójność: Zamiast zmieniać istniejącą funkcję, aby miała inne znaczenie, stworzyli nową funkcję o innej nazwie. Możesz teraz uzyskać dostęp do CSPRNG przez crypto.getRandomValues.

Podsumowując: starsze, ale także szybkość i spójność . Niezabezpieczone PRNG są nadal znacznie szybsze, ponieważ nie można założyć, że cały sprzęt obsługuje AES, ani nie zależy od dostępności lub bezpieczeństwa RDRAND.

Osobiście uważam, że nadszedł czas, aby zamienić wszystkie losowe funkcje na CSPRNG i zmienić nazwy szybszych, niezabezpieczonych funkcji na coś takiego jak fast_insecure_random () . Powinny być potrzebne tylko naukowcom lub innym osobom, które przeprowadzają symulacje, które wymagają wielu liczb losowych, ale gdzie przewidywalność RNG nie stanowi problemu. Ale w przypadku funkcji z dwudziestoletnią historią, dla której alternatywa istnieje tylko od czterech lat (w 2018 r.), Mogę zrozumieć, dlaczego jeszcze nie jesteśmy w tym momencie.

Również Javascript jest trochę starszy, niż myśli większość ludzi.a funkcja math.random jest w nim od co najmniej 1997 roku (wersja 1.1) Czas, w którym nikt nawet nie próbowałby czegoś takiego jak kryptografia w javascript (SSL sam nie ujrzał światła publicznego aż do 1995 roku, zaledwie kilka lat wcześniej)
Nie zgadzam się z ostatnim zdaniem w tej sprawie.Chociaż `crypto.getRandomValues` mogłoby być lepszą nazwą w izolacji, skoro` math.Random` istnieje już od kilku lat coś takiego jak `math.RandomCrypto` byłoby znacznie lepszym wyborem, ponieważ byłoby wymienione jako następnena niezabezpieczone wywołanie w jakimkolwiek wykazie API i dobre autouzupełnianie spowodowałoby wyświetlenie obu wersji za każdym razem, gdy programista wpisze `math.rando`, co znacznie zwiększa prawdopodobieństwo, że zdadzą sobie sprawę, że powinni używać nowej, kiedy tego potrzebują.
semantycznie twoja propozycja jest błędna.chcesz uzyskać losowe wartości, które są poprawne kryptograficznie.nie otrzymaj losowej funkcji kryptograficznej / ciper / itp. Ponadto biblioteka Math jest tylko o funkcjach matematycznych.a CSPRNG to funkcja kryptograficzna, a tym samym rzeczy w bibliotece kryptograficznej.(i nie zapominaj, że dodanie do standardu wymaga konsensusu wszystkich różnych konstruktorów silników).
@DanNeely Rozumiem twój punkt widzenia, ale nie jestem pewien, jak najlepiej to zmienić.Zapraszam do edycji!
@LvB Jestem otwarty na różne nazwy funkcji (`math.RandomSecure`?) Lub nawet implementację w` crypto. * `Z aliasem pod` math. * `(Czy współczesny js jest w stanie wstawić alias douniknąć narzutu dodatkowego wywołania funkcjonalnego w celu zaimplementowania aliasu?).Jednak przy ogromnej liczbie różnych narzędzi, których ludzie używają do edycji javascript, umieszczenie starej nazwy jako pierwszej części nowej zwiększa prawdopodobieństwo, że redaktor będzie w stanie zasugerować programistom bezpieczne, losowe źródło.
@DanNeely, próbujesz tutaj rozwiązać ludzki problem środkami technicznymi.e.a.człowiek powinien dowiedzieć się, jakiego narzędzia i gdzie użyć, a nie IDE, korzystając z wygodnej funkcji, aby zasugerować właściwe.(lepiej byłoby mieć IDE niż sugerować właściwe, ale jest to zależne od IDE).Nie pomogłoby również wszystkim tym, którzy piszą javascript w przeglądarce / vim / nano / notatniku / kamiennym tablecie / karcie dziurkowanej / lub w jakimkolwiek innym edytorze tekstu lub metodologii bezpośredniego wprowadzania danych.Poza tym musiałbyś mieć do dyspozycji wielu programistów silnika, ludzi, których niełatwo jest przekonać.
@DanNeely, możesz się nie zgadzać, co chcesz, nie jesteś w komitecie TC39, ani nie jest to właściwe forum, na którym można dyskutować z ich decyzjami.FWIW, możesz wypełnić swoją własną sugestię, po prostu przypisując `Math.randomCrypto = function () {const u = new Uint32Array (1);crypto.getRandomValues (u);return u [0] / 2 ** 32;} `.Oczywiście są możliwe optymalizacje, ale to tylko przykładowa realizacja.
Jared Smith
2018-03-15 16:56:31 UTC
view on stackexchange narkive permalink

To za długie na komentarz.

Wydaje mi się, że Twoje pytanie zawiera błędne założenie:

na nowoczesnych (i nawet nie tak nowoczesnych) komputerach, byłoby trywialne wytwarzanie setek megabajtów na sekundę przy użyciu ChaCha8 lub AES-CTR

Myślisz o przeglądarce na komputerze podłączonym do prądu zmiennego lub laptopie z dużą baterią 10 Ah.

Żyjemy w coraz bardziej mobilnym świecie i chociaż urządzenia mobilne są obecnie dość potężne, mają dwa ważne ograniczenia: ciepło i żywotność baterii. W przeciwieństwie do procesora stacjonarnego, który z łatwością może osiągnąć 100 ° C, nie możesz spalić ręki użytkownika smartfona. A baterie do telefonów zwykle mieszczą tylko może 1/3 tego, co laptop (jeśli masz szczęście). Po prostu nie ma dobrego powodu, aby dodać dodatkowe wytwarzanie ciepła / zużycie energii, jeśli tego nie potrzebujesz.

Wątpię, byś zauważył różnicę w wydajności / zużyciu energii między kryptograficznymi i niekryptograficznymi numerami RNG dla typowego kodu, nawet na urządzeniach mobilnych.Musiałbyś napisać symulację Monte Carlo w javascript.Mówimy o około 30 cyklach procesora dla każdej liczby.
@CodesInChaos to może być prawda.Chciałbym zobaczyć dane analityczne (w szczególności dotyczące np. Portu CRPG) przed wykonaniem tego połączenia.Ale to ukryta przesłanka „komputery są teraz szybkie, więc to nie ma znaczenia”, to jest problem.
ChaCha8 może zapewnić około 3 cykli na bajt nawet na starych procesorach i poniżej 1 cyklu na bajt w przypadku AVX512.XorShift128 + ma mniej niż 1 cykl na bajt na wysokiej klasy procesorze Haswell, więc różnica nie jest duża.Wyobrażam sobie, że sam akt przekształcenia losowej wartości we właściwy zmiennoprzecinkowy i zwrócenie go zajmuje więcej cykli niż generowanie wartości losowej w pierwszej kolejności.
@CodesInChaos Ludzie piszą symulacje Monte Carlo w JavaScript.
Jeśli się nad tym zastanowić, jestem prawie pewien, że procesor desktopowy osiągający 100 ° C byłby _bardzo zły_.Procesory do laptopów zwykle sobie z tym poradzą (jeśli tylko ledwo), ale komputery stacjonarne?
@CodesInChaos Technicznie rzecz biorąc, nie potrzebujesz silnego kryptograficznie RNG dla Monte Carlo.Każdy przyzwoity RNG będzie działał (jak Mersenne Twister).
@jb.Chodzi mi o to, że kryptograficzne RNG są wystarczająco szybkie dla praktycznie każdego przypadku użycia, a zatem powinny być domyślne.Symulacje Monte Carlo to jeden z nielicznych przypadków, w których warto zamienić jakość na wydajność.
@CodesInChaos Biorąc pod uwagę, że `Math.random ()` zwraca tylko indywidualne wartości zmiennoprzecinkowe i musi być wywoływane dla każdej nowej wartości, byłby to raczej okropny sposób na uzyskanie losowości dla symulacji Monte Carlo, niezależnie od tego, czy XorShift128 + lub ChaCha jestużywany.Również LSB XorShift128 + to LFSR, który prawdopodobnie nie jest zbyt dobry do takich symulacji.
@CodesInChaos: Różnica w * generowaniu * bajtów jest prawdopodobnie niewielka, ale wydaje się, że nikt nie wspomniał o trudniejszej części CSPRNG: zbieraniu entropii.
przeglądarka może szczęśliwie korzystać z losowych danych generowanych przez system operacyjny
@JamesKPolk: Jeśli istnieje jakakolwiek możliwość ujawnienia stanu CSPRNG, konieczne jest ponowne umieszczenie w nim źródła entropii niezależnego od jakiegokolwiek poprzedniego, ale jeśli ma się dobry CSPRNG z np.4096 bitów stanu obsadzonych np.160 bitów „czystej” entropii i nigdy się nie ujawnia. Czy są jakieś ataki, które byłyby praktyczne, a które nie byłyby praktyczne, gdyby były obsiane 4096 bitami entropii?
@forest: Nie chodzi o to, że procesor stacjonarny może bezpiecznie tolerować większą temperaturę (nie może, chociaż limit jest zwykle podobny do procesora mobilnego, powiedzmy 90, 95 lub 100 ° C).Chodzi o to, że większość procesorów do komputerów stacjonarnych jest zainstalowanych z wydajnym chłodzeniem, dzięki czemu mogą wykonywać operacje kryptograficzne z pełnym nachyleniem i nadal pozostają stosunkowo chłodne, być może 60 ° C.Po prostu nie możesz zmieścić tego rozwiązania chłodzącego w urządzeniu przenośnym, między innymi dlatego, że waży więcej i jest większy niż reszta telefonu i działa tylko z otworami wentylacyjnymi i przepływem powietrza, co jest niedopuszczalne w przypadku wodoodpornego podręcznegotorba.
@BenVoigt Aha, mógłbym przysiąc, że Tj Max dla procesorów do komputerów stacjonarnych jest znacznie niższy niż w laptopach.Musiałem niepoprawnie zapamiętać.
LSerni
2018-03-15 12:15:35 UTC
view on stackexchange narkive permalink

Większy powód jest taki, że istnieje alternatywa dla Math.random () : zobacz odpowiedź Filipa . Więc każdy, kto potrzebuje mocnego kryptowaluty, może go mieć, a ci, którzy tego nie chcą, mogą zaoszczędzić czas i energię (baterii).

Ale przypuśćmy, że zapytałeś: „dlaczego, nawet jeśli istnieje silniejsza alternatywa, programiści nie aktualizują Math.random () tak samo - tj. utworzyli random () pochodną metody getRandomValues ​​() - w celu automatycznego wzmocnienia wielu dostępnych aplikacji? ” - to nie sądzę, aby można było na to odpowiedzieć z całą pewnością, z wyjątkiem tych deweloperów, którzy podjęli decyzję (aktualizacja: i tak jak chciał tego los, mamy taką odpowiedź).

Zasadniczo - jak już powiedziałeś - nie ma mocnego powodu .

Co więcej, większość zespołów programistycznych ma znaczne zaległości w sprawach, które są pilniejsze ; a nawet pozornie niewielka zmiana, taka jak ta, wymaga testowania, regresji i przeciwstawiania się złotej zasadzie „ Jeśli to nie jest zepsute, nie naprawiaj tego ”, silniejszej postaci kryterium YAGNI.

Jestem pewien, że dyskutowano na ten temat w trackerach Mozilli i Google.Może mógłbyś podać jakieś linki, aby to pokazać?Byłbym zadowolony, gdyby odpowiedź brzmiała po prostu „ponieważ nikt jeszcze tego nie zrobił”, ale chciałbym zobaczyć kilka przykładów, które pojawiły się już wcześniej, a programiści odrzucają ten pomysł jako niepotrzebny.
Głosuj przeciw, ponieważ uważam, że jest to kwestia odpowiedzialna i głupotą jest stwierdzenie tego pogrubioną czcionką u góry jako podsumowanie Twojej odpowiedzi.
@Luc Poprawiłem odpowiedź, aby wyjaśnić moje znaczenie - a także zagłosowałem za odpowiedzią Filipa, która moim zdaniem jest poprawną odpowiedzią na zadane pytanie.
Rob
2018-03-16 08:29:02 UTC
view on stackexchange narkive permalink

Liczby losowe i kryptolosowe bity to zupełnie inne zwierzęta. Nie są nawet używane w tym samym celu. Jeśli chcesz, aby losowa liczba była równomiernie rozłożona między 0 a 42, to chcesz równego rozkładu bez oczywistego wzoru. Zauważ, że jeśli zmodyfikujesz większą liczbę mniejszą, nie jest to dokładnie równa dystrybucja. Ten przykład jest łatwy do zauważenia dla losowej liczby od 0 do 31 wziętej z mod 27. 0 do 4 pojawia się dwa razy częściej niż 5 do 31.

Dopóki nie mówisz o kryptorandomie, pojęcie entropii nie jest ' nawet nie dyskutowałem. Odrobina entropii podwaja przestrzeń wyszukiwania przy odgadywaniu liczby (dla zamierzonego użytkownika liczb).

Kiedy pytasz o kryptorolubowe bity, pytasz o N bitów entropii. Nie wystarczy mieć nieoczywistego wzorca, ponieważ jeśli funkcja, która go generuje, zostanie odkryta (bez względu na to, jak skomplikowana), to w rzeczywistości istnieje 0 bitów entropii z punktu widzenia tego, kto zna tę funkcję.

Dobrym tego przykładem jest generator liczb pseudolosowych w stylu Fortuny. Szyfrujesz liczbę 1 za pomocą klucza dla pierwszej liczby losowej (gdzie blok szyfru jest dużą liczbą), następnie szyfrujesz liczbę 2 kluczem dla drugiej liczby losowej i tak dalej. W odniesieniu do użytkownika, który nie zna klucza (z K bitów) do szyfru, doskonały N-bitowy blok szyfrujący będzie miał N bitów entropii dla tego bloku.

Jeśli rozwiniesz do miliona bitów pseudolosowych danych, to nadal będziesz miał tylko K bitów entropii, jeśli będziesz kontynuował z tym samym kluczem K. Innymi słowy: jeśli masz Księga 1 miliona bitów, o których wiesz, że została wygenerowana za pomocą jednego szyfru pod literą K, więc nie próbuj zgadywać wszystkich bitów strumienia szyfrowania. Po prostu trzymaj się odgadywania klucza i generuj z niego strumień szyfrowania.

Więc generator liczb losowych jest często szyfrem, który jest ponownie zaszczepiany z większą losowością, ponieważ można to osiągnąć. Dla porównania, prosty generator liczb losowych [0,1] nie może mieć większej entropii niż liczba bitów w liczbie; i zazwyczaj będzie miał dziwną dystrybucję, która nie jest dokładnie tym, czego chcesz. Crypto potrzebuje setek bitów, gdy liczby zmiennoprzecinkowe są tylko 32 lub 64-bitowe, a sam algorytm zabiera większość entropii ... zakładając, że chcesz, aby coś było równomiernie rozłożone z [0..1], zamiast powiedzieć reprezentacja zmiennoprzecinkowa złożona z losowych bitów. Nie wiem nawet, jaka to by była dystrybucja.

richzilla
2018-03-15 16:39:06 UTC
view on stackexchange narkive permalink

W pewnym sensie sam odpowiedziałeś na pytanie:

standard wyraźnie nie daje żadnej gwarancji przydatności do użytku kryptograficznego

Zamiast więc zmieniać implementację, należy skupić się na edukacji programistów, aby wybrali „odpowiednie narzędzie do pracy” ™.

Biorąc to pod uwagę, oraz koszty techniczne zmiany implementacji powszechnie używanej funkcji, a także fakt, że istnieją już konkretne rozwiązania tego problemu (patrz odpowiedź @Philipps), nie ma żadnego ważnego powodu, aby wprowadzać zmiany.

Dlaczego DV?Anonimowe głosy przeciw nikomu nie są przydatne ...
Głosowałem w dół, ponieważ to odpowiada na inne pytanie.Oczywiście standard nie gwarantuje bezpieczeństwa kryptograficznego.Jednak moje pytanie dotyczyło szczególnie oportunistycznego bezpieczeństwa.Standardów nie trzeba by dotykać.Narzut techniczny powinien być niski, ponieważ przeglądarka już łączy się z biblioteką TLS.Prawdopodobnie mógłbym edytować przeglądarkę tak, aby korzystała z biblioteki dla funkcji `Math.random ()` w mniej niż 5 wierszach różnicy.
allo
2018-03-15 15:10:49 UTC
view on stackexchange narkive permalink

Projektowanie języka programowania wymaga uwzględnienia wielu rzeczy. Przeglądarki są bardzo wydajne i dziś dużo optymalizują javascript. Ale jeśli weźmiesz pod uwagę systemy wbudowane, możesz nie mieć dobrego źródła losowości. Na przykład istnieją mikrokontrolery działające w środowisku nodeJS (podobnym).

Taki mikrokontroler nie ma losowych źródeł, które gwarantują kryptograficznie bezpieczne liczby losowe. Więc musiałbyś wymagać podłączenia jakiegoś urządzenia, które może dostarczać losowe dane wejściowe do pinu, aby móc zaimplementować język programowania, który daje silne gwarancje dotyczące liczb losowych. Potrzebowałbyś sporej wiedzy, aby zbudować urządzenie zapewniające wystarczającą losowość i przetwarzać dane wejściowe z urządzenia w odpowiedni sposób.

Przeglądarka obsługująca JavaScript zazwyczaj ma dobre źródło losowości, aby zapewnić TLS.I jak powiedziałem, że standard nie musi być zmieniany, _ nie musi istnieć_ gwarancja, że API będzie generować kryptograficznie bezpieczną losowość.
Jeśli API nie gwarantuje prawdziwej losowości, jako programista nie powinieneś na nim polegać.Jeśli programiści nie polegają na tym, nie musisz go wdrażać.Wyobraź sobie, że większość przeglądarek ma tam prawdziwą losowość.Strony internetowe budowałyby na nim rzeczy, ponieważ one tam są.A potem następna przeglądarka nie ma prawdziwej losowości.ups.Innym powodem może być to, że wyczerpujesz pulę entropii bardziej i potrzebujesz więcej czasu, jeśli wyprowadzasz prawdziwe losowe wartości w każdym wywołaniu API, które ich nie wymaga.
Ale niektórzy programiści _nie_ polegają na nim, nie dlatego, że uważają, że jest bezpieczny kryptograficznie, ale dlatego, że nie wiedzą, jak działa losowość.Nie ma też czegoś takiego jak „wyczerpująca entropia”.Pojedyncze 128-bitowe ziarno może wysłać praktycznie nieograniczoną ilość nieprzewidywalnych danych.
@forest Chociaż prawdą jest, że wystarczająco losowy klucz 128-bitowy w połączeniu z wystarczająco dobrymi prymitywami kryptograficznymi może generować bardziej bezpieczne kryptograficznie dane pseudolosowe, niż ktokolwiek mógłby potrzebować w naszym życiu, jest w tym wiele zastrzeżeń.Prosty fakt jest taki, że w niektórych implementacjach CSPRNG, w tym w wielu jądrach Linuksa, pule entropii * nie * są nieograniczonym zasobem i mogą zostać wyczerpane / wyczerpane, jeśli zapytasz je wystarczająco mocno.Zachęcaj ludzi do używania takich rzeczy jak `/ dev / urandom` a nie` / dev / random`, jeśli chcesz, ale nie udawaj, że `/ dev / random` nie może się skończyć.
@CBHacking W rzeczywistości są nieograniczone.I faktycznie, `/ dev / random` nigdy się nie" kończy ".Raczej celowo blokuje z raczej głupich powodów.Przeczytaj kod w [`drivers / char / random.c`] (https://github.com/torvalds/linux/blob/master/drivers/char/random.c), aby zrozumieć to bardziej szczegółowo (jest to dosłowniewywołanie `wait_event_interruptible ()` w celu oszacowania liczby).Dopóki ChaCha20 (którego używa `/ dev / urandom`) nie jest śmiertelnie uszkodzony na wiele sposobów, nie ma powodu, aby używać puli blokującej zamiast puli nieblokującej.Należy pamiętać, że przeglądarki nie używają puli blokującej.
@forest Pedantry nie staje się tobą.Pula entropii uzupełnia się samoczynnie, ale twierdzenie, że „nigdy się nie kończy”, jest jak mówienie, że nie mogę „zabraknąć” mleka, dopóki jest dostępny sklep spożywczy.Podobnie twierdzenie, że powody, dla których „/ dev / random” mogą się blokować, są „głupie” i „legacy”, nie zmienia faktu, że odczyty z niego mogą blokować się przez dowolnie długi czas i rzeczywiście zaobserwowano, że robią to w przypadku maszyn takich jak maszyny wirtualnebez interakcji użytkownika lub prawdziwego sprzętu (chociaż obecnie host często przekazuje maszynę wirtualną do entropii).Jeśli chodzi o przeglądarki, czy nieblokujące źródło entropii jest wymagane przez jakąkolwiek specyfikację?
@CBHacking Kiedy pijesz mleko, mleko znika z dzbanka.Kiedy używasz entropii, nawet z puli blokującej, dane puli wciąż tam są.Jedyną zmianą jest pojedyncza liczba całkowita, która śledzi oszacowanie entropii.Jeśli chodzi o przeglądarki, tak, jest to wymagane.Wiele operacji, które wymagają nieprzewidywalnego strumienia liczb losowych, musi wystąpić w określonym czasie zgodnie ze specyfikacjami.Implementacja TCP, która wiąże się z ryzykiem czekania przez nieokreślony czas na losowość numeru sekwencyjnego, byłaby zepsutą implementacją.
Gdybyś miał załatać jądro, aby usunąć blokujące zachowanie `/ dev / random` siłą, nie dławiłoby się ono ani nie zmieniało w` / dev / zero`, jak można by się spodziewać, gdyby entropia została faktycznie wykorzystana.Nadal byłby to doskonale bezpieczny CSPRNG, chociaż taki, który opiera się na rezystancji przedobrazu SHA1 (pula blokująca i ukryta pula wejściowa używają mieszania SHA1, podczas gdy nowoczesna pula nieblokująca używa ChaCha20 z 48 bajtami losowych danych z wejściabasen).Więc przypuszczam, że można użyć terminu „zabraknie”, ale tylko w bardzo liberalnym sensie.Jest technicznie niedokładny i promuje mity.
@forest Wystarczająco uczciwe, ale zachowanie nadal przypomina "wyczerpywanie się" entropii aplikacji klienckiej i nie liczyłbym na to, że odporność SHA1 na preimage będzie trwała zbyt długo, w którym to momencie nieblokujący `/ dev / random`nie byłby już„ doskonale zabezpieczonym CSPRNG ”.Jeśli chodzi o przeglądarki, mówiłem o API JS, a nie o rzeczach, które stos sieciowy jądra (nie przeglądarka!) Robi z numerami sekwencji TCP.Oczywiście w przypadku tego pytania przeglądarka nie zaimplementowałaby `Math.random ()` używając puli blokującej, ale tylko dlatego, że byłoby to głupie, a nie niemożliwe.
@CBHacking Sposób, w jaki SHA1 jest używany w sterowniku losowym, to po prostu mieszanie danych i haszowanie całego 4096-bitowego bufora.Preimage przeciwko SHA1, jaki jest używany w jądrze, byłby ... bardzo nieoczekiwany (założę się, że ChaCha20 zostanie wcześniej uszkodzony).Co do specyfikacji JS, to nie wiem.Prawdopodobnie nie ma żadnych rzeczywistych wymagań dotyczących kryptograficznej losowości, ale jestem pewien, że ma to miejsce w przypadku zachowania nieblokującego.Chodzi o to, że wszystko czego potrzeba to 128 bitów losowości, aby `Math.random ()` było oportunistycznie bezpieczne, bez tworzenia tej części standardu.
Chodzi o to, że kiedy stan twojego CSPRNG wycieknie, będziesz potrzebować entropii, aby ponownie zaszczepić go w losowej wartości.A kiedy teraz spojrzysz na swój mikrokontroler, jest to bardzo zdeterminowane.Jego pamięć będzie zawsze wyglądać tak samo po uruchomieniu, w zależności od układu, który miał nawet taką samą liczbę cykli zegara w momencie, gdy żądana jest liczba losowa.Więc musisz go zasiać, w przeciwnym razie twoja losowa sekwencja jest zawsze taka sama.
A przy zbyt małej entropii ktoś może znaleźć stan twojego CSPRNG brutalną siłą, używając losowej sekwencji do walidacji, jeśli nie będziesz go wystarczająco często wysiewał.Należy pamiętać, że nie tylko stan MC jest bardzo ograniczony, ale sam program nie może być zbyt złożony, ponieważ jest mało miejsca na program i prawdopodobnie większość z niego będzie potrzebna na resztę kodu.
Jeśli użyjesz `getrandom ()`, to nie zwróci, dopóki pula entropii nie zostanie zainicjowana.Gdy to zrobisz, możesz być pewien, że basen nie może być brutalnie zmuszony.
@forest Nie mówimy tutaj o Linuksie.Twój mikrokontroler z prostą implementacją javascript w ogóle nie ma jądra (w sensie jądra Linuksa).Uruchamia się bezpośrednio do swojego środowiska nodejs (takiego jak), które nie ma wywołania `` getrandom () ''.Musisz samodzielnie wykonać wywołanie, biorąc pod uwagę wszystkie wymienione kwestie.
W takim przypadku możesz po prostu wrócić do dowolnego kiepskiego PRNG, jakiego chcesz (XorShift128 +, LFSR, LCG, cokolwiek).Nie ma potrzeby zmiany standardu, aby zapewnić oportunistyczne bezpieczeństwo na jednej platformie.
Cort Ammon
2018-03-17 03:04:51 UTC
view on stackexchange narkive permalink

Podobnie jak inni, chciałbym zwrócić uwagę, że Math.random () nie jest zabezpieczony kryptograficznie, ponieważ zazwyczaj nie jest potrzebny. Ale pójdę dalej i stwierdzę, że nie jest rozsądne pisanie algorytmu bezpiecznego kryptograficznie w specyfikacji, chyba że masz bardzo dobry powód.

Co to znaczy być bezpiecznym kryptograficznie? Cóż, zawsze istnieje nudna definicja „nikt jeszcze nie wie, jak to przerwać”. Ale co się stanie, gdy ktoś go złamie? Jeśli podałeś CSPRNG, musisz również uwzględnić sposób zapytania, który algorytm jest używany, lub w inny sposób zrobić to, aby użytkownik końcowy miał pewność, co otrzymuje.

To również prawdopodobnie prowadzi do konieczności obsługi wielu generatorów, tak aby użytkownik mógł wybrać jeden, któremu ufał. To dodaje ogromnej złożoności. Nagle 1-liniowa funkcja w API stała się pakietem.

Ponadto, kiedy zaczynasz mówić o kryptowalutach, zaczynasz mówić o próbie zapewnienia bezpieczeństwa w generatorze. Wspomniałeś o używaniu AES do generowania liczb losowych: czy Twoja implementacja AES musi być odporna na ataki kanału bocznego? Kiedy piszesz bibliotekę, której celem jest zapewnienie gwarancji kryptograficznych, zadawanie tego pytania nie jest aż tak nierozsądne. Dla specyfikacji może to być strasznie nierozsądne. Odporność na ataki typu side channel to bardzo rzecz do określenia w języku specyfikacji.

A co osiągnąłeś, umieszczając go w specyfikacji? Większość użytkowników PRNG w ogóle nie potrzebuje gwarancji kryptograficznych, więc po prostu zmarnowałeś dla nich cykle procesora. Ci, którzy chcą gwarancji kryptograficznych, prawdopodobnie będą szukać biblioteki, która obsługuje pełny zestaw funkcji potrzebnych do tego, aby czuć się komfortowo z taką kryptografią, więc i tak nie będą ufać Math.random () . Pozostaje tylko wspomniana grupa demograficzna: ludzie, którzy popełnili błąd i użyli narzędzia, kiedy nie powinni. Cóż, z doświadczenia mogę powiedzieć, że główne języki programowania nie są miejscem, w którym można szukać API, którego przez pomyłkę nie można użyć nieprawidłowo. Są pełne wyrażeń „jeśli to zrobisz, to twoja wina”.

Weź również pod uwagę to: jeśli używasz Math.random () i zakładasz gwarancje kryptograficzne, jakie są szanse, że popełnisz kolejny fatalny błąd kryptograficzny w swoim algorytmie? CSPRNG Math.random () może dawać fałszywe poczucie bezpieczeństwa i możemy znaleźć jeszcze więcej błędów!

Oczywiście nie powinieneś używać tego jako _przypuszczonych_ właściwości kryptograficznych.Jeśli tego potrzebujesz, istnieją dedykowane API kryptograficzne (dlatego też zasugerowałem ChaCha8 zamiast pełnej rundy ChaCha20. Pamiętaj, że przerwę kryptograficzną można wykonać przeciwko 7-rundowemu ChaCha).
Zobacz moją poprawkę do pierwotnego pytania, która to wyjaśnia.
@forest Widzę twoją zmianę i myślę, że mój ostatni akapit jest nadal aktualny.Jeśli ktoś uważa, że jego oprogramowanie jest bezpieczne, ponieważ miał szczęście i ktoś inny pomyślał o bezpieczeństwie dla niego, czeka go niegrzeczne przebudzenie.
Spence
2018-03-22 18:51:10 UTC
view on stackexchange narkive permalink

Wydaje się, że wszyscy przeoczyli tu trochę niuansów: algorytmy kryptograficzne wymagają matematycznego i statystycznego losu liczby we wszystkich wykonaniach algorytmu. Oznacza to na przykład podczas gry lub animacji, że możesz użyć psuedorandomowej sekwencji liczb i byłoby to całkowicie w porządku dla „rodzaju losowej” liczby.

Jednak jeśli można by manipulować tą liczbą lub przewidywane, na przykład rozstawiona liczba losowa (co jest domyślnym zachowaniem funkcji losowych systemu Windows), wtedy to ziarno jest w rzeczywistości przewidywalne. Jeśli uda mi się zmanipulować twoją aplikację w celu ponownego uruchomienia, a następnie użyć rozstawionej liczby losowej, mogę przewidzieć, jaką "losową" liczbę wybierzesz. Jeśli jest to możliwe, kryptografia może zostać pokonana. Drugorzędnym problemem może być również to, że niektóre algorytmy wymagają gwarantowanego rozkładu liczb w całym widmie, czego nie mogą zagwarantować niektóre generatory psuedorandom.

Kryptograficznie generatory liczb losowych mają duży zestaw danych wejściowych do tworzenia entropii, na przykład hałas wystrzeliwany z wejścia mikrofonowego, tyknięcia pory dnia, suma kontrolna rejestrów RAM, numery seryjne itp. Tak wiele wejść, jak to tylko możliwe, aby to uczynić, jeśli nie niemożliwe, to niezwykle trudne do zmanipulowania i przewidzenia. W sensie kryptograficznym celem nie jest wydajność, ale „prawdziwa” losowość.

Zatem w zależności od przypadku użycia możesz chcieć odpowiednio losowej, wydajnej implementacji liczby losowej, ale jeśli robisz -hellman do wymiany kluczy potrzebujesz algorytmu bezpiecznego kryptograficznie.

Bobby Baucom
2018-03-24 04:02:59 UTC
view on stackexchange narkive permalink

Kolejną kwestią, o której nikt nie wspomniał (lub po prostu przeoczyłem), jest to, że niektóre zastosowania funkcji Math.random () w rzeczywistości zależą od powtarzalności po rozstawieniu tak samo jak poprzednio czas. Zmiana teraz zniweczy te zastosowania.

Robią to wszystkie deterministyczne PRNG, bezpieczne kryptograficznie lub nie.
jakie przeglądarki są dostarczane z możliwością inicjowania generatora?


To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 3.0, w ramach której jest rozpowszechniana.
Loading...