From 7175f06e626a0d3494c7e583a105a0f0b66738f3 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 5 Sep 2023 09:02:40 -0700 Subject: [PATCH] util/rands: add package with HexString func We use it a number of places in different repos. Might as well make one. Another use is coming. Updates #cleanup Change-Id: Ib7ce38de0db35af998171edee81ca875102349a4 Signed-off-by: Brad Fitzpatrick --- cmd/tailscaled/depaware.txt | 1 + ipn/localapi/localapi.go | 11 ++------ tstest/integration/testcontrol/testcontrol.go | 6 ++--- util/rands/rands.go | 25 +++++++++++++++++++ util/rands/rands_test.go | 15 +++++++++++ 5 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 util/rands/rands.go create mode 100644 util/rands/rands_test.go diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 4ecac3d83..1367bbebc 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -343,6 +343,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/util/osshare from tailscale.com/ipn/ipnlocal+ W tailscale.com/util/pidowner from tailscale.com/ipn/ipnauth tailscale.com/util/racebuild from tailscale.com/logpolicy + tailscale.com/util/rands from tailscale.com/ipn/localapi tailscale.com/util/ringbuffer from tailscale.com/wgengine/magicsock tailscale.com/util/set from tailscale.com/health+ tailscale.com/util/singleflight from tailscale.com/control/controlclient+ diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index b4a015d0e..8b0cd8f54 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -7,8 +7,6 @@ package localapi import ( "bytes" "context" - "crypto/rand" - "encoding/hex" "encoding/json" "errors" "fmt" @@ -49,6 +47,7 @@ import ( "tailscale.com/util/httpm" "tailscale.com/util/mak" "tailscale.com/util/osdiag" + "tailscale.com/util/rands" "tailscale.com/version" ) @@ -118,12 +117,6 @@ var handler = map[string]localAPIHandler{ "query-feature": (*Handler).serveQueryFeature, } -func randHex(n int) string { - b := make([]byte, n) - rand.Read(b) - return hex.EncodeToString(b) -} - var ( // The clientmetrics package is stateful, but we want to expose a simple // imperative API to local clients, so we need to keep track of @@ -318,7 +311,7 @@ func (h *Handler) serveBugReport(w http.ResponseWriter, r *http.Request) { defer h.b.TryFlushLogs() // kick off upload after bugreport's done logging logMarker := func() string { - return fmt.Sprintf("BUG-%v-%v-%v", h.backendLogID, h.clock.Now().UTC().Format("20060102150405Z"), randHex(8)) + return fmt.Sprintf("BUG-%v-%v-%v", h.backendLogID, h.clock.Now().UTC().Format("20060102150405Z"), rands.HexString(16)) } if envknob.NoLogsNoSupport() { logMarker = func() string { return "BUG-NO-LOGS-NO-SUPPORT-this-node-has-had-its-logging-disabled" } diff --git a/tstest/integration/testcontrol/testcontrol.go b/tstest/integration/testcontrol/testcontrol.go index 093a38d1d..53dfa3897 100644 --- a/tstest/integration/testcontrol/testcontrol.go +++ b/tstest/integration/testcontrol/testcontrol.go @@ -7,7 +7,6 @@ package testcontrol import ( "bytes" "context" - crand "crypto/rand" "encoding/binary" "encoding/json" "errors" @@ -34,6 +33,7 @@ import ( "tailscale.com/types/key" "tailscale.com/types/logger" "tailscale.com/types/ptr" + "tailscale.com/util/rands" ) const msgLimit = 1 << 20 // encrypted message length limit @@ -569,9 +569,7 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key. authURL := "" if requireAuth { - randHex := make([]byte, 10) - crand.Read(randHex) - authPath := fmt.Sprintf("/auth/%x", randHex) + authPath := fmt.Sprintf("/auth/%s", rands.HexString(20)) s.addAuthPath(authPath, nk) authURL = s.BaseURL() + authPath } diff --git a/util/rands/rands.go b/util/rands/rands.go new file mode 100644 index 000000000..d83e1e558 --- /dev/null +++ b/util/rands/rands.go @@ -0,0 +1,25 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// Package rands contains utility functions for randomness. +package rands + +import ( + crand "crypto/rand" + "encoding/hex" +) + +// HexString returns a string of n cryptographically random lowercase +// hex characters. +// +// That is, HexString(3) returns something like "0fc", containing 12 +// bits of randomness. +func HexString(n int) string { + nb := n / 2 + if n%2 == 1 { + nb++ + } + b := make([]byte, nb) + crand.Read(b) + return hex.EncodeToString(b)[:n] +} diff --git a/util/rands/rands_test.go b/util/rands/rands_test.go new file mode 100644 index 000000000..5813f2bb4 --- /dev/null +++ b/util/rands/rands_test.go @@ -0,0 +1,15 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package rands + +import "testing" + +func TestHexString(t *testing.T) { + for i := 0; i <= 8; i++ { + s := HexString(i) + if len(s) != i { + t.Errorf("HexString(%v) = %q; want len %v, not %v", i, s, i, len(s)) + } + } +}