From 44b1a591a825fe8e4bd9b87e56625def5fbb8024 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 9 Apr 2020 16:17:17 +0100 Subject: [PATCH] crypt: get rid of the unused Cipher interface as it obfuscated the code --- backend/crypt/cipher.go | 80 ++++++++++++---------------------- backend/crypt/crypt.go | 10 ++--- cmd/cryptdecode/cryptdecode.go | 4 +- fs/operations/lsjson.go | 2 +- 4 files changed, 36 insertions(+), 60 deletions(-) diff --git a/backend/crypt/cipher.go b/backend/crypt/cipher.go index afd107df3..4e774e0b7 100644 --- a/backend/crypt/cipher.go +++ b/backend/crypt/cipher.go @@ -71,30 +71,6 @@ type ReadSeekCloser interface { // OpenRangeSeek opens the file handle at the offset with the limit given type OpenRangeSeek func(ctx context.Context, offset, limit int64) (io.ReadCloser, error) -// Cipher is used to swap out the encryption implementations -type Cipher interface { - // EncryptFileName encrypts a file path - EncryptFileName(string) string - // DecryptFileName decrypts a file path, returns error if decrypt was invalid - DecryptFileName(string) (string, error) - // EncryptDirName encrypts a directory path - EncryptDirName(string) string - // DecryptDirName decrypts a directory path, returns error if decrypt was invalid - DecryptDirName(string) (string, error) - // EncryptData - EncryptData(io.Reader) (io.Reader, error) - // DecryptData - DecryptData(io.ReadCloser) (io.ReadCloser, error) - // DecryptDataSeek decrypt at a given position - DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (ReadSeekCloser, error) - // EncryptedSize calculates the size of the data when encrypted - 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 type NameEncryptionMode int @@ -136,7 +112,8 @@ func (mode NameEncryptionMode) String() (out string) { return out } -type cipher struct { +// Cipher defines an encoding and decoding cipher for the crypt backend +type Cipher struct { dataKey [32]byte // Key for secretbox nameKey [32]byte // 16,24 or 32 bytes nameTweak [nameCipherBlockSize]byte // used to tweak the name crypto @@ -148,8 +125,8 @@ type cipher struct { } // newCipher initialises the cipher. If salt is "" then it uses a built in salt val -func newCipher(mode NameEncryptionMode, password, salt string, dirNameEncrypt bool) (*cipher, error) { - c := &cipher{ +func newCipher(mode NameEncryptionMode, password, salt string, dirNameEncrypt bool) (*Cipher, error) { + c := &Cipher{ mode: mode, cryptoRand: rand.Reader, dirNameEncrypt: dirNameEncrypt, @@ -172,7 +149,7 @@ func newCipher(mode NameEncryptionMode, password, salt string, dirNameEncrypt bo // // Note that empty passsword makes all 0x00 keys which is used in the // tests. -func (c *cipher) Key(password, salt string) (err error) { +func (c *Cipher) Key(password, salt string) (err error) { const keySize = len(c.dataKey) + len(c.nameKey) + len(c.nameTweak) var saltBytes = defaultSalt if salt != "" { @@ -196,12 +173,12 @@ func (c *cipher) Key(password, salt string) (err error) { } // getBlock gets a block from the pool of size blockSize -func (c *cipher) getBlock() []byte { +func (c *Cipher) getBlock() []byte { return c.buffers.Get().([]byte) } // putBlock returns a block to the pool of size blockSize -func (c *cipher) putBlock(buf []byte) { +func (c *Cipher) putBlock(buf []byte) { if len(buf) != blockSize { panic("bad blocksize returned to pool") } @@ -246,7 +223,7 @@ func decodeFileName(in string) ([]byte, error) { // This means that // * filenames with the same name will encrypt the same // * filenames which start the same won't have a common prefix -func (c *cipher) encryptSegment(plaintext string) string { +func (c *Cipher) encryptSegment(plaintext string) string { if plaintext == "" { return "" } @@ -256,7 +233,7 @@ func (c *cipher) encryptSegment(plaintext string) string { } // decryptSegment decrypts a path segment -func (c *cipher) decryptSegment(ciphertext string) (string, error) { +func (c *Cipher) decryptSegment(ciphertext string) (string, error) { if ciphertext == "" { return "", nil } @@ -283,7 +260,7 @@ func (c *cipher) decryptSegment(ciphertext string) (string, error) { } // Simple obfuscation routines -func (c *cipher) obfuscateSegment(plaintext string) string { +func (c *Cipher) obfuscateSegment(plaintext string) string { if plaintext == "" { return "" } @@ -370,7 +347,7 @@ func (c *cipher) obfuscateSegment(plaintext string) string { return result.String() } -func (c *cipher) deobfuscateSegment(ciphertext string) (string, error) { +func (c *Cipher) deobfuscateSegment(ciphertext string) (string, error) { if ciphertext == "" { return "", nil } @@ -457,7 +434,7 @@ func (c *cipher) deobfuscateSegment(ciphertext string) (string, error) { } // encryptFileName encrypts a file path -func (c *cipher) encryptFileName(in string) string { +func (c *Cipher) encryptFileName(in string) string { segments := strings.Split(in, "/") for i := range segments { // Skip directory name encryption if the user chose to @@ -475,7 +452,7 @@ func (c *cipher) encryptFileName(in string) string { } // EncryptFileName encrypts a file path -func (c *cipher) EncryptFileName(in string) string { +func (c *Cipher) EncryptFileName(in string) string { if c.mode == NameEncryptionOff { return in + encryptedSuffix } @@ -483,7 +460,7 @@ func (c *cipher) EncryptFileName(in string) string { } // EncryptDirName encrypts a directory path -func (c *cipher) EncryptDirName(in string) string { +func (c *Cipher) EncryptDirName(in string) string { if c.mode == NameEncryptionOff || !c.dirNameEncrypt { return in } @@ -491,7 +468,7 @@ func (c *cipher) EncryptDirName(in string) string { } // decryptFileName decrypts a file path -func (c *cipher) decryptFileName(in string) (string, error) { +func (c *Cipher) decryptFileName(in string) (string, error) { segments := strings.Split(in, "/") for i := range segments { var err error @@ -514,7 +491,7 @@ func (c *cipher) decryptFileName(in string) (string, error) { } // DecryptFileName decrypts a file path -func (c *cipher) DecryptFileName(in string) (string, error) { +func (c *Cipher) DecryptFileName(in string) (string, error) { if c.mode == NameEncryptionOff { remainingLength := len(in) - len(encryptedSuffix) if remainingLength > 0 && strings.HasSuffix(in, encryptedSuffix) { @@ -526,14 +503,14 @@ func (c *cipher) DecryptFileName(in string) (string, error) { } // DecryptDirName decrypts a directory path -func (c *cipher) DecryptDirName(in string) (string, error) { +func (c *Cipher) DecryptDirName(in string) (string, error) { if c.mode == NameEncryptionOff || !c.dirNameEncrypt { return in, nil } return c.decryptFileName(in) } -func (c *cipher) NameEncryptionMode() NameEncryptionMode { +func (c *Cipher) NameEncryptionMode() NameEncryptionMode { return c.mode } @@ -601,7 +578,7 @@ func (n *nonce) add(x uint64) { type encrypter struct { mu sync.Mutex in io.Reader - c *cipher + c *Cipher nonce nonce buf []byte readBuf []byte @@ -611,7 +588,7 @@ type encrypter struct { } // newEncrypter creates a new file handle encrypting on the fly -func (c *cipher) newEncrypter(in io.Reader, nonce *nonce) (*encrypter, error) { +func (c *Cipher) newEncrypter(in io.Reader, nonce *nonce) (*encrypter, error) { fh := &encrypter{ in: in, c: c, @@ -683,7 +660,7 @@ func (fh *encrypter) finish(err error) (int, error) { } // Encrypt data encrypts the data stream -func (c *cipher) EncryptData(in io.Reader) (io.Reader, error) { +func (c *Cipher) EncryptData(in io.Reader) (io.Reader, error) { in, wrap := accounting.UnWrap(in) // unwrap the accounting off the Reader out, err := c.newEncrypter(in, nil) if err != nil { @@ -698,7 +675,7 @@ type decrypter struct { rc io.ReadCloser nonce nonce initialNonce nonce - c *cipher + c *Cipher buf []byte readBuf []byte bufIndex int @@ -709,7 +686,7 @@ type decrypter struct { } // newDecrypter creates a new file handle decrypting on the fly -func (c *cipher) newDecrypter(rc io.ReadCloser) (*decrypter, error) { +func (c *Cipher) newDecrypter(rc io.ReadCloser) (*decrypter, error) { fh := &decrypter{ rc: rc, c: c, @@ -737,7 +714,7 @@ func (c *cipher) newDecrypter(rc io.ReadCloser) (*decrypter, error) { } // newDecrypterSeek creates a new file handle decrypting on the fly -func (c *cipher) newDecrypterSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (fh *decrypter, err error) { +func (c *Cipher) newDecrypterSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (fh *decrypter, err error) { var rc io.ReadCloser doRangeSeek := false setLimit := false @@ -1012,7 +989,7 @@ func (fh *decrypter) finishAndClose(err error) error { } // DecryptData decrypts the data stream -func (c *cipher) DecryptData(rc io.ReadCloser) (io.ReadCloser, error) { +func (c *Cipher) DecryptData(rc io.ReadCloser) (io.ReadCloser, error) { out, err := c.newDecrypter(rc) if err != nil { return nil, err @@ -1025,7 +1002,7 @@ func (c *cipher) DecryptData(rc io.ReadCloser) (io.ReadCloser, error) { // The open function must return a ReadCloser opened to the offset supplied // // You must use this form of DecryptData if you might want to Seek the file handle -func (c *cipher) DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (ReadSeekCloser, error) { +func (c *Cipher) DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (ReadSeekCloser, error) { out, err := c.newDecrypterSeek(ctx, open, offset, limit) if err != nil { return nil, err @@ -1034,7 +1011,7 @@ func (c *cipher) DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset } // EncryptedSize calculates the size of the data when encrypted -func (c *cipher) EncryptedSize(size int64) int64 { +func (c *Cipher) EncryptedSize(size int64) int64 { blocks, residue := size/blockDataSize, size%blockDataSize encryptedSize := int64(fileHeaderSize) + blocks*(blockHeaderSize+blockDataSize) if residue != 0 { @@ -1044,7 +1021,7 @@ func (c *cipher) EncryptedSize(size int64) int64 { } // DecryptedSize calculates the size of the data when decrypted -func (c *cipher) DecryptedSize(size int64) (int64, error) { +func (c *Cipher) DecryptedSize(size int64) (int64, error) { size -= int64(fileHeaderSize) if size < 0 { return 0, ErrorEncryptedFileTooShort @@ -1063,7 +1040,6 @@ func (c *cipher) DecryptedSize(size int64) (int64, error) { // check interfaces var ( - _ Cipher = (*cipher)(nil) _ io.ReadCloser = (*decrypter)(nil) _ io.Seeker = (*decrypter)(nil) _ fs.RangeSeeker = (*decrypter)(nil) diff --git a/backend/crypt/crypt.go b/backend/crypt/crypt.go index a3bac32e9..00f68e262 100644 --- a/backend/crypt/crypt.go +++ b/backend/crypt/crypt.go @@ -90,7 +90,7 @@ names, or for debugging purposes.`, } // newCipherForConfig constructs a Cipher for the given config name -func newCipherForConfig(opt *Options) (Cipher, error) { +func newCipherForConfig(opt *Options) (*Cipher, error) { mode, err := NewNameEncryptionMode(opt.FilenameEncryption) if err != nil { return nil, err @@ -117,7 +117,7 @@ func newCipherForConfig(opt *Options) (Cipher, error) { } // NewCipher constructs a Cipher for the given config -func NewCipher(m configmap.Mapper) (Cipher, error) { +func NewCipher(m configmap.Mapper) (*Cipher, error) { // Parse config into Options struct opt := new(Options) err := configstruct.Set(m, opt) @@ -203,7 +203,7 @@ type Fs struct { root string opt Options features *fs.Features // optional features - cipher Cipher + cipher *Cipher } // Name of the remote (as passed into NewFs) @@ -572,7 +572,7 @@ func (f *Fs) ComputeHash(ctx context.Context, o *Object, src fs.Object, hashType if err != nil { return "", errors.Wrap(err, "failed to open object to read nonce") } - d, err := f.cipher.(*cipher).newDecrypter(in) + d, err := f.cipher.newDecrypter(in) if err != nil { _ = in.Close() return "", errors.Wrap(err, "failed to open object to read nonce") @@ -605,7 +605,7 @@ func (f *Fs) ComputeHash(ctx context.Context, o *Object, src fs.Object, hashType defer fs.CheckClose(in, &err) // Now encrypt the src with the nonce - out, err := f.cipher.(*cipher).newEncrypter(in, &nonce) + out, err := f.cipher.newEncrypter(in, &nonce) if err != nil { return "", errors.Wrap(err, "failed to make encrypter") } diff --git a/cmd/cryptdecode/cryptdecode.go b/cmd/cryptdecode/cryptdecode.go index 493f9edf6..7e7514a0c 100644 --- a/cmd/cryptdecode/cryptdecode.go +++ b/cmd/cryptdecode/cryptdecode.go @@ -60,7 +60,7 @@ use it like this } // cryptDecode returns the unencrypted file name -func cryptDecode(cipher crypt.Cipher, args []string) error { +func cryptDecode(cipher *crypt.Cipher, args []string) error { output := "" for _, encryptedFileName := range args { @@ -78,7 +78,7 @@ func cryptDecode(cipher crypt.Cipher, args []string) error { } // cryptEncode returns the encrypted file name -func cryptEncode(cipher crypt.Cipher, args []string) error { +func cryptEncode(cipher *crypt.Cipher, args []string) error { output := "" for _, fileName := range args { diff --git a/fs/operations/lsjson.go b/fs/operations/lsjson.go index f8a9e28bd..ffba3ff9d 100644 --- a/fs/operations/lsjson.go +++ b/fs/operations/lsjson.go @@ -81,7 +81,7 @@ type ListJSONOpt struct { // ListJSON lists fsrc using the options in opt calling callback for each item func ListJSON(ctx context.Context, fsrc fs.Fs, remote string, opt *ListJSONOpt, callback func(*ListJSONItem) error) error { - var cipher crypt.Cipher + var cipher *crypt.Cipher if opt.ShowEncrypted { fsInfo, _, _, config, err := fs.ConfigFs(fsrc.Name() + ":" + fsrc.Root()) if err != nil {