Hi Isaac,

On 01 Nov 2014, at 05:19, Isaac Karth <isaacka...@gmail.com> wrote:

> Laurens, Using a PRF actually sounds very close to ideal for what I was 
> looking for. If I can convert a map (or record) to a reproducible seed, and 
> have that be independant from other random checks, that's pretty close to 
> exactly what I wanted.

Glad to be of assistance :)

> Looks like if I want to use libraries like clojure.data.generators or 
> bigml.sampling I'd need to amend the random generators to replace calls to 
> the Mersenne Twister function or (def ^:dynamic *rnd* (java.util.Random. 
> 42)). As long as I can figure out how to install caesium/libsodium on 
> Windows, it should theoretically be possible to substitute the PRF there, 
> though I'd have to rewrite some functions to replace the calls to 
> .nextDouble, .nextFloat, et cetera. 

Yeah. You’re probably going to have to do some slightly gnarly 
Float.intBitsToFloat and Double.longBitsToDouble there. Nothing too difficult. 
Just a little ugly ;-)

No clue how to install libsodium on Windows. Sorry! Never tried.

Keep in mind that the docs for Random 
(http://docs.oracle.com/javase/7/docs/api/java/util/Random.html) describe the 
algorithms for e.g. nextFloat, nextGaussian… You may be able to write those as 
a HOF in terms of a side-effecting “next” function. Writing next() is a little 
annoying, of course, because it has some state, when the beauty of the PRF 
approach is that it doesn’t (besides a seed, that is).

This is fine as long as you never want to extract more than one 
largest-bit-extracting-operation (which I think is a double, which needs 64 
bits?). That’s fine: BLAKE2’s output is a whopping 512. If you want to extract 
*many* bits out of BLAKE2, you probably want to look at the `personal` optional 
argument. Just put a little incrementing counter there (it’s 16 bytes), and you 
can get an awful lot of 512-bit sequences. Writing a “streaming” algorithm to 
support next(n) calls is left as an exercise to the reader ;)  

> I'm assuming that just passing the hash as a seed to MT wouldn't work. If I 
> can get away with something like (binding *rnd* (random-number-generator 
> (blake2b [seed thing-to-hash]))) using it becomes trivial. But I'm just 
> knowledgeable enough to know I don't know enough to be confident of that. 
> Granted, the current application is an art project that will be just fine 
> with some non-random randomness, so the tolerance for error is fairly high.

There’s nothing wrong with that, except of course that it’s a bunch of shared 
state, so you may get into concurrency problems :-)

FWIW, the big difference between algorithms like MT and BLAKE2 isn’t in 
“randomness” in the sense that you most likely require it for your game. MT 
(and BLAKE2) are both extremely randomly distributed. The difference is that if 
I can observe a handful of values from MT, I can predict all future values, 
whereas that should not be possible for BLAKE2. (That is a huge 
oversimplification. If you’re interested, my free book, Crypto 101, 
https://www.crypto101.io, touches on this in more detail.)

This is an obvious problem for cryptographic purposes, and *might* be a problem 
for a game, if you’re trying to defend against the scenario of an attacker 
trying to get an “unfair” advantage. It doesn’t sound like you’re terribly 
worried about that, though; plus, it’s nothing you can’t fix later.

Given the number of samples that you need from MT, if you go with the BLAKE->MT 
approach you noted, this wouldn’t even be a problem.

hth
lvh

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to