Re: Where to get a good seed for srandom()

2005-07-20 Thread Jack Bates
Marcus Watts states:


 Another way to fix this, is if you're using %, make sure the random
 value you plug into % is smaller than the largest multiple.  For 189,
 that would be 22724694*189 or 4294967296U.  If the number you get
 is larger than this, discard it and obtain another random number.
 If you throw out the last 130 values, you've now got a fair generator.


This is good advice.

CHEERS

-- 
Jack Bates
Venice, CA, USA
I play Texas Hold'Em at http://www.fulltiltpoker.com



Re: Where to get a good seed for srandom()

2005-07-19 Thread Alexander Farber
Hi,

that is an interesting (off-)topic :-) May I ask the very last question?

If % is not good enough for getting random values in a range, then what is?

I see a lot of arc4random() % ... when grepping the /usr/src on OpenBSD.

And my (probably too naive) approach to shuffling 32 cards has been:

void shuffle(card deck[])
{
unsignedk, n;
card   tmp;

for (k = 0; k  32; k++) {
/* find the new position for the card at k */
n = arc4random() % 32;

/* swap the cards at the indices k and n */
tmp = deck[n];
deck[n] = deck[k];
deck[k] = tmp;
}
}

Regards
Alex

2005/7/18, Jack Bates [EMAIL PROTECTED]:
 
 I happen to be very familiar with this subject, having developed, analyzed
 and qualified two different card-shuffling algorithms for real-money play
 in the online card game business.  There is a fair bit of literature on
 this subject.
 
 Some tips that I can share without breaking an NDA:
 
 1) Do not use current time other than as an _adjunct_ to initial seeding
 of a quality PRNG.  Under OpenBSD, you can obtain a good initial seed from
 /dev/?random, so why bother using time at all?
 
 2) Use of a hardware device (HRNG), such as the SG-100 from Protego
 (Sweden) or motherboard HRNG is preferred to a PRNG, as its state cannot
 be observed in memory.
 
 3) Qualify the quality of your random seed if it is coming from an HRNG.
 Some of these things have warm-up time and will initially produce poor
 entropy.
 
 4) Do not use the % (modulo) operator to select a card.  The residues from
 % introduce small amounts of bias, and this is a disqualifying factor for
 regulated gaming.
 
 5) Knuth's Art of Computer Programming has an algorithm for fairly
 shuffling cards.  Unfortunately it assumes perfect floating-point math,
 which a computer cannot really do.  The algorithm, however, is worth
 studying.
 
 CHEERS
 
 --
 Jack Bates
 Venice, CA, USA
 I play Texas Hold'Em at http://www.fulltiltpoker.com



Re: Where to get a good seed for srandom()

2005-07-19 Thread Marcus Watts
Alexander Farber [EMAIL PROTECTED] asks:
...
 If % is not good enough for getting random values in a range, then what is?
...

Actually, % 32 is fine (or any reasonably small power of 2).  Modulo
any odd number is guaranteed to have at least a small problem, and
module a large enough number is going to start to get really bad.

To illustrate the problem, suppose you had a perfect rand
function that returned numbers in the range 0-255.  On average,
about half the time, the numbers will be even or odd.  That's %2.
Any power of two up to 128 will work perfectly as well.
Now, suppose instead we take it module 189.  For values out of
the rand function less than 189, things work fine.  However, there
are only 67 values = 189, so the output of this will be twice
as likely to pick values 0-66 as it is values 67-188.  That's
sort of really bad.  Now, the output from arc4random() is really
quite large, so for small values of N, %N will be fine.  It's
only for large values of N that this roundoff problem is going
to be significant.  The for N=289 and using arcrandom(), the bias
is only 0.00044, so it would take a lot of values to estimate
this empirically.

Another way to fix this, is if you're using %, make sure the random
value you plug into % is smaller than the largest multiple.  For 189,
that would be 22724694*189 or 4294967296U.  If the number you get
is larger than this, discard it and obtain another random number.
If you throw out the last 130 values, you've now got a fair generator.

rc4 is a common cheap expansion function for random functions.
A higher quality but slower method is to use sha-1 or some other
function.  Another possible alternative is to use a symmetric algorithm
such as aes or blowfish.  Typically you would plug your seed plus
a counter into the input of these functions, then supply the output
(perhaps with some truncation) as the result of your function.

Incidently, I think your card shuffling algorith has some of the same
problems as the rc4 key schedule algorithm.  You might want to read up
on that.

-Marcus Watts



Re: Where to get a good seed for srandom()

2005-07-19 Thread Hannah Schroeter
Hello!

On Mon, Jul 18, 2005 at 11:02:54AM -0700, Jack Bates wrote:
[...]

4) Do not use the % (modulo) operator to select a card.  The residues from
% introduce small amounts of bias, and this is a disqualifying factor for
regulated gaming.

Does that point still hold, assuming I use a modulus which is a divisor
of the range of the original random values?

I use the following algorithm, assuming a random generator that
yields k-bit unsigned numbers of randomness, to yield random numbers
between 0 and n-1:

- determine the maximum multiple of n which is = 2^k, call that m
- get a random number from the source generator, until that number
  is  m, call that r
- return (r % n)

By re-getting random numbers, I transform the source (P)RNG into
a (P)RNG that yields numbers = 0,  m, and m is a multiple of n,
that should eliminate the bias, as long as the (P)RNG doesn't
have a bias if the previous number it yielded was = m.

[...]

Kind regards,

