2009-03-27 10 views
5

Sto scrivendo una funzione kid sister encryption e ho bisogno di un PRNG che produca risultati coerenti su tutti i sistemi operativi (quindi nessuna matematica in virgola mobile, sfruttando l'hardware o software di sistema). Sarebbe bello, ma non necessario, perché il PRNG aveva un periodo più lungo di 2 .Ho bisogno di un generatore di numeri pseudocasuale portatile, coerente

Attualmente sto usando un 32 bit Xorshift:

#!/usr/bin/perl 

use strict; 
use warnings; 

{ 
    use integer; #use integer math 
    my $x = 123456789; 
    my $y = 362436069; 
    my $w = 88675123; 
    my $z = 521288629; 

    sub set_random_seed { 
     $w = shift; 
    } 

    sub random { 
     my $t = $x^($x << 11); 
     $x = $y; 
     $y = $z; 
     $z = $w; 
     my $rand = $w = ($w^($w >> 19))^($t^($t >> 8)); 
     return $rand % 256; #scale it back to a byte at a time 
    } 
} 

set_random_seed(5); 
print map { random(), "\n" } 1 .. 10; 

Ma io sono preoccupato perché io non capisco come funziona. Ad esempio, la fonte originale non aveva la possibilità di impostare il seme, quindi ne ho aggiunto uno, ma non so se ho scelto la variabile corretta per il seme.

Quindi, tutto questo si riduce a

  1. Sapete di un modulo su CPAN che si adatta alle mie esigenze?
  2. In caso contrario, conosci un algoritmo che si adatta alle mie esigenze?

risposta

7

Math::Random::Auto è un modulo CPAN che implementa il noto PRNG Mersenne twister.

+0

Ma è coerente? Se lo seminerò con 5, produrrebbe gli stessi risultati su Linux, BSD, OS X, Win32, ecc. –

+0

Se leggi il link di Wikipedia, noterai che la prima cosa che dice in "Applicazione" è che non è adatto per la crittografia. – cjm

+0

@cjm: se leggi il link di crittografia di kid kid, noterai che probabilmente non è rilevante. – ysth

7

Provare a utilizzare un LFSR - Linear Feedback Shift Register.. T he first link sui link esterni ha tutto il necessario per produrre un numero qualsiasi di bit di casualità. La cosa bella di questo è che è facile da implementare e può essere fatto usando tutti i numeri interi.

L'ho usato con successo su un progetto 8051. Con perl sarà un gioco da ragazzi.

Aggiornamento:

Ecco un'implementazione perl rapida di un LFSR 8 bit:

use strict; 
use warnings; 

use List::Util qw(reduce); 
use vars qw($a $b); 

print 'Taps: ', set_taps(8, 7, 2, 1), "\n"; 
print 'Seed: ', seed_lfsr(1), "\n"; 
print read_lfsr(), "\n" for 1..10; 

BEGIN { 
    my $tap_mask; 
    my $lfsr = 0; 

    sub read_lfsr { 
     $lfsr = ($lfsr >> 1)^(-($lfsr & 1) & $tap_mask); 

     return $lfsr; 
    } 

    sub seed_lfsr { 
     $lfsr = shift || 0; 
     $lfsr &= 0xFF; 
    } 

    sub set_taps { 
     my @taps = @_; 

     $tap_mask = reduce { $a + 2**$b } 0, @taps; 

     $tap_mask >>= 1; 

     $tap_mask &= 0xFF; 

     return $tap_mask; 
    } 
} 

Questo codice è solo un prototipo. Se volessi usarlo in produzione probabilmente lo avvolgerei in un oggetto e rendere configurabile la dimensione del registro. Quindi ci libereremmo di quelle fastidiose variabili condivise.

+0

Cliccando sul wiki si mostra un'intera famiglia di funzioni affascinanti. Questo è semplicemente pulito. – jettero

Problemi correlati