mirror of
https://github.com/octoleo/syncthing.git
synced 2025-04-02 15:51:51 +00:00
lib/rand: Break out random functions into separate package
The intention for this package is to provide a combination of the security of crypto/rand and the convenience of math/rand. It should be the first choice of random data unless ultimate performance is required and the usage is provably irrelevant from a security standpoint. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3186
This commit is contained in:
parent
410d700ae3
commit
e6b78e5d56
@ -35,11 +35,11 @@ import (
|
|||||||
"github.com/syncthing/syncthing/lib/model"
|
"github.com/syncthing/syncthing/lib/model"
|
||||||
"github.com/syncthing/syncthing/lib/osutil"
|
"github.com/syncthing/syncthing/lib/osutil"
|
||||||
"github.com/syncthing/syncthing/lib/protocol"
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
|
"github.com/syncthing/syncthing/lib/rand"
|
||||||
"github.com/syncthing/syncthing/lib/stats"
|
"github.com/syncthing/syncthing/lib/stats"
|
||||||
"github.com/syncthing/syncthing/lib/sync"
|
"github.com/syncthing/syncthing/lib/sync"
|
||||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||||
"github.com/syncthing/syncthing/lib/upgrade"
|
"github.com/syncthing/syncthing/lib/upgrade"
|
||||||
"github.com/syncthing/syncthing/lib/util"
|
|
||||||
"github.com/vitrun/qart/qr"
|
"github.com/vitrun/qart/qr"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
@ -750,7 +750,7 @@ func (s *apiService) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
if curAcc := s.cfg.Options().URAccepted; to.Options.URAccepted > curAcc {
|
if curAcc := s.cfg.Options().URAccepted; to.Options.URAccepted > curAcc {
|
||||||
// UR was enabled
|
// UR was enabled
|
||||||
to.Options.URAccepted = usageReportVersion
|
to.Options.URAccepted = usageReportVersion
|
||||||
to.Options.URUniqueID = util.RandomString(8)
|
to.Options.URUniqueID = rand.String(8)
|
||||||
} else if to.Options.URAccepted < curAcc {
|
} else if to.Options.URAccepted < curAcc {
|
||||||
// UR was disabled
|
// UR was disabled
|
||||||
to.Options.URAccepted = -1
|
to.Options.URAccepted = -1
|
||||||
|
@ -9,15 +9,14 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/config"
|
"github.com/syncthing/syncthing/lib/config"
|
||||||
"github.com/syncthing/syncthing/lib/events"
|
"github.com/syncthing/syncthing/lib/events"
|
||||||
|
"github.com/syncthing/syncthing/lib/rand"
|
||||||
"github.com/syncthing/syncthing/lib/sync"
|
"github.com/syncthing/syncthing/lib/sync"
|
||||||
"github.com/syncthing/syncthing/lib/util"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -114,7 +113,7 @@ func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguratio
|
|||||||
return
|
return
|
||||||
|
|
||||||
passwordOK:
|
passwordOK:
|
||||||
sessionid := util.RandomString(32)
|
sessionid := rand.String(32)
|
||||||
sessionsMut.Lock()
|
sessionsMut.Lock()
|
||||||
sessions[sessionid] = true
|
sessions[sessionid] = true
|
||||||
sessionsMut.Unlock()
|
sessionsMut.Unlock()
|
||||||
|
@ -15,8 +15,8 @@ import (
|
|||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/config"
|
"github.com/syncthing/syncthing/lib/config"
|
||||||
"github.com/syncthing/syncthing/lib/osutil"
|
"github.com/syncthing/syncthing/lib/osutil"
|
||||||
|
"github.com/syncthing/syncthing/lib/rand"
|
||||||
"github.com/syncthing/syncthing/lib/sync"
|
"github.com/syncthing/syncthing/lib/sync"
|
||||||
"github.com/syncthing/syncthing/lib/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// csrfTokens is a list of valid tokens. It is sorted so that the most
|
// csrfTokens is a list of valid tokens. It is sorted so that the most
|
||||||
@ -87,7 +87,7 @@ func validCsrfToken(token string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newCsrfToken() string {
|
func newCsrfToken() string {
|
||||||
token := util.RandomString(32)
|
token := rand.String(32)
|
||||||
|
|
||||||
csrfMut.Lock()
|
csrfMut.Lock()
|
||||||
csrfTokens = append([]string{token}, csrfTokens...)
|
csrfTokens = append([]string{token}, csrfTokens...)
|
||||||
|
@ -39,10 +39,10 @@ import (
|
|||||||
"github.com/syncthing/syncthing/lib/model"
|
"github.com/syncthing/syncthing/lib/model"
|
||||||
"github.com/syncthing/syncthing/lib/osutil"
|
"github.com/syncthing/syncthing/lib/osutil"
|
||||||
"github.com/syncthing/syncthing/lib/protocol"
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
|
"github.com/syncthing/syncthing/lib/rand"
|
||||||
"github.com/syncthing/syncthing/lib/symlinks"
|
"github.com/syncthing/syncthing/lib/symlinks"
|
||||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||||
"github.com/syncthing/syncthing/lib/upgrade"
|
"github.com/syncthing/syncthing/lib/upgrade"
|
||||||
"github.com/syncthing/syncthing/lib/util"
|
|
||||||
|
|
||||||
"github.com/thejerf/suture"
|
"github.com/thejerf/suture"
|
||||||
)
|
)
|
||||||
@ -761,7 +761,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
if opts.URUniqueID == "" {
|
if opts.URUniqueID == "" {
|
||||||
// Previously the ID was generated from the node ID. We now need
|
// Previously the ID was generated from the node ID. We now need
|
||||||
// to generate a new one.
|
// to generate a new one.
|
||||||
opts.URUniqueID = util.RandomString(8)
|
opts.URUniqueID = rand.String(8)
|
||||||
cfg.SetOptions(opts)
|
cfg.SetOptions(opts)
|
||||||
cfg.Save()
|
cfg.Save()
|
||||||
}
|
}
|
||||||
@ -947,7 +947,7 @@ func defaultConfig(myName string) config.Configuration {
|
|||||||
|
|
||||||
if !noDefaultFolder {
|
if !noDefaultFolder {
|
||||||
l.Infoln("Default folder created and/or linked to new config")
|
l.Infoln("Default folder created and/or linked to new config")
|
||||||
folderID := util.RandomString(5) + "-" + util.RandomString(5)
|
folderID := rand.String(5) + "-" + rand.String(5)
|
||||||
defaultFolder = config.NewFolderConfiguration(folderID, locations[locDefFolder])
|
defaultFolder = config.NewFolderConfiguration(folderID, locations[locDefFolder])
|
||||||
defaultFolder.Label = "Default Folder (" + folderID + ")"
|
defaultFolder.Label = "Default Folder (" + folderID + ")"
|
||||||
defaultFolder.RescanIntervalS = 60
|
defaultFolder.RescanIntervalS = 60
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/protocol"
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
|
"github.com/syncthing/syncthing/lib/rand"
|
||||||
"github.com/syncthing/syncthing/lib/util"
|
"github.com/syncthing/syncthing/lib/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -254,7 +255,7 @@ func (cfg *Configuration) prepare(myID protocol.DeviceID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.GUI.APIKey == "" {
|
if cfg.GUI.APIKey == "" {
|
||||||
cfg.GUI.APIKey = util.RandomString(32)
|
cfg.GUI.APIKey = rand.String(32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
package util
|
// Package rand implements functions similar to math/rand in the standard
|
||||||
|
// library, but on top of a secure random number generator.
|
||||||
|
package rand
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
@ -14,6 +16,9 @@ import (
|
|||||||
mathRand "math/rand"
|
mathRand "math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Reader is the standard crypto/rand.Reader, re-exported for convenience
|
||||||
|
var Reader = cryptoRand.Reader
|
||||||
|
|
||||||
// randomCharset contains the characters that can make up a randomString().
|
// randomCharset contains the characters that can make up a randomString().
|
||||||
const randomCharset = "2345679abcdefghijkmnopqrstuvwxyzACDEFGHJKLMNPQRSTUVWXYZ"
|
const randomCharset = "2345679abcdefghijkmnopqrstuvwxyzACDEFGHJKLMNPQRSTUVWXYZ"
|
||||||
|
|
||||||
@ -26,15 +31,10 @@ var (
|
|||||||
defaultSecureRand = mathRand.New(defaltSecureSource)
|
defaultSecureRand = mathRand.New(defaltSecureSource)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// String returns a strongly random string of characters (taken from
|
||||||
// The default RNG should be seeded with something good.
|
|
||||||
mathRand.Seed(RandomInt64())
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomString returns a strongly random string of characters (taken from
|
|
||||||
// randomCharset) of the specified length. The returned string contains ~5.8
|
// randomCharset) of the specified length. The returned string contains ~5.8
|
||||||
// bits of entropy per character, due to the character set used.
|
// bits of entropy per character, due to the character set used.
|
||||||
func RandomString(l int) string {
|
func String(l int) string {
|
||||||
bs := make([]byte, l)
|
bs := make([]byte, l)
|
||||||
for i := range bs {
|
for i := range bs {
|
||||||
bs[i] = randomCharset[defaultSecureRand.Intn(len(randomCharset))]
|
bs[i] = randomCharset[defaultSecureRand.Intn(len(randomCharset))]
|
||||||
@ -42,14 +42,25 @@ func RandomString(l int) string {
|
|||||||
return string(bs)
|
return string(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomInt64 returns a strongly random int64, slowly
|
// Int63 returns a strongly random int63
|
||||||
func RandomInt64() int64 {
|
func Int63() int64 {
|
||||||
|
return defaltSecureSource.Int63()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns a strongly random int64
|
||||||
|
func Int64() int64 {
|
||||||
var bs [8]byte
|
var bs [8]byte
|
||||||
_, err := io.ReadFull(cryptoRand.Reader, bs[:])
|
_, err := io.ReadFull(cryptoRand.Reader, bs[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("randomness failure: " + err.Error())
|
panic("randomness failure: " + err.Error())
|
||||||
}
|
}
|
||||||
return SeedFromBytes(bs[:])
|
return int64(binary.BigEndian.Uint64(bs[:]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intn returns, as an int, a non-negative strongly random number in [0,n).
|
||||||
|
// It panics if n <= 0.
|
||||||
|
func Intn(n int) int {
|
||||||
|
return defaultSecureRand.Intn(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SeedFromBytes calculates a weak 64 bit hash from the given byte slice,
|
// SeedFromBytes calculates a weak 64 bit hash from the given byte slice,
|
@ -4,7 +4,7 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
package util
|
package rand
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ func TestSeedFromBytes(t *testing.T) {
|
|||||||
|
|
||||||
func TestRandomString(t *testing.T) {
|
func TestRandomString(t *testing.T) {
|
||||||
for _, l := range []int{0, 1, 2, 3, 4, 8, 42} {
|
for _, l := range []int{0, 1, 2, 3, 4, 8, 42} {
|
||||||
s := RandomString(l)
|
s := String(l)
|
||||||
if len(s) != l {
|
if len(s) != l {
|
||||||
t.Errorf("Incorrect length %d != %d", len(s), l)
|
t.Errorf("Incorrect length %d != %d", len(s), l)
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ func TestRandomString(t *testing.T) {
|
|||||||
|
|
||||||
strings := make([]string, 1000)
|
strings := make([]string, 1000)
|
||||||
for i := range strings {
|
for i := range strings {
|
||||||
strings[i] = RandomString(8)
|
strings[i] = String(8)
|
||||||
for j := range strings {
|
for j := range strings {
|
||||||
if i == j {
|
if i == j {
|
||||||
continue
|
continue
|
||||||
@ -50,7 +50,7 @@ func TestRandomString(t *testing.T) {
|
|||||||
func TestRandomInt64(t *testing.T) {
|
func TestRandomInt64(t *testing.T) {
|
||||||
ints := make([]int64, 1000)
|
ints := make([]int64, 1000)
|
||||||
for i := range ints {
|
for i := range ints {
|
||||||
ints[i] = RandomInt64()
|
ints[i] = Int64()
|
||||||
for j := range ints {
|
for j := range ints {
|
||||||
if i == j {
|
if i == j {
|
||||||
continue
|
continue
|
@ -4,7 +4,7 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
package util
|
package rand
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
@ -4,7 +4,7 @@
|
|||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
package util
|
package rand
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
@ -19,10 +18,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
mr "math/rand"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/syncthing/syncthing/lib/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -48,7 +48,7 @@ func NewCertificate(certFile, keyFile, tlsDefaultCommonName string, tlsRSABits i
|
|||||||
notAfter := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)
|
notAfter := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)
|
||||||
|
|
||||||
template := x509.Certificate{
|
template := x509.Certificate{
|
||||||
SerialNumber: new(big.Int).SetInt64(mr.Int63()),
|
SerialNumber: new(big.Int).SetInt64(rand.Int63()),
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: tlsDefaultCommonName,
|
CommonName: tlsDefaultCommonName,
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user