diff --git a/cryptfs/cryptfs_names.go b/cryptfs/cryptfs_names.go index 2a5f158..8f8486b 100644 --- a/cryptfs/cryptfs_names.go +++ b/cryptfs/cryptfs_names.go @@ -17,7 +17,7 @@ const ( ) // DecryptName - decrypt base64-encoded encrypted filename "cipherName" -func (be *CryptFS) decryptName(cipherName string, iv []byte) (string, error) { +func (be *CryptFS) DecryptName(cipherName string, iv []byte) (string, error) { // Make sure relative symlinks still work after encryption // by passing these through unchanged @@ -91,7 +91,7 @@ func (be *CryptFS) TranslatePathZeroIV(path string, op int) (string, error) { if op == OpEncrypt { newPart = be.encryptName(part, zeroIV) } else { - newPart, err = be.decryptName(part, zeroIV) + newPart, err = be.DecryptName(part, zeroIV) if err != nil { return "", err } diff --git a/cryptfs/names_diriv.go b/cryptfs/names_diriv.go index be7a2b1..ae8545b 100644 --- a/cryptfs/names_diriv.go +++ b/cryptfs/names_diriv.go @@ -7,8 +7,8 @@ import ( "strings" ) -// readDirIV - read the "gocryptfs.diriv" file from "dir" (absolute path) -func (be *CryptFS) readDirIV(dir string) (iv []byte, err error) { +// readDirIV - read the "gocryptfs.diriv" file from "dir" (absolute ciphertext path) +func (be *CryptFS) ReadDirIV(dir string) (iv []byte, err error) { ivfile := filepath.Join(dir, DIRIV_FILENAME) Debug.Printf("readDirIV: reading %s\n", ivfile) iv, err = ioutil.ReadFile(ivfile) @@ -22,7 +22,7 @@ func (be *CryptFS) readDirIV(dir string) (iv []byte, err error) { return iv, nil } -// WriteDirIV - create diriv file inside "dir" (absolute path) +// WriteDirIV - create diriv file inside "dir" (absolute ciphertext path) // This function is exported because it is used from pathfs_frontend, main, // and also the automated tests. func WriteDirIV(dir string) error { @@ -45,7 +45,7 @@ func (be *CryptFS) EncryptPathDirIV(plainPath string, rootDir string) (string, e var encryptedNames []string plainNames := strings.Split(plainPath, "/") for _, plainName := range plainNames { - iv, err := be.readDirIV(wd) + iv, err := be.ReadDirIV(wd) if err != nil { return "", err } @@ -66,11 +66,11 @@ func (be *CryptFS) DecryptPathDirIV(encryptedPath string, rootDir string) (strin encryptedNames := strings.Split(encryptedPath, "/") Debug.Printf("DecryptPathDirIV: decrypting %v\n", encryptedNames) for _, encryptedName := range encryptedNames { - iv, err := be.readDirIV(wd) + iv, err := be.ReadDirIV(wd) if err != nil { return "", err } - plainName, err := be.decryptName(encryptedName, iv) + plainName, err := be.DecryptName(encryptedName, iv) if err != nil { return "", err } diff --git a/pathfs_frontend/fs.go b/pathfs_frontend/fs.go index e68e6bc..fe9a8b0 100644 --- a/pathfs_frontend/fs.go +++ b/pathfs_frontend/fs.go @@ -75,36 +75,42 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f if err != nil { return nil, fuse.ToStatus(err) } + // Read ciphertext directory cipherEntries, status := fs.FileSystem.OpenDir(cDirName, context) - var plain []fuse.DirEntry - if cipherEntries != nil { - for i := range cipherEntries { - cName := cipherEntries[i].Name - if dirName == "" && cName == cryptfs.ConfDefaultName { - // silently ignore "gocryptfs.conf" in the top level dir - continue - } - if fs.args.DirIV && cName == cryptfs.DIRIV_FILENAME { - // silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled - continue - } - var name string - if !fs.args.DirIV { - name, err = fs.decryptPath(cName) - } else { - // When dirIV is enabled we need the full path to be able to decrypt it - cPath := filepath.Join(cDirName, cName) - name, err = fs.decryptPath(cPath) - name = filepath.Base(name) - } - if err != nil { - cryptfs.Warn.Printf("Invalid name \"%s\" in dir \"%s\": %s\n", cName, dirName, err) - continue - } - cipherEntries[i].Name = name - plain = append(plain, cipherEntries[i]) + if cipherEntries == nil { + return nil, status + } + // Get DirIV (stays zero if DirIV if off) + cachedIV := make([]byte, cryptfs.DIRIV_LEN) + if fs.args.DirIV { + // Read the DirIV once and use it for all later name decryptions + cDirAbsPath := filepath.Join(fs.args.Cipherdir, cDirName) + cachedIV, err = fs.CryptFS.ReadDirIV(cDirAbsPath) + if err != nil { + return nil, fuse.ToStatus(err) } } + // Decrypt filenames + var plain []fuse.DirEntry + for i := range cipherEntries { + cName := cipherEntries[i].Name + if dirName == "" && cName == cryptfs.ConfDefaultName { + // silently ignore "gocryptfs.conf" in the top level dir + continue + } + if fs.args.DirIV && cName == cryptfs.DIRIV_FILENAME { + // silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled + continue + } + var name string + name, err = fs.CryptFS.DecryptName(cName, cachedIV) + if err != nil { + cryptfs.Warn.Printf("Invalid name \"%s\" in dir \"%s\": %s\n", cName, dirName, err) + continue + } + cipherEntries[i].Name = name + plain = append(plain, cipherEntries[i]) + } return plain, status } diff --git a/performance.txt b/performance.txt new file mode 100644 index 0000000..55678c3 --- /dev/null +++ b/performance.txt @@ -0,0 +1,10 @@ +All test performed on tmpfs, /tmp/a mounted on /tmp/b. + +UNTAR: tar xfz ../linux-3.0.tar.gz +LS: ls -lR > /dev/null +RM: rm -rf linux-3.0 + +VERSION UNTAR LS RM +v0.4 48 1.5 5 +v0.5-rc1 56 7 19 +v0.5-rc1-1 54 4.1 9