@@ -10,6 +10,7 @@ import (
1010 "crypto/cipher"
1111 "encoding/binary"
1212 "io"
13+ "math"
1314 "sync"
1415)
1516
@@ -23,28 +24,29 @@ const (
2324
2425const (
2526 // NotAuthentic is returned when the decryption of a data stream fails.
26- // It indicates that the data is not authentic - e.g. malisously modified.
27- NotAuthentic errorType = "data is not authentic"
27+ // It indicates that the encrypted data is invalid - i.e. it has been
28+ // (maliciously) modified.
29+ NotAuthentic errorType = "sio: data is not authentic"
2830
2931 // ErrExceeded is returned when no more data can be encrypted /
3032 // decrypted securely. It indicates that the data stream is too
3133 // large to be encrypted / decrypted with a single key-nonce
3234 // combination.
3335 //
34- // For BufSize this will happen after processing ~64 TiB.
35- ErrExceeded errorType = "data limit exceeded"
36+ // It depends on the buffer size how many bytes can be
37+ // encrypted / decrypted securely using the same key-nonce
38+ // combination. For BufSize the limit is ~64 TiB.
39+ ErrExceeded errorType = "sio: data limit exceeded"
3640)
3741
3842type errorType string
3943
4044func (e errorType ) Error () string { return string (e ) }
4145
4246// NewStream creates a new Stream that encrypts or decrypts data
43- // streams with the cipher. If you don't have special requirements
44- // just use the default BufSize.
45- //
46- // The returned Stream will allocate a new bufSize large buffer
47- // when en/decrypting a data stream.
47+ // streams with the cipher using bufSize large chunks. Therefore,
48+ // the bufSize must be the same for encryption and decryption. If
49+ // you don't have special requirements just use the default BufSize.
4850//
4951// The cipher must support a NonceSize() >= 4 and the
5052// bufSize must be between 1 (inclusive) and MaxBufSize (inclusive).
@@ -75,35 +77,53 @@ type Stream struct {
7577func (s * Stream ) NonceSize () int { return s .cipher .NonceSize () - 4 }
7678
7779// Overhead returns the overhead added when encrypting a
78- // data stream. It panic's if the length is either negative
79- // or exceeds the data limit of (2³² - 1) * bufSize bytes.
80- func (s * Stream ) Overhead (length int64 ) int64 {
81- if length < 0 {
82- panic ("sio: length is negative" )
80+ // data stream. For a plaintext stream of a non-negative
81+ // size, the size of an encrypted data stream will be:
82+ //
83+ // encSize = size + stream.Overhead(size) // 0 <= size <= (2³² - 1) * bufSize
84+ // 0 = stream.Overhead(size) // size > (2³² - 1) * bufSize
85+ // -1 = stream.Overhead(size) // size < 0
86+ //
87+ // In general, the size of an encrypted data stream is
88+ // always greater than the size of the corresponding
89+ // plaintext stream. If size is too large (i.e.
90+ // greater than (2³² - 1) * bufSize) then Overhead
91+ // returns 0. If size is negative Overhead returns -1.
92+ func (s * Stream ) Overhead (size int64 ) int64 {
93+ if size < 0 {
94+ return - 1
8395 }
84- if length > int64 (s .bufSize )* ((1 << 32 )- 1 ) {
85- panic ("sio: length exceeds data limit" )
96+
97+ bufSize := int64 (s .bufSize )
98+ if size > (bufSize * math .MaxUint32 ) {
99+ return 0
86100 }
87101
88102 overhead := int64 (s .cipher .Overhead ())
89- if length == 0 {
103+ if size == 0 {
90104 return overhead
91105 }
92106
93- t := length / int64 ( s . bufSize )
94- if r := length % int64 ( s . bufSize ) ; r > 0 {
107+ t := size / bufSize
108+ if r := size % bufSize ; r > 0 {
95109 return (t * overhead ) + overhead
96110 }
97111 return t * overhead
98112}
99113
100114// EncryptWriter returns a new EncWriter that wraps w and
101- // encrypts and authenticates everything written to it.
102- // The nonce must be NonceSize() bytes long and unique for
103- // the same key (used to create cipher.AEAD). The
104- // associatedData is authenticated but neither encrypted nor
105- // written to w and must be provided whenever decrypting the
106- // data again.
115+ // encrypts and authenticates everything before writing
116+ // it to w.
117+ //
118+ // The nonce must be Stream.NonceSize() bytes long and unique
119+ // for the same key. The same nonce must be provided when
120+ // decrypting the data stream.
121+ //
122+ // The associatedData is only authenticated but not encrypted
123+ // and not written to w. Instead, the same associatedData must
124+ // be provided when decrypting the data stream again. It is
125+ // safe to set:
126+ // associatedData = nil
107127func (s * Stream ) EncryptWriter (w io.Writer , nonce , associatedData []byte ) * EncWriter {
108128 if len (nonce ) != s .NonceSize () {
109129 panic ("sio: nonce has invalid length" )
@@ -124,10 +144,14 @@ func (s *Stream) EncryptWriter(w io.Writer, nonce, associatedData []byte) *EncWr
124144}
125145
126146// DecryptWriter returns a new DecWriter that wraps w and
127- // decrypts and verifies everything written to it. The
128- // nonce and associatedData must match the values used
129- // when encrypting the data. The associatedData is not
130- // written to w.
147+ // decrypts and verifies everything before writing
148+ // it to w.
149+ //
150+ // The nonce must be Stream.NonceSize() bytes long and
151+ // must match the value used when encrypting the data stream.
152+ //
153+ // The associatedData must match the value used when encrypting
154+ // the data stream.
131155func (s * Stream ) DecryptWriter (w io.Writer , nonce , associatedData []byte ) * DecWriter {
132156 if len (nonce ) != s .NonceSize () {
133157 panic ("sio: nonce has invalid length" )
@@ -148,10 +172,17 @@ func (s *Stream) DecryptWriter(w io.Writer, nonce, associatedData []byte) *DecWr
148172}
149173
150174// EncryptReader returns a new EncReader that wraps r and
151- // encrypts and authenticates everything it reads. The
152- // nonce must be NonceSize() bytes long and unique for
153- // the same key (used to create cipher.AEAD). The
154- // associatedData is authenticated but not encrypted.
175+ // encrypts and authenticates it reads from r.
176+ //
177+ // The nonce must be Stream.NonceSize() bytes long and unique
178+ // for the same key. The same nonce must be provided when
179+ // decrypting the data stream.
180+ //
181+ // The associatedData is only authenticated but not encrypted
182+ // and not written to w. Instead, the same associatedData must
183+ // be provided when decrypting the data stream again. It is
184+ // safe to set:
185+ // associatedData = nil
155186func (s * Stream ) EncryptReader (r io.Reader , nonce , associatedData []byte ) * EncReader {
156187 if len (nonce ) != s .NonceSize () {
157188 panic ("sio: nonce has invalid length" )
@@ -174,9 +205,13 @@ func (s *Stream) EncryptReader(r io.Reader, nonce, associatedData []byte) *EncRe
174205}
175206
176207// DecryptReader returns a new DecReader that wraps r and
177- // decrypts and verifies everything it reads. The nonce
178- // and associatedData must match the values used to
179- // encrypt the data.
208+ // decrypts and verifies everything it reads from r.
209+ //
210+ // The nonce must be Stream.NonceSize() bytes long and
211+ // must match the value used when encrypting the data stream.
212+ //
213+ // The associatedData must match the value used when encrypting
214+ // the data stream.
180215func (s * Stream ) DecryptReader (r io.Reader , nonce , associatedData []byte ) * DecReader {
181216 if len (nonce ) != s .NonceSize () {
182217 panic ("sio: nonce has invalid length" )
@@ -198,10 +233,14 @@ func (s *Stream) DecryptReader(r io.Reader, nonce, associatedData []byte) *DecRe
198233 return dr
199234}
200235
201- // DecryptReaderAt returns a new DecReaderAt that wraps r and
202- // decrypts and verifies everything it reads. The nonce
203- // and associatedData must match the values used to
204- // encrypt the data.
236+ // DecryptReader returns a new DecReaderAt that wraps r and
237+ // decrypts and verifies everything it reads from r.
238+ //
239+ // The nonce must be Stream.NonceSize() bytes long and
240+ // must match the value used when encrypting the data stream.
241+ //
242+ // The associatedData must match the value used when encrypting
243+ // the data stream.
205244func (s * Stream ) DecryptReaderAt (r io.ReaderAt , nonce , associatedData []byte ) * DecReaderAt {
206245 if len (nonce ) != s .NonceSize () {
207246 panic ("sio: nonce has invalid length" )
0 commit comments