2019-08-06 13:44:08 +02:00
|
|
|
// Package random holds a few functions for working with random numbers
|
|
|
|
package random
|
|
|
|
|
2019-08-25 09:39:31 +02:00
|
|
|
import (
|
2020-11-18 13:03:01 +01:00
|
|
|
cryptorand "crypto/rand"
|
2019-08-25 09:39:31 +02:00
|
|
|
"encoding/base64"
|
2020-11-18 15:02:53 +01:00
|
|
|
"encoding/binary"
|
2020-11-18 13:03:01 +01:00
|
|
|
mathrand "math/rand"
|
2019-08-06 13:44:08 +02:00
|
|
|
|
2019-08-25 09:39:31 +02:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
// String create a random string for test purposes.
|
|
|
|
//
|
|
|
|
// Do not use these for passwords.
|
2019-08-06 13:44:08 +02:00
|
|
|
func String(n int) string {
|
|
|
|
const (
|
|
|
|
vowel = "aeiou"
|
|
|
|
consonant = "bcdfghjklmnpqrstvwxyz"
|
|
|
|
digit = "0123456789"
|
|
|
|
)
|
|
|
|
pattern := []string{consonant, vowel, consonant, vowel, consonant, vowel, consonant, digit}
|
|
|
|
out := make([]byte, n)
|
|
|
|
p := 0
|
|
|
|
for i := range out {
|
|
|
|
source := pattern[p]
|
|
|
|
p = (p + 1) % len(pattern)
|
2020-11-18 13:03:01 +01:00
|
|
|
out[i] = source[mathrand.Intn(len(source))]
|
2019-08-06 13:44:08 +02:00
|
|
|
}
|
|
|
|
return string(out)
|
|
|
|
}
|
2019-08-25 09:39:31 +02:00
|
|
|
|
|
|
|
// Password creates a crypto strong password which is just about
|
|
|
|
// memorable. The password is composed of printable ASCII characters
|
|
|
|
// from the base64 alphabet.
|
|
|
|
//
|
Spelling fixes
Fix spelling of: above, already, anonymous, associated,
authentication, bandwidth, because, between, blocks, calculate,
candidates, cautious, changelog, cleaner, clipboard, command,
completely, concurrently, considered, constructs, corrupt, current,
daemon, dependencies, deprecated, directory, dispatcher, download,
eligible, ellipsis, encrypter, endpoint, entrieslist, essentially,
existing writers, existing, expires, filesystem, flushing, frequently,
hierarchy, however, implementation, implements, inaccurate,
individually, insensitive, longer, maximum, metadata, modified,
multipart, namedirfirst, nextcloud, obscured, opened, optional,
owncloud, pacific, passphrase, password, permanently, persimmon,
positive, potato, protocol, quota, receiving, recommends, referring,
requires, revisited, satisfied, satisfies, satisfy, semver,
serialized, session, storage, strategies, stringlist, successful,
supported, surprise, temporarily, temporary, transactions, unneeded,
update, uploads, wrapped
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-10-09 02:17:24 +02:00
|
|
|
// Requires password strength in bits.
|
2019-08-25 09:39:31 +02:00
|
|
|
// 64 is just about memorable
|
|
|
|
// 128 is secure
|
|
|
|
func Password(bits int) (password string, err error) {
|
|
|
|
bytes := bits / 8
|
|
|
|
if bits%8 != 0 {
|
|
|
|
bytes++
|
|
|
|
}
|
|
|
|
var pw = make([]byte, bytes)
|
2020-11-18 13:03:01 +01:00
|
|
|
n, err := cryptorand.Read(pw)
|
2019-08-25 09:39:31 +02:00
|
|
|
if err != nil {
|
|
|
|
return "", errors.Wrap(err, "password read failed")
|
|
|
|
}
|
|
|
|
if n != bytes {
|
|
|
|
return "", errors.Errorf("password short read: %d", n)
|
|
|
|
}
|
|
|
|
password = base64.RawURLEncoding.EncodeToString(pw)
|
|
|
|
return password, nil
|
|
|
|
}
|
2020-11-18 15:02:53 +01:00
|
|
|
|
|
|
|
// Seed the global math/rand with crypto strong data
|
|
|
|
//
|
|
|
|
// This doesn't make it OK to use math/rand in crypto sensitive
|
|
|
|
// environments - don't do that! However it does help to mitigate the
|
|
|
|
// problem if that happens accidentally. This would have helped with
|
|
|
|
// CVE-2020-28924 - #4783
|
|
|
|
func Seed() error {
|
|
|
|
var seed int64
|
|
|
|
err := binary.Read(cryptorand.Reader, binary.LittleEndian, &seed)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "failed to read random seed")
|
|
|
|
}
|
|
|
|
mathrand.Seed(seed)
|
|
|
|
return nil
|
|
|
|
}
|