@@ -11,13 +11,15 @@ import (
1111 "encoding/pem"
1212 "fmt"
1313 "io"
14+
15+ "github.com/maxlaverse/synocrypto/pkg/log"
1416)
1517
1618const (
1719 // maxBlockSize is the maximum size an object can have. If the limit
1820 // is cross, CloudSync complains about it and says it considers the file
19- // to be corrupted. This size seems to be 8192 but we're being conservative.
20- maxBlockSize = 4096
21+ // to be corrupted.
22+ maxBlockSize = 8192
2123)
2224
2325// EncryptOnceWithPasswordAndSalt encrypts a single blob of data with
@@ -99,21 +101,22 @@ type encrypter struct {
99101 mode cipher.BlockMode
100102 bufferedBlock []byte
101103 out io.Writer
104+ blockIndex int
102105}
103106
104- func (d * encrypter ) Write (p []byte ) (int , error ) {
105- if len (p ) == 0 {
106- return d .write (nil )
107- }
107+ func (e * encrypter ) Write (p []byte ) (int , error ) {
108+ return e .writeInChunks (p , maxBlockSize )
109+ }
108110
111+ func (e * encrypter ) writeInChunks (p []byte , size int ) (int , error ) {
109112 written := 0
110- for start := 0 ; start < len (p ); start += maxBlockSize {
111- end := start + maxBlockSize
113+ for start := 0 ; start <= len (p ); start += size {
114+ end := start + size
112115 if end > len (p ) {
113116 end = len (p )
114117 }
115118
116- n , err := d .write (p [start :end ])
119+ n , err := e .write (p [start :end ])
117120 written = written + n
118121 if err != nil {
119122 return written , err
@@ -122,66 +125,76 @@ func (d *encrypter) Write(p []byte) (int, error) {
122125 return written , nil
123126}
124127
125- func (d * encrypter ) write (p []byte ) (int , error ) {
126- if d .hasBufferedBlock {
127- lastBlockEncrypted := make ([]byte , len (d .bufferedBlock ))
128-
129- err := func () (err error ) {
130- defer func () {
131- if r := recover (); r != nil {
132- err = fmt .Errorf ("CryptBlocks paniced: %v" , r )
133- }
134- }()
135-
136- d .mode .CryptBlocks (lastBlockEncrypted , d .bufferedBlock )
137- return
138- }()
128+ func (e * encrypter ) write (p []byte ) (int , error ) {
129+ if e .hasBufferedBlock {
130+ err := e .encryptAndFlushBuffer ()
139131 if err != nil {
140- return - 1 , fmt . Errorf ( "error crypting block: %w" , err )
132+ return - 1 , err
141133 }
134+ }
142135
143- n , err := d .out .Write (lastBlockEncrypted )
144- if err != nil {
145- return n , fmt .Errorf ("error flushing block: %w" , err )
146- }
147- d .hasBufferedBlock = false
136+ if len (p ) != 0 {
137+ e .bufferData (p )
148138 }
139+ return len (p ), nil
140+ }
149141
150- // We have to return len(p) instead of what was really written
151- // to the output, or io.Copy() returns 'short write' error.
152- if len (p ) == 0 {
153- return len (p ), nil
142+ func (e * encrypter ) bufferData (p []byte ) {
143+ log .Debugf ("Buffering %d bytes of plain data" , len (p ))
144+ e .bufferedBlock = make ([]byte , len (p ))
145+ copy (e .bufferedBlock , p )
146+
147+ e .hasBufferedBlock = true
148+ }
149+
150+ func (e * encrypter ) encryptAndFlushBuffer () error {
151+ encryptedBlock := make ([]byte , len (e .bufferedBlock ))
152+
153+ err := func () (err error ) {
154+ defer func () {
155+ if r := recover (); r != nil {
156+ err = fmt .Errorf ("CryptBlocks paniced: %v" , r )
157+ }
158+ }()
159+
160+ e .mode .CryptBlocks (encryptedBlock , e .bufferedBlock )
161+ return
162+ }()
163+ if err != nil {
164+ return fmt .Errorf ("error crypting block: %w" , err )
154165 }
155166
156- if len (d .bufferedBlock ) < len (p ) {
157- d .bufferedBlock = make ([]byte , len (p ))
158- } else if len (d .bufferedBlock ) > len (p ) {
159- d .bufferedBlock = d .bufferedBlock [:len (p )]
167+ e .blockIndex += 1
168+ log .Debugf ("Block #%d - Writting out %d encrypted bytes " , e .blockIndex , len (encryptedBlock ))
169+ _ , err = e .out .Write (encryptedBlock )
170+ if err != nil {
171+ return fmt .Errorf ("error flushing block: %w" , err )
160172 }
161- copy (d .bufferedBlock , p )
162173
163- d .hasBufferedBlock = true
164- return len ( p ), nil
174+ e .hasBufferedBlock = false
175+ return nil
165176}
166177
167- func (d * encrypter ) flushBufferWithPadding () ( int , error ) {
168- if ! d .hasBufferedBlock {
169- return - 1 , nil
178+ func (e * encrypter ) encryptAndFlushBufferWithPadding () error {
179+ if ! e .hasBufferedBlock {
180+ return nil
170181 }
171182
172183 var err error
173- d .bufferedBlock , err = pkcs7Pad (d .bufferedBlock , d .mode .BlockSize ())
184+ sizeBeforePadding := len (e .bufferedBlock )
185+ e .bufferedBlock , err = pkcs7Pad (e .bufferedBlock , e .mode .BlockSize ())
186+ log .Debugf ("Adding %d bytes of padding to the plain data" , len (e .bufferedBlock )- sizeBeforePadding )
187+
174188 if err != nil {
175- return - 1 , fmt .Errorf ("unable to pad data: %w" , err )
189+ return fmt .Errorf ("unable to pad data: %w" , err )
176190 }
177-
178- return d .Write (nil )
191+ return e .encryptAndFlushBuffer ()
179192}
180193
181- func (d * encrypter ) Close () error {
182- _ , err := d . flushBufferWithPadding ()
194+ func (e * encrypter ) Close () error {
195+ err := e . encryptAndFlushBufferWithPadding ()
183196
184- if v , ok := d .out .(io.WriteCloser ); ok {
197+ if v , ok := e .out .(io.WriteCloser ); ok {
185198 if err := v .Close (); err != nil {
186199 return err
187200 }
0 commit comments