2016-01-03 2 views
5

Wie generieren Sie cryptographically secure Floats in Javascript?Kryptographisch sicher Float

Dies sollte ein Plug-in für Math.random sein, mit Bereich (0, 1), aber kryptographisch sicher. Anwendungsbeispiel

cryptoFloat.random(); 
0.8083966837153522 

Secure random numbers in javascript? zeigt, wie ein kryptografisch sicheren Uint32Array erstellen. Vielleicht könnte das irgendwie in einen Float umgewandelt werden?

  • The Mozilla Uint32Array documentation war nicht ganz klar, wie man von einem Int umwandelt.
  • Google war auch nicht auf den Punkt.
  • Float32Array.from(someUintBuf); gab immer eine ganze Zahl.
  • +1

    Müssen Sie nur Browser unterstützen, die 'window.crypto' unterstützen? –

    +1

    @ T.J.Crowder: Eigentlich würde für meinen Anwendungsfall Firefox ausreichen. Je allgemeiner, desto besser. –

    +1

    Nur um es auf einer hohen Ebene zu markieren: JavaScript Floats sind 64-Bit-IEEE-754-Nummern (na ja, Sie können eine 32-Bit-eine erhalten, wenn Sie wollen), was bedeutet, dass sie nur 53 (effektive) signifikante Binärziffern haben . Für fast jeden kryptografischen Zweck reicht das nicht aus. –

    Antwort

    4

    Da der folgende Code recht einfach ist und functionally equivalent to the division method, hier ist die alternate method of altering the bits. (Dieser Code ist kopiert und geändert von @ T.J. Crowder sehr hilfreiche Antwort).

    // A buffer with just the right size to convert to Float64 
     
    let buffer = new ArrayBuffer(8); 
     
    
     
    // View it as an Int8Array and fill it with 8 random ints 
     
    let ints = new Int8Array(buffer); 
     
    window.crypto.getRandomValues(ints); 
     
    
     
    // Set the sign (ints[7][7]) to 0 and the 
     
    // exponent (ints[7][6]-[6][5]) to just the right size 
     
    // (all ones except for the highest bit) 
     
    ints[7] = 63; 
     
    ints[6] |= 0xf0; 
     
    
     
    // Now view it as a Float64Array, and read the one float from it 
     
    let float = new DataView(buffer).getFloat64(0, true) - 1; 
     
    document.body.innerHTML = "The number is " + float;

    Erläuterung:

    The format of a IEEE754 double 1 Vorzeichenbit (ints[7][7]), 11 Exponentenbits (ints[7][6]-ints[6][5]) und der Rest als Mantisse (die gilt die Werte). Die Formel zur Berechnung ist

    (-1)<sup>sign</sup> (1 + Σ<sub>i=1</sub><sup>52</sup> b<sub>52-i</sub> 2<sup>i</sup>) * 2<sup>e-1023</sup>

    den Faktor auf 1 zu setzen, der Exponent 1023 sein muss es 11 Bits hat, so dass die Bit höchster Ordnung gibt 2048. Dies muss auf 0 gesetzt werden, die anderen Bits zu 1.

    +0

    Kühl. Hast du festgestellt, dass die subnormale Sache kein Problem war, oder ...? –

    +0

    @ T.J.Crowder: Dies verwendet die maximale Anzahl von Bits. Berücksichtigen Sie, dass jedes Bit der Mantisse das Intervall um 2 "aufteilt": Das erste addiert entweder 1/2 oder 0, das zweite addiert 1/4 oder 0, das dritte 1/8 oder 0, ... Es scheint, als ob der Problem der subnormalen Zahlen tritt nur auf, wenn Sie den Exponenten enthalten. (Dann sind die Zahlen eindeutig logarithmisch beabstandet). Vielen Dank. Ich hätte es wahrscheinlich ohne deine Hilfe nicht geschafft. (hatte vorher noch nicht mit JS FloatArrays usw. gearbeitet) –

    +1

    Gern geschehen, ich bin froh, dass das geholfen hat. Zu den Unternormalen, jetzt habe ich es ein paar Stunden später wieder gelesen, ich glaube nicht, dass es ein Problem ist; Ihre Methode sollte die Werte gleichmäßig über den Zahlenbereich verteilen, den "Zahl" genau darstellen kann. Subnormale erweitern den Bereich durch Kompromisse bei der Präzision. Ich glaube nicht, dass du etwas aus einer Zufälligkeitsperspektive verlierst, indem du sie auslässt. –

    Verwandte Themen