github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/randutil/rand.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-2020 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 // Package randutil initialises properly random value generation and 21 // exposes a streamlined set of functions for it, including for crypto 22 // random tokens. 23 package randutil 24 25 import ( 26 "crypto/sha256" 27 "encoding/binary" 28 "math/rand" 29 "net" 30 "os" 31 "sync" 32 "time" 33 ) 34 35 func init() { 36 // golang does not init Seed() itself 37 rand.Seed(time.Now().UnixNano() + int64(os.Getpid())) 38 } 39 40 var moreMixedSeedOnce sync.Once 41 42 func moreMixedSeed() { 43 moreMixedSeedOnce.Do(func() { 44 h := sha256.New224() 45 // do this instead of asking for time and pid again 46 var b [8]byte 47 rand.Read(b[:]) 48 h.Write(b[:]) 49 // mix in the hostname 50 if hostname, err := os.Hostname(); err == nil { 51 h.Write([]byte(hostname)) 52 } 53 // mix in net interfaces hw addresses (MACs etc) 54 if ifaces, err := net.Interfaces(); err == nil { 55 for _, iface := range ifaces { 56 h.Write(iface.HardwareAddr) 57 } 58 } 59 hs := h.Sum(nil) 60 s := binary.LittleEndian.Uint64(hs[0:]) 61 rand.Seed(int64(s)) 62 }) 63 } 64 65 const letters = "BCDFGHJKLMNPQRSTVWXYbcdfghjklmnpqrstvwxy0123456789" 66 67 // RandomString returns a random string of length length. 68 // 69 // The vowels are omitted to avoid that words are created by pure 70 // chance. Numbers are included. 71 // 72 // Not cryptographically secure. 73 func RandomString(length int) string { 74 out := "" 75 for i := 0; i < length; i++ { 76 out += string(letters[rand.Intn(len(letters))]) 77 } 78 79 return out 80 } 81 82 // Re-exported from math/rand for streamlining. 83 var ( 84 Intn = rand.Intn 85 Int63n = rand.Int63n 86 ) 87 88 // RandomDuration returns a random duration up to the given length. 89 func RandomDuration(d time.Duration) time.Duration { 90 // try to switch to more mixed seed to avoid subsets of a 91 // fleet of machines with similar initial conditions to behave 92 // the same 93 moreMixedSeed() 94 return time.Duration(Int63n(int64(d))) 95 }