diff options
Diffstat (limited to 'crypto/rand.go')
| -rw-r--r-- | crypto/rand.go | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/crypto/rand.go b/crypto/rand.go index 0778ebd..527f841 100644 --- a/crypto/rand.go +++ b/crypto/rand.go @@ -30,7 +30,8 @@ import ( // the operating system has insufficient randomness, the buffer creation will // fail. This is an improvement over Go's built-in crypto/rand which will still // return bytes if the system has insufficiency entropy. -// See: https://github.com/golang/go/issues/19274 +// +// See: https://github.com/golang/go/issues/19274 // // While this syscall was only introduced in Kernel v3.17, it predates the // introduction of filesystem encryption, so it introduces no additional @@ -44,11 +45,43 @@ func NewRandomBuffer(length int) ([]byte, error) { } // NewRandomKey creates a random key of the specified length. This function uses -// the same random number generation process a NewRandomBuffer. +// the same random number generation process as NewRandomBuffer. func NewRandomKey(length int) (*Key, error) { return NewFixedLengthKeyFromReader(randReader{}, length) } +// NewRandomPassphrase creates a random passphrase of the specified length +// containing random alphabetic characters. +func NewRandomPassphrase(length int) (*Key, error) { + chars := []byte("abcdefghijklmnopqrstuvwxyz") + passphrase, err := NewBlankKey(length) + if err != nil { + return nil, err + } + for i := 0; i < length; { + // Get some random bytes. + raw, err := NewRandomKey((length - i) * 2) + if err != nil { + return nil, err + } + // Translate the random bytes into random characters. + for _, b := range raw.data { + if int(b) >= 256-(256%len(chars)) { + // Avoid bias towards the first characters in the list. + continue + } + c := chars[int(b)%len(chars)] + passphrase.data[i] = c + i++ + if i == length { + break + } + } + raw.Wipe() + } + return passphrase, nil +} + // randReader just calls into Getrandom, so no internal data is needed. type randReader struct{} @@ -58,10 +91,9 @@ func (r randReader) Read(buffer []byte) (int, error) { case nil: return n, nil case unix.EAGAIN: - return 0, errors.Wrap(ErrGetrandomFail, "insufficient entropy in pool") + err = errors.New("insufficient entropy in pool") case unix.ENOSYS: - return 0, errors.Wrap(ErrGetrandomFail, "kernel must be v3.17 or later") - default: - return 0, errors.Wrap(ErrGetrandomFail, err.Error()) + err = errors.New("kernel must be v3.17 or later") } + return 0, errors.Wrap(err, "getrandom() failed") } |