/
entropy.go
68 lines (60 loc) 路 1.56 KB
/
entropy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package entropy
import (
"bufio"
"bytes"
"crypto/rand"
"errors"
"fmt"
"io"
"os"
"os/exec"
)
// GetRandom reads n bytes of randomness from whatever Reader is passed in, and returns
// those bytes as the requested randomness.
func GetRandom(source io.Reader, n uint32) ([]byte, error) {
if source == nil {
source = rand.Reader
}
randomBytes := make([]byte, n)
bytesRead, err := source.Read(randomBytes)
if err != nil || uint32(bytesRead) != n {
// If customEntropy provides an error,
// fallback to Golang crypto/rand generator.
_, err := rand.Read(randomBytes)
return randomBytes, err
}
return randomBytes, nil
}
// ScriptReader hold info for user entropy to be given to the dkg
type ScriptReader struct {
Path string
}
var _ io.Reader = &ScriptReader{}
// Read calls the executable as many times needed to fill the array p
// n == len(p) if and only if err == nil
func (r *ScriptReader) Read(p []byte) (n int, err error) {
if r.Path == "" {
return 0, errors.New("no reader was provided")
}
var b bytes.Buffer
read := 0
for read < len(p) {
cmd := exec.Command(r.Path) // #nosec
cmd.Stdout = bufio.NewWriter(&b)
err = cmd.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "entropy: cannot read from the file: %s\v", err.Error())
return read, err
}
read += copy(p[read:], b.Bytes())
}
return len(p), nil
}
// GetPath returns the path of the script
func (r *ScriptReader) GetPath() string {
return r.Path
}
// NewScriptReader creates a new ScriptReader struct
func NewScriptReader(path string) *ScriptReader {
return &ScriptReader{path}
}