2009-03-27 10 views
5

Piszę funkcję kid sister encryption i potrzebuję PRNG, który produkuje spójne wyniki w różnych systemach operacyjnych (więc nie ma matematyki zmiennoprzecinkowej, korzystając ze sprzętu lub oprogramowania na poziomie systemu). Byłoby to miłe, ale niekonieczne, ponieważ PRNG miał okres dłuższy niż 2 .Potrzebuję przenośny, zgodny generator liczb pseudolosowych

Obecnie używam 32-bitowy 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; 

Ale martwię się, bo nie bardzo rozumiem jak to działa. Na przykład oryginalne źródło nie miało możliwości ustawienia nasion, więc dodałem jeden, ale nie wiem, czy wybrałem poprawną zmienną dla nasienia.

Tak, to wszystko sprowadza się do

  1. Wiesz modułu na CPAN, który pasuje do moich potrzeb?
  2. Jeśli nie, czy znasz algorytm, który pasuje do moich potrzeb?

Odpowiedz

7

Math::Random::Auto to moduł CPAN realizujący znany PRNG Mersenne twister.

+0

Ale czy jest to zgodne? Jeśli założę to na 5, da takie same wyniki na Linuksie, BSD, OS X, Win32, itd. –

+0

Jeśli przeczytasz ten link do Wikipedii, zauważysz, że pierwszą rzeczą, o której mówi w "Aplikacja", jest to, że nie jest odpowiedni do kryptografii. – cjm

+0

@cjm: jeśli czytasz ten link do siostrzanej siostrzyczki, zauważysz, że to prawdopodobnie nie ma znaczenia. – ysth

7

Spróbuj użyć LFSR - Linear Feedback Shift Register.. T he first link na zewnętrznych linkach ma wszystko, czego potrzebujesz, aby wytworzyć dowolną liczbę bitów losowości. Zaletą jest to, że jest łatwa do wdrożenia i można to zrobić za pomocą wszystkich liczb całkowitych.

Użyłem go z powodzeniem w projekcie 8051. Z perlem będzie to proste.

Aktualizacja:

Oto szybka realizacja Perl z 8-bitowy LFSR:

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; 
    } 
} 

Ten kod jest tylko prototyp. Gdybym chciał użyć go w produkcji, prawdopodobnie owinąłbym go w obiekt i skonfigurowałbym rozmiar rejestru. Wtedy będziemy pozbyć się tych nieznośnych wspólnych zmiennych.

+0

Kliknięcie na wiki pokazuje całą rodzinę fascynujących funkcji. To jest po prostu schludne. – jettero