1
2
3
4
5 package sha3
6
7 import (
8 "bytes"
9 "crypto/internal/fips"
10 "errors"
11 "internal/byteorder"
12 "math/bits"
13 )
14
15 type SHAKE struct {
16 d Digest
17
18
19
20
21
22
23 initBlock []byte
24 }
25
26 func bytepad(data []byte, rate int) []byte {
27 out := make([]byte, 0, 9+len(data)+rate-1)
28 out = append(out, leftEncode(uint64(rate))...)
29 out = append(out, data...)
30 if padlen := rate - len(out)%rate; padlen < rate {
31 out = append(out, make([]byte, padlen)...)
32 }
33 return out
34 }
35
36 func leftEncode(x uint64) []byte {
37
38 n := (bits.Len64(x) + 7) / 8
39 if n == 0 {
40 n = 1
41 }
42
43 b := make([]byte, 9)
44 byteorder.BePutUint64(b[1:], x)
45 b = b[9-n-1:]
46 b[0] = byte(n)
47 return b
48 }
49
50 func newCShake(N, S []byte, rate, outputLen int, dsbyte byte) *SHAKE {
51 c := &SHAKE{d: Digest{rate: rate, outputLen: outputLen, dsbyte: dsbyte}}
52 c.initBlock = make([]byte, 0, 9+len(N)+9+len(S))
53 c.initBlock = append(c.initBlock, leftEncode(uint64(len(N))*8)...)
54 c.initBlock = append(c.initBlock, N...)
55 c.initBlock = append(c.initBlock, leftEncode(uint64(len(S))*8)...)
56 c.initBlock = append(c.initBlock, S...)
57 c.Write(bytepad(c.initBlock, c.d.rate))
58 return c
59 }
60
61 func (s *SHAKE) BlockSize() int { return s.d.BlockSize() }
62 func (s *SHAKE) Size() int { return s.d.Size() }
63
64
65
66
67
68 func (s *SHAKE) Sum(in []byte) []byte { return s.d.Sum(in) }
69
70
71
72 func (s *SHAKE) Write(p []byte) (n int, err error) { return s.d.Write(p) }
73
74 func (s *SHAKE) Read(out []byte) (n int, err error) {
75 fips.RecordApproved()
76
77
78 return s.d.read(out)
79 }
80
81
82 func (s *SHAKE) Reset() {
83 s.d.Reset()
84 if len(s.initBlock) != 0 {
85 s.Write(bytepad(s.initBlock, s.d.rate))
86 }
87 }
88
89
90 func (s *SHAKE) Clone() *SHAKE {
91 ret := *s
92 return &ret
93 }
94
95 func (s *SHAKE) MarshalBinary() ([]byte, error) {
96 return s.AppendBinary(make([]byte, 0, marshaledSize+len(s.initBlock)))
97 }
98
99 func (s *SHAKE) AppendBinary(b []byte) ([]byte, error) {
100 b, err := s.d.AppendBinary(b)
101 if err != nil {
102 return nil, err
103 }
104 b = append(b, s.initBlock...)
105 return b, nil
106 }
107
108 func (s *SHAKE) UnmarshalBinary(b []byte) error {
109 if len(b) < marshaledSize {
110 return errors.New("sha3: invalid hash state")
111 }
112 if err := s.d.UnmarshalBinary(b[:marshaledSize]); err != nil {
113 return err
114 }
115 s.initBlock = bytes.Clone(b[marshaledSize:])
116 return nil
117 }
118
119
120 func NewShake128() *SHAKE {
121 return &SHAKE{d: Digest{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}}
122 }
123
124
125 func NewShake256() *SHAKE {
126 return &SHAKE{d: Digest{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}}
127 }
128
129
130
131
132
133
134 func NewCShake128(N, S []byte) *SHAKE {
135 if len(N) == 0 && len(S) == 0 {
136 return NewShake128()
137 }
138 return newCShake(N, S, rateK256, 32, dsbyteCShake)
139 }
140
141
142
143
144
145
146 func NewCShake256(N, S []byte) *SHAKE {
147 if len(N) == 0 && len(S) == 0 {
148 return NewShake256()
149 }
150 return newCShake(N, S, rateK512, 64, dsbyteCShake)
151 }
152
View as plain text