github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/backend/crypt/cipher.go (about) 1 package crypt 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/aes" 7 gocipher "crypto/cipher" 8 "crypto/rand" 9 "encoding/base32" 10 "fmt" 11 "io" 12 "strconv" 13 "strings" 14 "sync" 15 "unicode/utf8" 16 17 "github.com/ncw/rclone/backend/crypt/pkcs7" 18 "github.com/ncw/rclone/fs" 19 "github.com/ncw/rclone/fs/accounting" 20 "github.com/pkg/errors" 21 "github.com/rfjakob/eme" 22 "golang.org/x/crypto/nacl/secretbox" 23 "golang.org/x/crypto/scrypt" 24 ) 25 26 // Constants 27 const ( 28 nameCipherBlockSize = aes.BlockSize 29 fileMagic = "RCLONE\x00\x00" 30 fileMagicSize = len(fileMagic) 31 fileNonceSize = 24 32 fileHeaderSize = fileMagicSize + fileNonceSize 33 blockHeaderSize = secretbox.Overhead 34 blockDataSize = 64 * 1024 35 blockSize = blockHeaderSize + blockDataSize 36 encryptedSuffix = ".bin" // when file name encryption is off we add this suffix to make sure the cloud provider doesn't process the file 37 ) 38 39 // Errors returned by cipher 40 var ( 41 ErrorBadDecryptUTF8 = errors.New("bad decryption - utf-8 invalid") 42 ErrorBadDecryptControlChar = errors.New("bad decryption - contains control chars") 43 ErrorNotAMultipleOfBlocksize = errors.New("not a multiple of blocksize") 44 ErrorTooShortAfterDecode = errors.New("too short after base32 decode") 45 ErrorTooLongAfterDecode = errors.New("too long after base32 decode") 46 ErrorEncryptedFileTooShort = errors.New("file is too short to be encrypted") 47 ErrorEncryptedFileBadHeader = errors.New("file has truncated block header") 48 ErrorEncryptedBadMagic = errors.New("not an encrypted file - bad magic string") 49 ErrorEncryptedBadBlock = errors.New("failed to authenticate decrypted block - bad password?") 50 ErrorBadBase32Encoding = errors.New("bad base32 filename encoding") 51 ErrorFileClosed = errors.New("file already closed") 52 ErrorNotAnEncryptedFile = errors.New("not an encrypted file - no \"" + encryptedSuffix + "\" suffix") 53 ErrorBadSeek = errors.New("Seek beyond end of file") 54 defaultSalt = []byte{0xA8, 0x0D, 0xF4, 0x3A, 0x8F, 0xBD, 0x03, 0x08, 0xA7, 0xCA, 0xB8, 0x3E, 0x58, 0x1F, 0x86, 0xB1} 55 obfuscQuoteRune = '!' 56 ) 57 58 // Global variables 59 var ( 60 fileMagicBytes = []byte(fileMagic) 61 ) 62 63 // ReadSeekCloser is the interface of the read handles 64 type ReadSeekCloser interface { 65 io.Reader 66 io.Seeker 67 io.Closer 68 fs.RangeSeeker 69 } 70 71 // OpenRangeSeek opens the file handle at the offset with the limit given 72 type OpenRangeSeek func(ctx context.Context, offset, limit int64) (io.ReadCloser, error) 73 74 // Cipher is used to swap out the encryption implementations 75 type Cipher interface { 76 // EncryptFileName encrypts a file path 77 EncryptFileName(string) string 78 // DecryptFileName decrypts a file path, returns error if decrypt was invalid 79 DecryptFileName(string) (string, error) 80 // EncryptDirName encrypts a directory path 81 EncryptDirName(string) string 82 // DecryptDirName decrypts a directory path, returns error if decrypt was invalid 83 DecryptDirName(string) (string, error) 84 // EncryptData 85 EncryptData(io.Reader) (io.Reader, error) 86 // DecryptData 87 DecryptData(io.ReadCloser) (io.ReadCloser, error) 88 // DecryptDataSeek decrypt at a given position 89 DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (ReadSeekCloser, error) 90 // EncryptedSize calculates the size of the data when encrypted 91 EncryptedSize(int64) int64 92 // DecryptedSize calculates the size of the data when decrypted 93 DecryptedSize(int64) (int64, error) 94 // NameEncryptionMode returns the used mode for name handling 95 NameEncryptionMode() NameEncryptionMode 96 } 97 98 // NameEncryptionMode is the type of file name encryption in use 99 type NameEncryptionMode int 100 101 // NameEncryptionMode levels 102 const ( 103 NameEncryptionOff NameEncryptionMode = iota 104 NameEncryptionStandard 105 NameEncryptionObfuscated 106 ) 107 108 // NewNameEncryptionMode turns a string into a NameEncryptionMode 109 func NewNameEncryptionMode(s string) (mode NameEncryptionMode, err error) { 110 s = strings.ToLower(s) 111 switch s { 112 case "off": 113 mode = NameEncryptionOff 114 case "standard": 115 mode = NameEncryptionStandard 116 case "obfuscate": 117 mode = NameEncryptionObfuscated 118 default: 119 err = errors.Errorf("Unknown file name encryption mode %q", s) 120 } 121 return mode, err 122 } 123 124 // String turns mode into a human readable string 125 func (mode NameEncryptionMode) String() (out string) { 126 switch mode { 127 case NameEncryptionOff: 128 out = "off" 129 case NameEncryptionStandard: 130 out = "standard" 131 case NameEncryptionObfuscated: 132 out = "obfuscate" 133 default: 134 out = fmt.Sprintf("Unknown mode #%d", mode) 135 } 136 return out 137 } 138 139 type cipher struct { 140 dataKey [32]byte // Key for secretbox 141 nameKey [32]byte // 16,24 or 32 bytes 142 nameTweak [nameCipherBlockSize]byte // used to tweak the name crypto 143 block gocipher.Block 144 mode NameEncryptionMode 145 buffers sync.Pool // encrypt/decrypt buffers 146 cryptoRand io.Reader // read crypto random numbers from here 147 dirNameEncrypt bool 148 } 149 150 // newCipher initialises the cipher. If salt is "" then it uses a built in salt val 151 func newCipher(mode NameEncryptionMode, password, salt string, dirNameEncrypt bool) (*cipher, error) { 152 c := &cipher{ 153 mode: mode, 154 cryptoRand: rand.Reader, 155 dirNameEncrypt: dirNameEncrypt, 156 } 157 c.buffers.New = func() interface{} { 158 return make([]byte, blockSize) 159 } 160 err := c.Key(password, salt) 161 if err != nil { 162 return nil, err 163 } 164 return c, nil 165 } 166 167 // Key creates all the internal keys from the password passed in using 168 // scrypt. 169 // 170 // If salt is "" we use a fixed salt just to make attackers lives 171 // slighty harder than using no salt. 172 // 173 // Note that empty passsword makes all 0x00 keys which is used in the 174 // tests. 175 func (c *cipher) Key(password, salt string) (err error) { 176 const keySize = len(c.dataKey) + len(c.nameKey) + len(c.nameTweak) 177 var saltBytes = defaultSalt 178 if salt != "" { 179 saltBytes = []byte(salt) 180 } 181 var key []byte 182 if password == "" { 183 key = make([]byte, keySize) 184 } else { 185 key, err = scrypt.Key([]byte(password), saltBytes, 16384, 8, 1, keySize) 186 if err != nil { 187 return err 188 } 189 } 190 copy(c.dataKey[:], key) 191 copy(c.nameKey[:], key[len(c.dataKey):]) 192 copy(c.nameTweak[:], key[len(c.dataKey)+len(c.nameKey):]) 193 // Key the name cipher 194 c.block, err = aes.NewCipher(c.nameKey[:]) 195 return err 196 } 197 198 // getBlock gets a block from the pool of size blockSize 199 func (c *cipher) getBlock() []byte { 200 return c.buffers.Get().([]byte) 201 } 202 203 // putBlock returns a block to the pool of size blockSize 204 func (c *cipher) putBlock(buf []byte) { 205 if len(buf) != blockSize { 206 panic("bad blocksize returned to pool") 207 } 208 c.buffers.Put(buf) 209 } 210 211 // check to see if the byte string is valid with no control characters 212 // from 0x00 to 0x1F and is a valid UTF-8 string 213 func checkValidString(buf []byte) error { 214 for i := range buf { 215 c := buf[i] 216 if c >= 0x00 && c < 0x20 || c == 0x7F { 217 return ErrorBadDecryptControlChar 218 } 219 } 220 if !utf8.Valid(buf) { 221 return ErrorBadDecryptUTF8 222 } 223 return nil 224 } 225 226 // encodeFileName encodes a filename using a modified version of 227 // standard base32 as described in RFC4648 228 // 229 // The standard encoding is modified in two ways 230 // * it becomes lower case (no-one likes upper case filenames!) 231 // * we strip the padding character `=` 232 func encodeFileName(in []byte) string { 233 encoded := base32.HexEncoding.EncodeToString(in) 234 encoded = strings.TrimRight(encoded, "=") 235 return strings.ToLower(encoded) 236 } 237 238 // decodeFileName decodes a filename as encoded by encodeFileName 239 func decodeFileName(in string) ([]byte, error) { 240 if strings.HasSuffix(in, "=") { 241 return nil, ErrorBadBase32Encoding 242 } 243 // First figure out how many padding characters to add 244 roundUpToMultipleOf8 := (len(in) + 7) &^ 7 245 equals := roundUpToMultipleOf8 - len(in) 246 in = strings.ToUpper(in) + "========"[:equals] 247 return base32.HexEncoding.DecodeString(in) 248 } 249 250 // encryptSegment encrypts a path segment 251 // 252 // This uses EME with AES 253 // 254 // EME (ECB-Mix-ECB) is a wide-block encryption mode presented in the 255 // 2003 paper "A Parallelizable Enciphering Mode" by Halevi and 256 // Rogaway. 257 // 258 // This makes for determinstic encryption which is what we want - the 259 // same filename must encrypt to the same thing. 260 // 261 // This means that 262 // * filenames with the same name will encrypt the same 263 // * filenames which start the same won't have a common prefix 264 func (c *cipher) encryptSegment(plaintext string) string { 265 if plaintext == "" { 266 return "" 267 } 268 paddedPlaintext := pkcs7.Pad(nameCipherBlockSize, []byte(plaintext)) 269 ciphertext := eme.Transform(c.block, c.nameTweak[:], paddedPlaintext, eme.DirectionEncrypt) 270 return encodeFileName(ciphertext) 271 } 272 273 // decryptSegment decrypts a path segment 274 func (c *cipher) decryptSegment(ciphertext string) (string, error) { 275 if ciphertext == "" { 276 return "", nil 277 } 278 rawCiphertext, err := decodeFileName(ciphertext) 279 if err != nil { 280 return "", err 281 } 282 if len(rawCiphertext)%nameCipherBlockSize != 0 { 283 return "", ErrorNotAMultipleOfBlocksize 284 } 285 if len(rawCiphertext) == 0 { 286 // not possible if decodeFilename() working correctly 287 return "", ErrorTooShortAfterDecode 288 } 289 if len(rawCiphertext) > 2048 { 290 return "", ErrorTooLongAfterDecode 291 } 292 paddedPlaintext := eme.Transform(c.block, c.nameTweak[:], rawCiphertext, eme.DirectionDecrypt) 293 plaintext, err := pkcs7.Unpad(nameCipherBlockSize, paddedPlaintext) 294 if err != nil { 295 return "", err 296 } 297 err = checkValidString(plaintext) 298 if err != nil { 299 return "", err 300 } 301 return string(plaintext), err 302 } 303 304 // Simple obfuscation routines 305 func (c *cipher) obfuscateSegment(plaintext string) string { 306 if plaintext == "" { 307 return "" 308 } 309 310 // If the string isn't valid UTF8 then don't rotate; just 311 // prepend a !. 312 if !utf8.ValidString(plaintext) { 313 return "!." + plaintext 314 } 315 316 // Calculate a simple rotation based on the filename and 317 // the nameKey 318 var dir int 319 for _, runeValue := range plaintext { 320 dir += int(runeValue) 321 } 322 dir = dir % 256 323 324 // We'll use this number to store in the result filename... 325 var result bytes.Buffer 326 _, _ = result.WriteString(strconv.Itoa(dir) + ".") 327 328 // but we'll augment it with the nameKey for real calculation 329 for i := 0; i < len(c.nameKey); i++ { 330 dir += int(c.nameKey[i]) 331 } 332 333 // Now for each character, depending on the range it is in 334 // we will actually rotate a different amount 335 for _, runeValue := range plaintext { 336 switch { 337 case runeValue == obfuscQuoteRune: 338 // Quote the Quote character 339 _, _ = result.WriteRune(obfuscQuoteRune) 340 _, _ = result.WriteRune(obfuscQuoteRune) 341 342 case runeValue >= '0' && runeValue <= '9': 343 // Number 344 thisdir := (dir % 9) + 1 345 newRune := '0' + (int(runeValue)-'0'+thisdir)%10 346 _, _ = result.WriteRune(rune(newRune)) 347 348 case (runeValue >= 'A' && runeValue <= 'Z') || 349 (runeValue >= 'a' && runeValue <= 'z'): 350 // ASCII letter. Try to avoid trivial A->a mappings 351 thisdir := dir%25 + 1 352 // Calculate the offset of this character in A-Za-z 353 pos := int(runeValue - 'A') 354 if pos >= 26 { 355 pos -= 6 // It's lower case 356 } 357 // Rotate the character to the new location 358 pos = (pos + thisdir) % 52 359 if pos >= 26 { 360 pos += 6 // and handle lower case offset again 361 } 362 _, _ = result.WriteRune(rune('A' + pos)) 363 364 case runeValue >= 0xA0 && runeValue <= 0xFF: 365 // Latin 1 supplement 366 thisdir := (dir % 95) + 1 367 newRune := 0xA0 + (int(runeValue)-0xA0+thisdir)%96 368 _, _ = result.WriteRune(rune(newRune)) 369 370 case runeValue >= 0x100: 371 // Some random Unicode range; we have no good rules here 372 thisdir := (dir % 127) + 1 373 base := int(runeValue - runeValue%256) 374 newRune := rune(base + (int(runeValue)-base+thisdir)%256) 375 // If the new character isn't a valid UTF8 char 376 // then don't rotate it. Quote it instead 377 if !utf8.ValidRune(newRune) { 378 _, _ = result.WriteRune(obfuscQuoteRune) 379 _, _ = result.WriteRune(runeValue) 380 } else { 381 _, _ = result.WriteRune(newRune) 382 } 383 384 default: 385 // Leave character untouched 386 _, _ = result.WriteRune(runeValue) 387 } 388 } 389 return result.String() 390 } 391 392 func (c *cipher) deobfuscateSegment(ciphertext string) (string, error) { 393 if ciphertext == "" { 394 return "", nil 395 } 396 pos := strings.Index(ciphertext, ".") 397 if pos == -1 { 398 return "", ErrorNotAnEncryptedFile 399 } // No . 400 num := ciphertext[:pos] 401 if num == "!" { 402 // No rotation; probably original was not valid unicode 403 return ciphertext[pos+1:], nil 404 } 405 dir, err := strconv.Atoi(num) 406 if err != nil { 407 return "", ErrorNotAnEncryptedFile // Not a number 408 } 409 410 // add the nameKey to get the real rotate distance 411 for i := 0; i < len(c.nameKey); i++ { 412 dir += int(c.nameKey[i]) 413 } 414 415 var result bytes.Buffer 416 417 inQuote := false 418 for _, runeValue := range ciphertext[pos+1:] { 419 switch { 420 case inQuote: 421 _, _ = result.WriteRune(runeValue) 422 inQuote = false 423 424 case runeValue == obfuscQuoteRune: 425 inQuote = true 426 427 case runeValue >= '0' && runeValue <= '9': 428 // Number 429 thisdir := (dir % 9) + 1 430 newRune := '0' + int(runeValue) - '0' - thisdir 431 if newRune < '0' { 432 newRune += 10 433 } 434 _, _ = result.WriteRune(rune(newRune)) 435 436 case (runeValue >= 'A' && runeValue <= 'Z') || 437 (runeValue >= 'a' && runeValue <= 'z'): 438 thisdir := dir%25 + 1 439 pos := int(runeValue - 'A') 440 if pos >= 26 { 441 pos -= 6 442 } 443 pos = pos - thisdir 444 if pos < 0 { 445 pos += 52 446 } 447 if pos >= 26 { 448 pos += 6 449 } 450 _, _ = result.WriteRune(rune('A' + pos)) 451 452 case runeValue >= 0xA0 && runeValue <= 0xFF: 453 thisdir := (dir % 95) + 1 454 newRune := 0xA0 + int(runeValue) - 0xA0 - thisdir 455 if newRune < 0xA0 { 456 newRune += 96 457 } 458 _, _ = result.WriteRune(rune(newRune)) 459 460 case runeValue >= 0x100: 461 thisdir := (dir % 127) + 1 462 base := int(runeValue - runeValue%256) 463 newRune := rune(base + (int(runeValue) - base - thisdir)) 464 if int(newRune) < base { 465 newRune += 256 466 } 467 _, _ = result.WriteRune(newRune) 468 469 default: 470 _, _ = result.WriteRune(runeValue) 471 472 } 473 } 474 475 return result.String(), nil 476 } 477 478 // encryptFileName encrypts a file path 479 func (c *cipher) encryptFileName(in string) string { 480 segments := strings.Split(in, "/") 481 for i := range segments { 482 // Skip directory name encryption if the user chose to 483 // leave them intact 484 if !c.dirNameEncrypt && i != (len(segments)-1) { 485 continue 486 } 487 if c.mode == NameEncryptionStandard { 488 segments[i] = c.encryptSegment(segments[i]) 489 } else { 490 segments[i] = c.obfuscateSegment(segments[i]) 491 } 492 } 493 return strings.Join(segments, "/") 494 } 495 496 // EncryptFileName encrypts a file path 497 func (c *cipher) EncryptFileName(in string) string { 498 if c.mode == NameEncryptionOff { 499 return in + encryptedSuffix 500 } 501 return c.encryptFileName(in) 502 } 503 504 // EncryptDirName encrypts a directory path 505 func (c *cipher) EncryptDirName(in string) string { 506 if c.mode == NameEncryptionOff || !c.dirNameEncrypt { 507 return in 508 } 509 return c.encryptFileName(in) 510 } 511 512 // decryptFileName decrypts a file path 513 func (c *cipher) decryptFileName(in string) (string, error) { 514 segments := strings.Split(in, "/") 515 for i := range segments { 516 var err error 517 // Skip directory name decryption if the user chose to 518 // leave them intact 519 if !c.dirNameEncrypt && i != (len(segments)-1) { 520 continue 521 } 522 if c.mode == NameEncryptionStandard { 523 segments[i], err = c.decryptSegment(segments[i]) 524 } else { 525 segments[i], err = c.deobfuscateSegment(segments[i]) 526 } 527 528 if err != nil { 529 return "", err 530 } 531 } 532 return strings.Join(segments, "/"), nil 533 } 534 535 // DecryptFileName decrypts a file path 536 func (c *cipher) DecryptFileName(in string) (string, error) { 537 if c.mode == NameEncryptionOff { 538 remainingLength := len(in) - len(encryptedSuffix) 539 if remainingLength > 0 && strings.HasSuffix(in, encryptedSuffix) { 540 return in[:remainingLength], nil 541 } 542 return "", ErrorNotAnEncryptedFile 543 } 544 return c.decryptFileName(in) 545 } 546 547 // DecryptDirName decrypts a directory path 548 func (c *cipher) DecryptDirName(in string) (string, error) { 549 if c.mode == NameEncryptionOff || !c.dirNameEncrypt { 550 return in, nil 551 } 552 return c.decryptFileName(in) 553 } 554 555 func (c *cipher) NameEncryptionMode() NameEncryptionMode { 556 return c.mode 557 } 558 559 // nonce is an NACL secretbox nonce 560 type nonce [fileNonceSize]byte 561 562 // pointer returns the nonce as a *[24]byte for secretbox 563 func (n *nonce) pointer() *[fileNonceSize]byte { 564 return (*[fileNonceSize]byte)(n) 565 } 566 567 // fromReader fills the nonce from an io.Reader - normally the OSes 568 // crypto random number generator 569 func (n *nonce) fromReader(in io.Reader) error { 570 read, err := io.ReadFull(in, (*n)[:]) 571 if read != fileNonceSize { 572 return errors.Wrap(err, "short read of nonce") 573 } 574 return nil 575 } 576 577 // fromBuf fills the nonce from the buffer passed in 578 func (n *nonce) fromBuf(buf []byte) { 579 read := copy((*n)[:], buf) 580 if read != fileNonceSize { 581 panic("buffer to short to read nonce") 582 } 583 } 584 585 // carry 1 up the nonce from position i 586 func (n *nonce) carry(i int) { 587 for ; i < len(*n); i++ { 588 digit := (*n)[i] 589 newDigit := digit + 1 590 (*n)[i] = newDigit 591 if newDigit >= digit { 592 // exit if no carry 593 break 594 } 595 } 596 } 597 598 // increment to add 1 to the nonce 599 func (n *nonce) increment() { 600 n.carry(0) 601 } 602 603 // add an uint64 to the nonce 604 func (n *nonce) add(x uint64) { 605 carry := uint16(0) 606 for i := 0; i < 8; i++ { 607 digit := (*n)[i] 608 xDigit := byte(x) 609 x >>= 8 610 carry += uint16(digit) + uint16(xDigit) 611 (*n)[i] = byte(carry) 612 carry >>= 8 613 } 614 if carry != 0 { 615 n.carry(8) 616 } 617 } 618 619 // encrypter encrypts an io.Reader on the fly 620 type encrypter struct { 621 mu sync.Mutex 622 in io.Reader 623 c *cipher 624 nonce nonce 625 buf []byte 626 readBuf []byte 627 bufIndex int 628 bufSize int 629 err error 630 } 631 632 // newEncrypter creates a new file handle encrypting on the fly 633 func (c *cipher) newEncrypter(in io.Reader, nonce *nonce) (*encrypter, error) { 634 fh := &encrypter{ 635 in: in, 636 c: c, 637 buf: c.getBlock(), 638 readBuf: c.getBlock(), 639 bufSize: fileHeaderSize, 640 } 641 // Initialise nonce 642 if nonce != nil { 643 fh.nonce = *nonce 644 } else { 645 err := fh.nonce.fromReader(c.cryptoRand) 646 if err != nil { 647 return nil, err 648 } 649 } 650 // Copy magic into buffer 651 copy(fh.buf, fileMagicBytes) 652 // Copy nonce into buffer 653 copy(fh.buf[fileMagicSize:], fh.nonce[:]) 654 return fh, nil 655 } 656 657 // Read as per io.Reader 658 func (fh *encrypter) Read(p []byte) (n int, err error) { 659 fh.mu.Lock() 660 defer fh.mu.Unlock() 661 662 if fh.err != nil { 663 return 0, fh.err 664 } 665 if fh.bufIndex >= fh.bufSize { 666 // Read data 667 // FIXME should overlap the reads with a go-routine and 2 buffers? 668 readBuf := fh.readBuf[:blockDataSize] 669 n, err = io.ReadFull(fh.in, readBuf) 670 if n == 0 { 671 // err can't be nil since: 672 // n == len(buf) if and only if err == nil. 673 return fh.finish(err) 674 } 675 // possibly err != nil here, but we will process the 676 // data and the next call to ReadFull will return 0, err 677 // Write nonce to start of block 678 copy(fh.buf, fh.nonce[:]) 679 // Encrypt the block using the nonce 680 block := fh.buf 681 secretbox.Seal(block[:0], readBuf[:n], fh.nonce.pointer(), &fh.c.dataKey) 682 fh.bufIndex = 0 683 fh.bufSize = blockHeaderSize + n 684 fh.nonce.increment() 685 } 686 n = copy(p, fh.buf[fh.bufIndex:fh.bufSize]) 687 fh.bufIndex += n 688 return n, nil 689 } 690 691 // finish sets the final error and tidies up 692 func (fh *encrypter) finish(err error) (int, error) { 693 if fh.err != nil { 694 return 0, fh.err 695 } 696 fh.err = err 697 fh.c.putBlock(fh.buf) 698 fh.buf = nil 699 fh.c.putBlock(fh.readBuf) 700 fh.readBuf = nil 701 return 0, err 702 } 703 704 // Encrypt data encrypts the data stream 705 func (c *cipher) EncryptData(in io.Reader) (io.Reader, error) { 706 in, wrap := accounting.UnWrap(in) // unwrap the accounting off the Reader 707 out, err := c.newEncrypter(in, nil) 708 if err != nil { 709 return nil, err 710 } 711 return wrap(out), nil // and wrap the accounting back on 712 } 713 714 // decrypter decrypts an io.ReaderCloser on the fly 715 type decrypter struct { 716 mu sync.Mutex 717 rc io.ReadCloser 718 nonce nonce 719 initialNonce nonce 720 c *cipher 721 buf []byte 722 readBuf []byte 723 bufIndex int 724 bufSize int 725 err error 726 limit int64 // limit of bytes to read, -1 for unlimited 727 open OpenRangeSeek 728 } 729 730 // newDecrypter creates a new file handle decrypting on the fly 731 func (c *cipher) newDecrypter(rc io.ReadCloser) (*decrypter, error) { 732 fh := &decrypter{ 733 rc: rc, 734 c: c, 735 buf: c.getBlock(), 736 readBuf: c.getBlock(), 737 limit: -1, 738 } 739 // Read file header (magic + nonce) 740 readBuf := fh.readBuf[:fileHeaderSize] 741 _, err := io.ReadFull(fh.rc, readBuf) 742 if err == io.EOF || err == io.ErrUnexpectedEOF { 743 // This read from 0..fileHeaderSize-1 bytes 744 return nil, fh.finishAndClose(ErrorEncryptedFileTooShort) 745 } else if err != nil { 746 return nil, fh.finishAndClose(err) 747 } 748 // check the magic 749 if !bytes.Equal(readBuf[:fileMagicSize], fileMagicBytes) { 750 return nil, fh.finishAndClose(ErrorEncryptedBadMagic) 751 } 752 // retrieve the nonce 753 fh.nonce.fromBuf(readBuf[fileMagicSize:]) 754 fh.initialNonce = fh.nonce 755 return fh, nil 756 } 757 758 // newDecrypterSeek creates a new file handle decrypting on the fly 759 func (c *cipher) newDecrypterSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (fh *decrypter, err error) { 760 var rc io.ReadCloser 761 doRangeSeek := false 762 setLimit := false 763 // Open initially with no seek 764 if offset == 0 && limit < 0 { 765 // If no offset or limit then open whole file 766 rc, err = open(ctx, 0, -1) 767 } else if offset == 0 { 768 // If no offset open the header + limit worth of the file 769 _, underlyingLimit, _, _ := calculateUnderlying(offset, limit) 770 rc, err = open(ctx, 0, int64(fileHeaderSize)+underlyingLimit) 771 setLimit = true 772 } else { 773 // Otherwise just read the header to start with 774 rc, err = open(ctx, 0, int64(fileHeaderSize)) 775 doRangeSeek = true 776 } 777 if err != nil { 778 return nil, err 779 } 780 // Open the stream which fills in the nonce 781 fh, err = c.newDecrypter(rc) 782 if err != nil { 783 return nil, err 784 } 785 fh.open = open // will be called by fh.RangeSeek 786 if doRangeSeek { 787 _, err = fh.RangeSeek(ctx, offset, io.SeekStart, limit) 788 if err != nil { 789 _ = fh.Close() 790 return nil, err 791 } 792 } 793 if setLimit { 794 fh.limit = limit 795 } 796 return fh, nil 797 } 798 799 // read data into internal buffer - call with fh.mu held 800 func (fh *decrypter) fillBuffer() (err error) { 801 // FIXME should overlap the reads with a go-routine and 2 buffers? 802 readBuf := fh.readBuf 803 n, err := io.ReadFull(fh.rc, readBuf) 804 if n == 0 { 805 // err can't be nil since: 806 // n == len(buf) if and only if err == nil. 807 return err 808 } 809 // possibly err != nil here, but we will process the data and 810 // the next call to ReadFull will return 0, err 811 812 // Check header + 1 byte exists 813 if n <= blockHeaderSize { 814 if err != nil { 815 return err // return pending error as it is likely more accurate 816 } 817 return ErrorEncryptedFileBadHeader 818 } 819 // Decrypt the block using the nonce 820 block := fh.buf 821 _, ok := secretbox.Open(block[:0], readBuf[:n], fh.nonce.pointer(), &fh.c.dataKey) 822 if !ok { 823 if err != nil { 824 return err // return pending error as it is likely more accurate 825 } 826 return ErrorEncryptedBadBlock 827 } 828 fh.bufIndex = 0 829 fh.bufSize = n - blockHeaderSize 830 fh.nonce.increment() 831 return nil 832 } 833 834 // Read as per io.Reader 835 func (fh *decrypter) Read(p []byte) (n int, err error) { 836 fh.mu.Lock() 837 defer fh.mu.Unlock() 838 839 if fh.err != nil { 840 return 0, fh.err 841 } 842 if fh.bufIndex >= fh.bufSize { 843 err = fh.fillBuffer() 844 if err != nil { 845 return 0, fh.finish(err) 846 } 847 } 848 toCopy := fh.bufSize - fh.bufIndex 849 if fh.limit >= 0 && fh.limit < int64(toCopy) { 850 toCopy = int(fh.limit) 851 } 852 n = copy(p, fh.buf[fh.bufIndex:fh.bufIndex+toCopy]) 853 fh.bufIndex += n 854 if fh.limit >= 0 { 855 fh.limit -= int64(n) 856 if fh.limit == 0 { 857 return n, fh.finish(io.EOF) 858 } 859 } 860 return n, nil 861 } 862 863 // calculateUnderlying converts an (offset, limit) in a crypted file 864 // into an (underlyingOffset, underlyingLimit) for the underlying 865 // file. 866 // 867 // It also returns number of bytes to discard after reading the first 868 // block and number of blocks this is from the start so the nonce can 869 // be incremented. 870 func calculateUnderlying(offset, limit int64) (underlyingOffset, underlyingLimit, discard, blocks int64) { 871 // blocks we need to seek, plus bytes we need to discard 872 blocks, discard = offset/blockDataSize, offset%blockDataSize 873 874 // Offset in underlying stream we need to seek 875 underlyingOffset = int64(fileHeaderSize) + blocks*(blockHeaderSize+blockDataSize) 876 877 // work out how many blocks we need to read 878 underlyingLimit = int64(-1) 879 if limit >= 0 { 880 // bytes to read beyond the first block 881 bytesToRead := limit - (blockDataSize - discard) 882 883 // Read the first block 884 blocksToRead := int64(1) 885 886 if bytesToRead > 0 { 887 // Blocks that need to be read plus left over blocks 888 extraBlocksToRead, endBytes := bytesToRead/blockDataSize, bytesToRead%blockDataSize 889 if endBytes != 0 { 890 // If left over bytes must read another block 891 extraBlocksToRead++ 892 } 893 blocksToRead += extraBlocksToRead 894 } 895 896 // Must read a whole number of blocks 897 underlyingLimit = blocksToRead * (blockHeaderSize + blockDataSize) 898 } 899 return 900 } 901 902 // RangeSeek behaves like a call to Seek(offset int64, whence 903 // int) with the output wrapped in an io.LimitedReader 904 // limiting the total length to limit. 905 // 906 // RangeSeek with a limit of < 0 is equivalent to a regular Seek. 907 func (fh *decrypter) RangeSeek(ctx context.Context, offset int64, whence int, limit int64) (int64, error) { 908 fh.mu.Lock() 909 defer fh.mu.Unlock() 910 911 if fh.open == nil { 912 return 0, fh.finish(errors.New("can't seek - not initialised with newDecrypterSeek")) 913 } 914 if whence != io.SeekStart { 915 return 0, fh.finish(errors.New("can only seek from the start")) 916 } 917 918 // Reset error or return it if not EOF 919 if fh.err == io.EOF { 920 fh.unFinish() 921 } else if fh.err != nil { 922 return 0, fh.err 923 } 924 925 underlyingOffset, underlyingLimit, discard, blocks := calculateUnderlying(offset, limit) 926 927 // Move the nonce on the correct number of blocks from the start 928 fh.nonce = fh.initialNonce 929 fh.nonce.add(uint64(blocks)) 930 931 // Can we seek underlying stream directly? 932 if do, ok := fh.rc.(fs.RangeSeeker); ok { 933 // Seek underlying stream directly 934 _, err := do.RangeSeek(ctx, underlyingOffset, 0, underlyingLimit) 935 if err != nil { 936 return 0, fh.finish(err) 937 } 938 } else { 939 // if not reopen with seek 940 _ = fh.rc.Close() // close underlying file 941 fh.rc = nil 942 943 // Re-open the underlying object with the offset given 944 rc, err := fh.open(ctx, underlyingOffset, underlyingLimit) 945 if err != nil { 946 return 0, fh.finish(errors.Wrap(err, "couldn't reopen file with offset and limit")) 947 } 948 949 // Set the file handle 950 fh.rc = rc 951 } 952 953 // Fill the buffer 954 err := fh.fillBuffer() 955 if err != nil { 956 return 0, fh.finish(err) 957 } 958 959 // Discard bytes from the buffer 960 if int(discard) > fh.bufSize { 961 return 0, fh.finish(ErrorBadSeek) 962 } 963 fh.bufIndex = int(discard) 964 965 // Set the limit 966 fh.limit = limit 967 968 return offset, nil 969 } 970 971 // Seek implements the io.Seeker interface 972 func (fh *decrypter) Seek(offset int64, whence int) (int64, error) { 973 return fh.RangeSeek(context.TODO(), offset, whence, -1) 974 } 975 976 // finish sets the final error and tidies up 977 func (fh *decrypter) finish(err error) error { 978 if fh.err != nil { 979 return fh.err 980 } 981 fh.err = err 982 fh.c.putBlock(fh.buf) 983 fh.buf = nil 984 fh.c.putBlock(fh.readBuf) 985 fh.readBuf = nil 986 return err 987 } 988 989 // unFinish undoes the effects of finish 990 func (fh *decrypter) unFinish() { 991 // Clear error 992 fh.err = nil 993 994 // reinstate the buffers 995 fh.buf = fh.c.getBlock() 996 fh.readBuf = fh.c.getBlock() 997 998 // Empty the buffer 999 fh.bufIndex = 0 1000 fh.bufSize = 0 1001 } 1002 1003 // Close 1004 func (fh *decrypter) Close() error { 1005 fh.mu.Lock() 1006 defer fh.mu.Unlock() 1007 1008 // Check already closed 1009 if fh.err == ErrorFileClosed { 1010 return fh.err 1011 } 1012 // Closed before reading EOF so not finish()ed yet 1013 if fh.err == nil { 1014 _ = fh.finish(io.EOF) 1015 } 1016 // Show file now closed 1017 fh.err = ErrorFileClosed 1018 if fh.rc == nil { 1019 return nil 1020 } 1021 return fh.rc.Close() 1022 } 1023 1024 // finishAndClose does finish then Close() 1025 // 1026 // Used when we are returning a nil fh from new 1027 func (fh *decrypter) finishAndClose(err error) error { 1028 _ = fh.finish(err) 1029 _ = fh.Close() 1030 return err 1031 } 1032 1033 // DecryptData decrypts the data stream 1034 func (c *cipher) DecryptData(rc io.ReadCloser) (io.ReadCloser, error) { 1035 out, err := c.newDecrypter(rc) 1036 if err != nil { 1037 return nil, err 1038 } 1039 return out, nil 1040 } 1041 1042 // DecryptDataSeek decrypts the data stream from offset 1043 // 1044 // The open function must return a ReadCloser opened to the offset supplied 1045 // 1046 // You must use this form of DecryptData if you might want to Seek the file handle 1047 func (c *cipher) DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (ReadSeekCloser, error) { 1048 out, err := c.newDecrypterSeek(ctx, open, offset, limit) 1049 if err != nil { 1050 return nil, err 1051 } 1052 return out, nil 1053 } 1054 1055 // EncryptedSize calculates the size of the data when encrypted 1056 func (c *cipher) EncryptedSize(size int64) int64 { 1057 blocks, residue := size/blockDataSize, size%blockDataSize 1058 encryptedSize := int64(fileHeaderSize) + blocks*(blockHeaderSize+blockDataSize) 1059 if residue != 0 { 1060 encryptedSize += blockHeaderSize + residue 1061 } 1062 return encryptedSize 1063 } 1064 1065 // DecryptedSize calculates the size of the data when decrypted 1066 func (c *cipher) DecryptedSize(size int64) (int64, error) { 1067 size -= int64(fileHeaderSize) 1068 if size < 0 { 1069 return 0, ErrorEncryptedFileTooShort 1070 } 1071 blocks, residue := size/blockSize, size%blockSize 1072 decryptedSize := blocks * blockDataSize 1073 if residue != 0 { 1074 residue -= blockHeaderSize 1075 if residue <= 0 { 1076 return 0, ErrorEncryptedFileBadHeader 1077 } 1078 } 1079 decryptedSize += residue 1080 return decryptedSize, nil 1081 } 1082 1083 // check interfaces 1084 var ( 1085 _ Cipher = (*cipher)(nil) 1086 _ io.ReadCloser = (*decrypter)(nil) 1087 _ io.Seeker = (*decrypter)(nil) 1088 _ fs.RangeSeeker = (*decrypter)(nil) 1089 _ io.Reader = (*encrypter)(nil) 1090 )