Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Reverse Mode #19

Closed
usr42 opened this issue Mar 14, 2016 · 32 comments
Closed

Feature Request: Reverse Mode #19

usr42 opened this issue Mar 14, 2016 · 32 comments

Comments

@usr42
Copy link

usr42 commented Mar 14, 2016

Add an option similar to the --reverse option for encfs:

Normally EncFS provides a plaintext view of data on demand. Normally it stores enciphered data and displays plaintext data. With --reverse it takes as source plaintext data and produces enciphered data on-demand. This can be useful for creating remote encrypted backups, where you do not wish to keep the local files unencrypted.

For example, the following would create an encrypted view in /tmp/crypt-view.

encfs --reverse /home/me /tmp/crypt-view
You could then copy the /tmp/crypt-view directory in order to have a copy of the encrypted data. You must also keep a copy of the file /home/me/.encfs5 which contains the filesystem information. Together, the two can be used to reproduce the unencrypted data:
ENCFS5_CONFIG=/home/me/.encfs5 encfs /tmp/crypt-view /tmp/plain-view
Now /tmp/plain-view contains the same data as /home/me
Note that --reverse mode only works with limited configuration options, so many settings may be disabled when used.

(Quote from encfs man page)

@rfjakob
Copy link
Owner

rfjakob commented Mar 15, 2016

Reverse mode really is a nice feature. However, with reverse mode, there is no permanent store for the ciphertext (everything is encrypted on the fly and not stored). That means that gocryptfs could not store the file and block headers permanently.
encfs disables both in reverse mode, but this comes at a security cost, and is impossible for gocryptfs because GCM encryption absolutely needs a block header.
Now gocryptfs could just generate new block headers for every access (they are random anyway). But this would mean that you get different ciphertext every time you read a file (it still decrypts to the same plain-text, of course). This would make it pretty painful for backup purposes.

In short, I don't see a way to do this in a useful way for gocryptfs.

@rfjakob rfjakob closed this as completed Mar 15, 2016
@rfjakob
Copy link
Owner

rfjakob commented Jun 30, 2016

GCM-SIV ( https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-01 ) looks like a way this could be implemented. Reopening.

@rfjakob rfjakob reopened this Jun 30, 2016
@rfjakob rfjakob changed the title Add --reverse command-line option Feature: Reverse Mode Jun 30, 2016
@rfjakob rfjakob changed the title Feature: Reverse Mode Feature Request: Reverse Mode Jun 30, 2016
@fulldecent
Copy link

@rfjakob
Copy link
Owner

rfjakob commented Aug 24, 2016

@fulldecent Question: Do you need a writeable reverse mount or is read-only good enough?

@fulldecent
Copy link

I am happy with read only. My use case is secure backups with rsync.

If somebody needs read-write, maybe that can be a separate issue.

@bgw
Copy link

bgw commented Aug 25, 2016

Added another $20 to the bounty.

@rfjakob
Copy link
Owner

rfjakob commented Sep 4, 2016

Just FYI: I have started working on this in the "reverse" branch. I'll travel abroad for two weeks now but I expect to have things in a testable state by the end of September.

@fulldecent
Copy link

Very cool, thanks for the update

@rfjakob
Copy link
Owner

rfjakob commented Sep 25, 2016

This is essentially done. Fetch the latest "reverse" branch if you want to test it.

However, it uses the GCM-SIV Go reference implementation from github.com/agl/gcmsiv which is painfully slow at about 2 MB/s.

I am thinking about switching to AES-SIV, which has a reasonably fast Go implementation and the format is finalized (RFC 5297). Votes against?

@bgw
Copy link

bgw commented Sep 25, 2016

This is essentially done. Fetch the latest "reverse" branch if you want to test it.

Awesome! I'm skimming through the code. When trying to run go get in the branch, I'm getting:

package github.com/rfjakob/gocryptfs/internal/fusefrontend_reverse: cannot find package "github.com/rfjakob/gocryptfs/internal/fusefrontend_reverse" in any of:
        /usr/lib/go-1.6/src/github.com/rfjakob/gocryptfs/internal/fusefrontend_reverse (from $GOROOT)
        /home/bgw/.golang/src/github.com/rfjakob/gocryptfs/internal/fusefrontend_reverse (from $GOPATH)

However, I don't know if this is because I'm doing something wrong. I'm not a Go developer.

I am thinking about switching to AES-SIV, which has a reasonably fast Go implementation and the format is finalized (RFC 5297). Votes against?

The code looks better maintained too, so it seems like a good decision. However, I don't know enough about the pros/cons of these different cryptographic methods to intelligently comment.

@rfjakob
Copy link
Owner

rfjakob commented Sep 25, 2016

That error message does not make sense to me, but I just tried from an empty $GOPATH, this should work (note the second "go get ."):

go get github.com/rfjakob/gocryptfs
cd $GOPATH/src/github.com/rfjakob/gocryptfs
git checkout reverse
go get .  # Pull the remaining dependencies

@rfjakob
Copy link
Owner

rfjakob commented Sep 25, 2016

BTW, quickstart for how to use this:

gocryptfs -reverse -init DIR
gocryptfs -reverse DIR MNT

and if you want you can mount this again in forward mode and you'll get the plaintext files:

gocryptfs MNT MNT2

@bgw
Copy link

bgw commented Sep 25, 2016

@rfjakob, Thanks that works! The procedure I was trying was:

  1. Clone the repository (manually, using git)
  2. Check out the reverse branch
  3. Run go get inside that directory

