MCPcopy
hub / github.com/syncthing/syncthing / decryptFile

Method decryptFile

cmd/syncthing/decrypt/decrypt.go:211–262  ·  view source on GitHub ↗

decryptFile reads, decrypts and verifies all the blocks in src, writing it to dst if dst is non-nil. (If dst is nil it just becomes a read-and-verify operation.)

(encFi *protocol.FileInfo, plainFi *protocol.FileInfo, src io.ReaderAt, dst io.WriterAt)

Source from the content-addressed store, hash-verified

209// it to dst if dst is non-nil. (If dst is nil it just becomes a
210// read-and-verify operation.)
211func (c *CLI) decryptFile(encFi *protocol.FileInfo, plainFi *protocol.FileInfo, src io.ReaderAt, dst io.WriterAt) error {
212 // The encrypted and plaintext files must consist of an equal number of blocks
213 if len(encFi.Blocks) != len(plainFi.Blocks) {
214 return fmt.Errorf("block count mismatch: encrypted %d != plaintext %d", len(encFi.Blocks), len(plainFi.Blocks))
215 }
216
217 fileKey := c.keyGen.FileKey(plainFi.Name, c.folderKey)
218 for i, encBlock := range encFi.Blocks {
219 // Read the encrypted block
220 buf := make([]byte, encBlock.Size)
221 if _, err := src.ReadAt(buf, encBlock.Offset); err != nil {
222 return fmt.Errorf("encrypted block %d (%d bytes): %w", i, encBlock.Size, err)
223 }
224
225 // Decrypt it
226 dec, err := protocol.DecryptBytes(buf, fileKey)
227 if err != nil {
228 return fmt.Errorf("encrypted block %d (%d bytes): %w", i, encBlock.Size, err)
229 }
230
231 // Verify the block size against the expected plaintext
232 plainBlock := plainFi.Blocks[i]
233 if i == len(plainFi.Blocks)-1 && len(dec) > plainBlock.Size {
234 // The last block might be padded, which is fine (we skip the padding)
235 dec = dec[:plainBlock.Size]
236 } else if len(dec) != plainBlock.Size {
237 return fmt.Errorf("plaintext block %d size mismatch, actual %d != expected %d", i, len(dec), plainBlock.Size)
238 }
239
240 // Verify the hash against the plaintext block info
241 if !scanner.Validate(dec, plainBlock.Hash) {
242 // The block decrypted correctly but fails the hash check. This
243 // is odd and unexpected, but it it's still a valid block from
244 // the source. The file might have changed while we pulled it?
245 err := fmt.Errorf("plaintext block %d (%d bytes) failed validation after decryption", i, plainBlock.Size)
246 if c.Continue {
247 log.Printf("Warning: %s: %s: %v", encFi.Name, plainFi.Name, err)
248 } else {
249 return err
250 }
251 }
252
253 // Write it to the destination, unless we're just verifying.
254 if dst != nil {
255 if _, err := dst.WriteAt(dec, plainBlock.Offset); err != nil {
256 return err
257 }
258 }
259 }
260
261 return nil
262}
263
264// loadEncryptedFileInfo loads the encrypted FileInfo trailer from a file on
265// disk.

Callers 1

processMethod · 0.95

Calls 5

DecryptBytesFunction · 0.92
ValidateFunction · 0.92
FileKeyMethod · 0.80
ReadAtMethod · 0.45
WriteAtMethod · 0.45

Tested by

no test coverage detected