aboutsummaryrefslogtreecommitdiff
path: root/crypto/rand.go
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/rand.go')
-rw-r--r--crypto/rand.go44
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")
}