-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreader.go
42 lines (37 loc) · 1.05 KB
/
reader.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
package gopherng
import (
"crypto/cipher"
"fmt"
"golang.org/x/crypto/chacha20"
"golang.org/x/crypto/sha3"
)
// PseudorandomReader is a Reader providing seeded pseudorandom output from the
// keystream of an internal stream cipher.
//
// It is not safe for concurrent use.
type PseudorandomReader struct {
// cipher is the stream cipher used to generate output.
cipher cipher.Stream
}
// NewReader initializes a PseudorandomReader by initializing its internal
// stream cipher.
func NewReader(seed []byte) *PseudorandomReader {
var p PseudorandomReader
keyNonce := sha3.Sum512(seed)
var err error
p.cipher, err = chacha20.NewUnauthenticatedCipher(keyNonce[0:32],
keyNonce[32:56])
if err != nil {
panic(fmt.Errorf(
"failed to construct XChaCha20 unauthenticated cipher: %w", err))
}
return &p
}
// Read reads pseudorandom bytes by calling XORKeyStream with 0s in order to
// produce the keystream output.
func (p *PseudorandomReader) Read(b []byte) (int, error) {
l := len(b)
srcZero := make([]byte, l)
p.cipher.XORKeyStream(b, srcZero)
return l, nil
}