Hannah.



Where to get a good seed for srandom()

2005-07-18 Thread Alexander Farber
Hi,

I'm developing a small multiplayer card game on OpenBSD 
(but also try to keep it at least compilable on Linux). 

After 32 cards have been shuffled, each of 3 players gets 
10 cards. At the moment I use the sum of time()s when any 
data has been received from a player as the seed value:

  typedef struct client_s {
  .
time_t  last;
  } client;

  .
  srandom((cp-last + prev-last + next-last) % UINT_MAX);

I'm worried though, that someone will look at my source code
and since those 3 time()s are probably contained in the last 10
minutes, then there aren't actually that many variants. 

So an attacker will prepare a list of possible variants, 
filter them by looking at the 10 cards at his own hand and 
then with each played trick will have a better idea, 
what cards do the other players have in their hands.

Where could I get a better seed? Should I use the initstate()
and srandomdev() routines and how to use them (in which 
order)?

Regards
Alex

PS: Also I'm worried, if my naive code above 
   overflows and maybe in few years it'll be equal to 
 srandom(UINT_MAX % UINT_MAX);  or similar...



Re: Where to get a good seed for srandom()

2005-07-18 Thread Said Outgajjouft

Artur Grabowski wrote:


A good suggestion might be to use arc4random(3) instead of random(3).

If the security of your application depends on randomness, you should
really pay an expert to help you do it. Randomness is harder than it
looks and most likely you will screw it up very badly (a few years ago
some online Black Jack lost a lot of money because they improved their
randomness by adding the current time to it).

//art

 



Can you actually only use software code to achieve true randomness?
Doesn't it require a hardware solution (like a hardware that listens
to background radiation to create random numbers)?


OpenBSD keep it real by keeping it free!
Said Outgajjouft



Re: Where to get a good seed for srandom()

2005-07-18 Thread Artur Grabowski
Said Outgajjouft [EMAIL PROTECTED] writes:

 Can you actually only use software code to achieve true randomness?

Who cares?

You don't need true randomness. You need good enough. What good
enough is depends on your application, the potential threats, the
sophisitcation of the attackers, the other secuirty problems your
application might have, etc. Even the best true randomness doesn't
protect your application from rubber hose cryptanalysis.

//art



Re: Where to get a good seed for srandom()

2005-07-18 Thread Alexander Farber
Thank you for both good advices.

Until I have money to pay an expert and my card game isn't using real money... 

Would arc4random() % 32 be the usual way to get random integers from 0 to 31, 
or are some bits of the returned value more random than the others?

And what is the highest number returned by arc4random(), is it RAND_MAX?
The man page doesn't elaborate on this subject

Regards
Alex

18 Jul 2005 11:50:25 +0200, Artur Grabowski [EMAIL PROTECTED]:
 A good suggestion might be to use arc4random(3) instead of random(3).
 
 If the security of your application depends on randomness, you should
 really pay an expert to help you do it. Randomness is harder than it
 looks and most likely you will screw it up very badly (a few years ago
 some online Black Jack lost a lot of money because they improved their
 randomness by adding the current time to it).



Re: Where to get a good seed for srandom()

2005-07-18 Thread Artur Grabowski
Alexander Farber [EMAIL PROTECTED] writes:

 And what is the highest number returned by arc4random(), is it RAND_MAX?
 The man page doesn't elaborate on this subject

32 bits.

//art



Re: Where to get a good seed for srandom()

2005-07-18 Thread Damien Miller

Alexander Farber wrote:

Hi,

I'm developing a small multiplayer card game on OpenBSD 
(but also try to keep it at least compilable on Linux). 

After 32 cards have been shuffled, each of 3 players gets 
10 cards. At the moment I use the sum of time()s when any 
data has been received from a player as the seed value:


  typedef struct client_s {
  .
time_t  last;
  } client;

  .
  srandom((cp-last + prev-last + next-last) % UINT_MAX);

I'm worried though, that someone will look at my source code
and since those 3 time()s are probably contained in the last 10
minutes, then there aren't actually that many variants. 


use arc4random(). If you need to port it to Linux, include an
arc4random() replacement. If you like, you can copy the one from
portable OpenSSH.

-d



Re: Where to get a good seed for srandom()

2005-07-18 Thread Jack Bates
Good day:

I happen to be very familiar with this subject, having developed, analyzed
and qualified two different card-shuffling algorithms for real-money play
in the online card game business.  There is a fair bit of literature on
this subject.

Some tips that I can share without breaking an NDA:

1) Do not use current time other than as an _adjunct_ to initial seeding
of a quality PRNG.  Under OpenBSD, you can obtain a good initial seed from
/dev/?random, so why bother using time at all?

2) Use of a hardware device (HRNG), such as the SG-100 from Protego
(Sweden) or motherboard HRNG is preferred to a PRNG, as its state cannot
be observed in memory.

3) Qualify the quality of your random seed if it is coming from an HRNG. 
Some of these things have warm-up time and will initially produce poor
entropy.

4) Do not use the % (modulo) operator to select a card.  The residues from
% introduce small amounts of bias, and this is a disqualifying factor for
regulated gaming.

5) Knuth's Art of Computer Programming has an algorithm for fairly
shuffling cards.  Unfortunately it assumes perfect floating-point math,
which a computer cannot really do.  The algorithm, however, is worth
studying.

CHEERS

-- 
Jack Bates
Venice, CA, USA
I play Texas Hold'Em at http://www.fulltiltpoker.com