# Securely shuffling an array with 75 numbers in Go

I have a SHA512 hex string consisting of my random input and that of the user.

Since rand.Seed only accepts a int64 I can never generate enough possibilities to shuffle an array with numbers 1-75: 75! = 2.480914e+109.

So my plan was to loop over the hex string 11 times, each time converting 10 hex characters to decimal and keep on shuffling the numbers.

func Shuffle(t []int, hex string) {
for j := 0; j < 11; j++ {
shuffleSeed, _ := strconv.ParseInt(hex[j*10:(j+1)*10], 16, 64)
rand.Seed(shuffleSeed)
for i := 1; i < len(t); i++ {
r := rand.Intn(i + 1)
if i != r {
t[r], t[i] = t[i], t[r]
}
}
}
}

items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75}

hex := "099b5721eaa9b5bcd87a07366aa175a1fb5b6fa6e5671b93ef443df927474198ec2ae959928f95c46f9fe9621575aa4e1e6f70780b059044da17737fcc99a322"
Shuffle(items, hex)


What do you think about this? I'm not a cryptography expert, not a math expert and certainly not a Go expert (I started yesterday).

Taken from another post I shuffled an array with [1,2,3] and here are the occurrences of each after 1 million times:

167136
166403
166877
166520
166925
166145

• Do you realize that that is a completely deterministic "shuffle"? Run the program any number of times, and the resulting order will be exactly the same. Is that your intention? Aug 6, 2014 at 19:07
• I removed the benchmark part from the post. Anyways, it is my goal to reproduce results given the same input. But the hex part in my sample code will be different every time. Is that what you mean? Aug 6, 2014 at 19:10
• Then where does the hex string come from? You've asked about the randomness properties of the shuffle, but haven't told us much about the source of that randomness, except that it derives from the SHA512 hash of some other data, and it's hard-coded in your shuffling program. Aug 6, 2014 at 19:12
• It doesn't really matter. Since I have no control of it. I generate a random string and the user inputs a string. I generate a SHA512 hash of those two strings together and take the hex value from it. It's only hardcoded there for demonstration purposes of my code. Since I don't know what the user inputs and the user doesn't know what I input we have pseudorandom seed for the shuffling Aug 6, 2014 at 19:53

## Initialization

A simple loop would be easier to maintain than hard-coding an array of 75 values.

items := make([]int, 75, 75)
for i := range items {
items[i] = i + 1
}


## Seeding

The PRNG should be seeded just once.

You are correct that an Int64 seed is "only" capable of producing 264 ≈ 1019 distinct sequences, which is well under 75! ≈ 10109.

However, you should also consider the magnitude of the numbers involved. The age of the Universe is well under 1018 seconds. There is therefore no way you could remotely come close to producing a small fraction of the 75! possible permutations, just due to lack of time. A 64-bit seed is more than enough to generate as many unreproducible sequences as you could ever want.

So, calling rand.Seed(time.Now().UnixNano()) just once in func init() will be sufficient.

• Thank you for taking time to answer! Due to the nature of my "game" I will need to reproduce the results and prove it to the user. So I think I'll keep going with the first 10 hex characters converted to int64 as the seed. Every time the Shuffle function is called the hex will be different. So I'll guess that's fine. Aug 6, 2014 at 20:36