From 3f53d75269a4435af1806e2c885400862b12e7c1 Mon Sep 17 00:00:00 2001 From: Roland Bracewell Shoemaker Date: Sat, 4 Jun 2016 23:51:30 -0700 Subject: [PATCH] Seed math/rand with crypto/rand (#359) * Use crypto/rand to seed math/rand instead of using the default seed * Better seeding+generation and fallback on crypto/rand.Read failure * Remove user warning --- dns_bench_test.go | 6 ++++++ msg.go | 20 ++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/dns_bench_test.go b/dns_bench_test.go index de930087..bccc3d54 100644 --- a/dns_bench_test.go +++ b/dns_bench_test.go @@ -203,3 +203,9 @@ func BenchmarkUnpackMsg(b *testing.B) { _ = msg.Unpack(msgBuf) } } + +func BenchmarkIdGeneration(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = id() + } +} diff --git a/msg.go b/msg.go index 60463b6d..6fe553bf 100644 --- a/msg.go +++ b/msg.go @@ -11,15 +11,30 @@ package dns //go:generate go run msg_generate.go import ( + crand "crypto/rand" + "encoding/binary" "encoding/hex" "math/big" "math/rand" "net" "reflect" "strconv" - "time" ) +func init() { + // Initialize default math/rand source using crypto/rand to provide better + // security without the performance trade-off. + buf := make([]byte, 8) + _, err := crand.Read(buf) + if err != nil { + // Failed to read from cryptographic source, fallback to default initial + // seed (1) by returning early + return + } + seed := binary.BigEndian.Uint64(buf) + rand.Seed(int64(seed)) +} + const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer var ( @@ -1911,7 +1926,8 @@ func compressionLenSearchType(c map[string]int, r RR) (int, bool) { // id returns a 16 bits random number to be used as a // message id. The random provided should be good enough. func id() uint16 { - return uint16(rand.Int()) ^ uint16(time.Now().Nanosecond()) + id32 := rand.Uint32() + return uint16(id32) } // Copy returns a new RR which is a deep-copy of r.