Toying around with the cli, was able to encrypt and decrypt a file in a directory. Very cool!

One minor bit of feedback: When I first saw the cli output upon setup, it wasn't immediately clear to me that the master key was deterministic, though it seems that it is.

selection_056

@fulldecent
Copy link

@bgw Does this mean that if you delete the folder and recreate it you get the same master key?

@rfjakob
Copy link
Owner

rfjakob commented Sep 26, 2016

@rfjakob
Copy link
Owner

rfjakob commented Sep 26, 2016

I have switched to AES-SIV and have merged everything to master. Speed is at > 60MB/s on my CPU without AES-NI, so that should be pretty usable.

I have tagged it as "v1.1-beta1" because there may still be small changes to the IV derivation, so I'd wait for "v1.1" final before archiving data.

@bgw
Copy link

bgw commented Sep 27, 2016

No way: https://github.com/rfjakob/gocryptfs/blob/master/internal/configfile/config_file.go#L52

Whoops, I totally missed that the -reverse -init step creates a .gocryptfs.reverse.conf file. If I delete that file and reinitialize, the master key changes.

@rfjakob, If the master key is stored in this file, why do I need to enter the password every time I mount? (Ignore that, the master key is derived from the combination of this file and the password)

Does this mean that if you delete the folder and recreate it you get the same master key?

If you mount the same directory multiple times, the resulting encrypted mount is encrypted with the same master key every time. This should mean you can incrementally rsync that encrypted mount somewhere else.

@rfjakob
Copy link
Owner

rfjakob commented Sep 27, 2016 via email

@fulldecent
Copy link

Looks good, thanks for all the effort.

I am okay to mark this done for bounty purposes. Since some other people have money in, I'll wait for them to give the go ahead too.

@bgw
Copy link

bgw commented Oct 4, 2016

I'm fine with marking the bounty as done.

@fulldecent
Copy link

@rfjakob Thanks for your great work. Please fill in the form at https://www.bountysource.com/issues/31871717-feature-request-reverse-mode so we may award bounty.

rfjakob added a commit that referenced this issue Oct 8, 2016
@rfjakob
Copy link
Owner

rfjakob commented Oct 9, 2016

I'm quite happy with the reverse implementation now and I don't think there will be any more changes. The feature is released as v1.1-rc1 and I'm going to close the ticket.

Just a word to @fulldecent and @bgw: Having a bounty on a feature is not only great because you get the money. It shows you that people are genuinely interested in advancing the project, and the amount of the donation doesn't even have to be high for that. Having the bounty on this was very motivating, thank you guys for that, you are awesome!

@rfjakob rfjakob closed this as completed Oct 9, 2016
@fulldecent
Copy link

@rfjakob Thank you! This is my first time working with a bounty. Their website seems to be down right now, and I'm not sure how to close it out. I imagine you will need to mark it complete and then we confirm or something like that. Please let me know when you have marked it complete from their perspective so I can figure out my next step there.

@benrubson
Copy link

Do you need a writeable reverse mount or is read-only good enough?

@rfjakob, did you finally made the reverse mode read-only, or also writable ?
Thx 👍

@rfjakob
Copy link
Owner

rfjakob commented Apr 28, 2018

It's read only

@benrubson
Copy link

What would be needed to make it writable ?

@rfjakob
Copy link
Owner

rfjakob commented Apr 28, 2018

It's missing implementations for Create, Truncate, Unlink, Rmdir etc. Most work is probably the file Write function (forward mode for reference):

func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
).

@benrubson
Copy link

Just curious, do you plan it ?

@rfjakob
Copy link
Owner

rfjakob commented Feb 29, 2020

No as I don't have a use case for it

@Nodens-
Copy link

Nodens- commented Mar 10, 2020

@rfjakob Well there is a valid use case for it. 2-way syncing from multiple locations to remote untrusted locations, without double the disk space cost, using reverse mode.

And #108 (adding flag to disable all randomness in both forward and reverse for AES-SIV) would allow this use case easily and also alleviate the huge terror those of us with filesystems with hundreds of thousands of files in huge directory trees have, with possible corruption/loss of .diriv files at the remote untrusted location effectively destroying our backups. All birds with one stone.

@axet
Copy link

axet commented Jul 9, 2023

Read only --reverse option only good for local backups. But --reverwrite option would allow you not only to create local backups but also backups using cloud like (dropbox, google drive or yandex disk).

Here are few benefits having files unencrypted on your hard-drive. One of them is possibility to compress files by filesystem. Properly encrypted files does not support compression (obviously because of entropy == 1) and that is a limitation of default encryption mode of gocryptfs (or encfs for example). You can't compress encrypted folders!

If you have encrypted a lot of emails (maildir format) you can save up to 10 times of space for text files (emails or logs) if they compressed using filesystem. But you have to compress them before encryption (or using --reverse option)

The only problem with --reversewrite is not know what to do with conflict files. Conflict files which have been created by sync tool with broken names like "2xX3403-1fc (2)". In reversewrite mode you can't create corresponding unencypted file since encypted file name corrupted by conflict suffix "(2)". encfs prevents to create such files. But it may be not the optimal solution.

EDIT: I endup patching encfs properly handling conflicting files, and it works great!

@eugenesvk
Copy link
Contributor

Another use case of the writeable reverse mode: I've tried to use it to backup to Megasync, but Mega creates .megaignore files to track what to include/exclude within a folder, and with a read-only folder you can't create those files, so you can't start a backup of that folder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants