diff --git a/client.go b/client.go index f41f2e47..f0b4c060 100644 --- a/client.go +++ b/client.go @@ -3,7 +3,6 @@ package quic import ( "bytes" "errors" - "math/rand" "net" "strings" "sync/atomic" @@ -52,9 +51,10 @@ func NewClient(host string, cryptoChangeCallback CryptoChangeCallback, versionNe return nil, err } - // TODO: generate cryptographically secure random ConnectionID - rand.Seed(time.Now().UTC().UnixNano()) - connectionID := protocol.ConnectionID(rand.Int63()) + connectionID, err := utils.GenerateConnectionID() + if err != nil { + return nil, err + } hostname, _, err := net.SplitHostPort(host) if err != nil { diff --git a/utils/connection_id.go b/utils/connection_id.go new file mode 100644 index 00000000..e0227d07 --- /dev/null +++ b/utils/connection_id.go @@ -0,0 +1,18 @@ +package utils + +import ( + "crypto/rand" + "encoding/binary" + + "github.com/lucas-clemente/quic-go/protocol" +) + +// GenerateConnectionID generates a connection ID using cryptographic random +func GenerateConnectionID() (protocol.ConnectionID, error) { + b := make([]byte, 8, 8) + _, err := rand.Read(b) + if err != nil { + return 0, err + } + return protocol.ConnectionID(binary.LittleEndian.Uint64(b)), nil +} diff --git a/utils/connection_id_test.go b/utils/connection_id_test.go new file mode 100644 index 00000000..cd3f9af1 --- /dev/null +++ b/utils/connection_id_test.go @@ -0,0 +1,17 @@ +package utils + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Connection ID generation", func() { + It("generates random connection IDs", func() { + c1, err := GenerateConnectionID() + Expect(err).ToNot(HaveOccurred()) + Expect(c1).ToNot(BeZero()) + c2, err := GenerateConnectionID() + Expect(err).ToNot(HaveOccurred()) + Expect(c1).ToNot(Equal(c2)) + }) +})