diff --git a/vlib/crypto/rand/rand_test.v b/vlib/crypto/rand/rand_test.v index b0a680a866..d4913f38b9 100644 --- a/vlib/crypto/rand/rand_test.v +++ b/vlib/crypto/rand/rand_test.v @@ -4,7 +4,7 @@ import crypto.rand -fn test_crypto_rand() { +fn test_crypto_rand_read() { no_bytes := 100 max_percentage_diff := 20 @@ -28,3 +28,16 @@ fn test_crypto_rand() { assert diff_percentage <= max_percentage_diff } + +fn test_crypto_rand_read_u64() { + max := u64(200) + r1 := rand.read_u64(max) or { + assert false + return + } + r2 := rand.read_u64(max) or { + assert false + return + } + assert r1 > u64(0) && r2 > u64(0) && r1 < max && r2 < max +} diff --git a/vlib/crypto/rand/utils.v b/vlib/crypto/rand/utils.v new file mode 100644 index 0000000000..7e7be7c36b --- /dev/null +++ b/vlib/crypto/rand/utils.v @@ -0,0 +1,63 @@ +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module rand + +import( + math + encoding.binary +) + +pub fn read_u64(max u64) u64? { + if max <= u64(0) { + return error('crypto.rand: argument to read_u64 is <= 0') + } + // bitlen := int(math.floor(math.log2(f64(max))+1)) + bitlen := int(math.floor(math.log(f64(max))/math.log(2)) + 1) + if bitlen == 0 { + return u64(0) + } + k := (bitlen + 7) / 8 + mut b := u64(bitlen % 8) + if b == u64(0) { + b = u64(8) + } + mut n := u64(0) + for { + mut bytes := read(k) or { + return error(err) + } + bytes[0] &= byte(int(u64(1)< 1 { + n = u64(u32(x[1])<= 8; k++ { + z[k] = binary.big_endian_u64(b.slice(i-8, i)) + i -= 8 + } + if i > 0 { + mut d := u64(0) + for s := u64(0); i > 0; s += u64(8) { + d |= u64(u64(b[i-1]) << s) + i-- + } + z[z.len-1] = d + } + return z +}