diff --git a/backend/crypt/cipher.go b/backend/crypt/cipher.go index 05105c53a..4b1345d5b 100644 --- a/backend/crypt/cipher.go +++ b/backend/crypt/cipher.go @@ -91,6 +91,8 @@ type Cipher interface { EncryptedSize(int64) int64 // DecryptedSize calculates the size of the data when decrypted DecryptedSize(int64) (int64, error) + // NameEncryptionMode returns the used mode for name handling + NameEncryptionMode() NameEncryptionMode } // NameEncryptionMode is the type of file name encryption in use @@ -547,6 +549,10 @@ func (c *cipher) DecryptDirName(in string) (string, error) { return c.decryptFileName(in) } +func (c *cipher) NameEncryptionMode() NameEncryptionMode { + return c.mode +} + // nonce is an NACL secretbox nonce type nonce [fileNonceSize]byte diff --git a/backend/crypt/crypt.go b/backend/crypt/crypt.go index 415fc4c6b..8176a82bf 100644 --- a/backend/crypt/crypt.go +++ b/backend/crypt/crypt.go @@ -73,8 +73,8 @@ func init() { }) } -// NewFs contstructs an Fs from the path, container:path -func NewFs(name, rpath string) (fs.Fs, error) { +// NewCipher constructs a Cipher for the given config name +func NewCipher(name string) (Cipher, error) { mode, err := NewNameEncryptionMode(config.FileGet(name, "filename_encryption", "standard")) if err != nil { return nil, err @@ -102,6 +102,15 @@ func NewFs(name, rpath string) (fs.Fs, error) { if err != nil { return nil, errors.Wrap(err, "failed to make cipher") } + return cipher, nil +} + +// NewFs contstructs an Fs from the path, container:path +func NewFs(name, rpath string) (fs.Fs, error) { + cipher, err := NewCipher(name) + if err != nil { + return nil, err + } remote := config.FileGet(name, "remote") if strings.HasPrefix(remote, name+":") { return nil, errors.New("can't point crypt remote at itself - check the value of the remote setting") @@ -122,12 +131,11 @@ func NewFs(name, rpath string) (fs.Fs, error) { name: name, root: rpath, cipher: cipher, - mode: mode, } // the features here are ones we could support, and they are // ANDed with the ones from wrappedFs f.features = (&fs.Features{ - CaseInsensitive: mode == NameEncryptionOff, + CaseInsensitive: cipher.NameEncryptionMode() == NameEncryptionOff, DuplicateFiles: true, ReadMimeType: false, // MimeTypes not supported with crypt WriteMimeType: false, diff --git a/cmd/cryptdecode/cryptdecode.go b/cmd/cryptdecode/cryptdecode.go index 28cd351e8..00585112e 100644 --- a/cmd/cryptdecode/cryptdecode.go +++ b/cmd/cryptdecode/cryptdecode.go @@ -1,13 +1,13 @@ package cryptdecode import ( + "errors" "fmt" "github.com/ncw/rclone/backend/crypt" "github.com/ncw/rclone/cmd" "github.com/ncw/rclone/fs" "github.com/ncw/rclone/fs/config/flags" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -39,40 +39,32 @@ use it like this `, Run: func(command *cobra.Command, args []string) { cmd.CheckArgs(2, 11, command, args) - fsrc := cmd.NewFsSrc(args) - if Reverse { - cmd.Run(false, false, command, func() error { - return cryptEncode(fsrc, args[1:]) - }) - } else { - cmd.Run(false, false, command, func() error { - return cryptDecode(fsrc, args[1:]) - }) - } + cmd.Run(false, false, command, func() error { + fsInfo, configName, _, err := fs.ParseRemote(args[0]) + if err != nil { + return err + } + if fsInfo.Name != "crypt" { + return errors.New("The remote needs to be of type \"crypt\"") + } + cipher, err := crypt.NewCipher(configName) + if err != nil { + return err + } + if Reverse { + return cryptEncode(cipher, args[1:]) + } + return cryptDecode(cipher, args[1:]) + }) }, } -// Check if fsrc is a crypt -func assertCryptFs(fsrc fs.Fs) (*crypt.Fs, error) { - fcrypt, ok := fsrc.(*crypt.Fs) - if !ok { - return nil, errors.Errorf("%s:%s is not a crypt remote", fsrc.Name(), fsrc.Root()) - } - return fcrypt, nil -} - // cryptDecode returns the unencrypted file name -func cryptDecode(fsrc fs.Fs, args []string) error { - fcrypt, err := assertCryptFs(fsrc) - - if err != nil { - return err - } - +func cryptDecode(cipher crypt.Cipher, args []string) error { output := "" for _, encryptedFileName := range args { - fileName, err := fcrypt.DecryptFileName(encryptedFileName) + fileName, err := cipher.DecryptFileName(encryptedFileName) if err != nil { output += fmt.Sprintln(encryptedFileName, "\t", "Failed to decrypt") } else { @@ -86,17 +78,11 @@ func cryptDecode(fsrc fs.Fs, args []string) error { } // cryptEncode returns the encrypted file name -func cryptEncode(fsrc fs.Fs, args []string) error { - fcrypt, err := assertCryptFs(fsrc) - - if err != nil { - return err - } - +func cryptEncode(cipher crypt.Cipher, args []string) error { output := "" for _, fileName := range args { - encryptedFileName := fcrypt.EncryptFileName(fileName) + encryptedFileName := cipher.EncryptFileName(fileName) output += fmt.Sprintln(fileName, "\t", encryptedFileName) }