-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
encryption 2.0 - early stage #14376
encryption 2.0 - early stage #14376
Conversation
At the moment I work on the storage wrapper and encounter some problems. In some cases we need to bypass the wrapper, e.g if I want to read the raw file to extract some information from the header. In the current encryption app (which used proxies instead of the storage wrapper) we disabled the file proxies for these kind of operations which was not the most elegant solution but it works. I'm struggling with how I should to this with the storage wrapper. Is there also a way to by-pass the storage wrapper for some operations? @icewind1991 any idea? |
|
||
namespace OC\Files\Storage\Wrapper; | ||
|
||
class Encryption extends Wrapper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀 encryption as storage wrapper 🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let's hope everything will work out well and that we don't get stopped by stuff like I mentioned here #14376 (comment)
Can we please avoid black magic and special by-pass of components. It will definetly cause headaches and problems later. Please please please don't by-pass anything. Improve the storage or whatever ... and don't start again with kung fu ✨ black magic 🔮 . Sorry if this sounds harsh, I don't meant it so. I just want a encryption layer, that more than one person could understand, debug, fix and maintain. ;) 🚀 |
The wrapper itself can bypass it by calling the wrapper storage directly but the main way to "bypass" it is to not wrap any storage we want to access unencrypted in the first place. For example encryption keys can be put in a seperate storage (but still on the same physical location) and the encryption wrapper leaves that storage alone. |
* License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
namespace OC\Encryption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer not using the block style namespaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 to that, we use these no where else in OC or anywhere else in the community for that matter ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm quite sure that it is also used somewhere else in OC and I copy&pasted it. Anyway, I agree with you and will change it.
The problem is that we are talking about a storage which we want to access unencrypted in general but not in some special situations. We are talking about a normal file uploaded to ownCloud which is encrypted and for normal read operation it should of course get decrypted. But in some cases we want to read the header only, so in this case a fopen shouldn't strip the header away and start reading and decrypting the payload. |
Add a method to the storage wrapper to get that? |
Hm, I'm not sure. One example is here: https://github.com/owncloud/core/pull/14376/files#diff-a36b9c0307e0126dd50baa38fb4bb74aR169 To call the right encryption module to re-calculate the unencrypted size I need the encryption-module-id from the header. But as soon as I do a fopen to read the header of the file the stream wrapper will be executed again for fopen and perform all the steps the same way as I would like to read the unencrypted payload even if I want to read the raw file at this point in time. Don't see how a extra method could help. It will always need to start a read operation on a file covered by the wrapper so it will always call the wrapper and perform the necessary steps to read the payload unless I can tell him that I want the raw file in this case. Or do I miss something? |
Instead of passing just the path to |
*/ | ||
public function filesize($path) { | ||
$fullPath = $this->getFullPath($path); | ||
$fileInfo = \OC\Files\Filesystem::getFileInfo($fullPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please avoid calling call View
operations from a storage (wrapper), instead do something like
$info = $this->getCache()->get($path);
if($info['size'] > 0 and $info['encrypted']) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the pointer, will update the code
This only works if I'm in the wrapper and already perform a operation on the stream, e.g. if I call it from within a wrapped fopen call. But in this case I call it from a filesize() call so I don't have a stream I could pass on.
You mean that I could call fopen on $this->storage within the storage wrapper which then would bypass the encryption wrapper because $this->storage will no longer be wrapped? Sound like a good solution in this case. Although, if you look at the current code I fear that we might also have situations where we want to read the file from outside of the storage wrapper. In this case this trick will no longer work. For example if the encryption module want to recalculate the unencrypted size which at the moment rely on the possibility to read the raw file, but maybe @th3fallen will find a way to rewrite this method for the new encryption module. 😉 |
Just do |
If you need to access the encrypted file from outside the wrapper then there's probably something wrong with the design of the app, the encryption wrapper should be transparent. |
Let's see how far we come... Maybe we can re-factor this parts to make it no longer necessary. I just want to mention it early in the process that we, and especially @th3fallen who works on the "app-part", are aware of it. |
Refer to this link for build results (access rights to CI server needed): |
@th3fallen please follow @schiesbn 's approach an open your pr early as well - THX |
Refer to this link for build results (access rights to CI server needed): |
@DeepDiver1975 no problem, when i create the WIP pr for that app should i set it to merge into master or this branch? |
excellent question - general speaking everything should be a PR against master - but in this case you rely on the changes with this branch. @schiesbn would it make sense to push changes with respect to the encryption app into this branch? Or would you prefer this going into an branch of it's own? Both has pros and cons - your call - THX |
@schiesbn looks like you need to rebase 🙊 |
@DeepDiver1975 @th3fallen as discussed yesterday and as explained by @DeepDiver1975 everything has his pros and cons so I would keep it to @th3fallen to chose what works best for him. We can also work on the same branch we just have to be careful with rebase and force-push than. So maybe it is better to keep it separate for now. Also keep in mind that the PR we open today doesn't necessarily has to be the branch we merge at the end. We still have the possibility to open a new PR once everything is finished and ready for review if the development branch become to chaotic over time. |
so @schiesbn The decision is on my own branch? Just to be clear |
yes, maybe for now it is better to keep it separated so nobody has to fear to mess it up from each other. If we reach the point where we and other can test and review it we can still consider merging it to one PR to make it easier to test/review |
6e27cb4
to
85e530c
Compare
Refer to this link for build results (access rights to CI server needed): Build result: FAILURE[...truncated 14 lines...] > git config remote.origin.url https://github.com/owncloud/core.git # timeout=10 > git config --add remote.origin.fetch +refs/heads/:refs/remotes/origin/ # timeout=10 > git config remote.origin.url https://github.com/owncloud/core.git # timeout=10Fetching upstream changes from https://github.com/owncloud/core.gitusing GIT_SSH to set credentials using .gitcredentials to set credentials > git config --local credential.helper store --file=/tmp/git3501811308828787963.credentials # timeout=10 > git -c core.askpass=true fetch --tags --progress https://github.com/owncloud/core.git +refs/pull/:refs/remotes/origin/pr/ > git config --local --remove-section credential # timeout=10 > git rev-parse refs/remotes/origin/pr/14376/merge^{commit} # timeout=10 > git rev-parse refs/remotes/origin/origin/pr/14376/merge^{commit} # timeout=10Checking out Revision cc341328089c8aed7e6ad6a07a69336a30e36924 (refs/remotes/origin/pr/14376/merge) > git config core.sparsecheckout # timeout=10 > git checkout -f cc341328089c8aed7e6ad6a07a69336a30e36924 > git rev-list ee13828e3d2916a52bcae0d33b942feabcc125e8 # timeout=10First time build. Skipping changelog. > git remote # timeout=10 > git submodule init # timeout=10 > git submodule sync # timeout=10 > git config --get remote.origin.url # timeout=10 > git submodule update --init --recursiveTriggering pull-request-analyser-ng-simple » SLAVEpull-request-analyser-ng-simple » SLAVE completed with result FAILURESetting status of 85e530cbd41931f9b4677126fa8cd011fd376c7d to FAILURE with url https://ci.owncloud.org/job/pull-request-analyser-ng-simple/9944/ and message: Merged build finished.Test FAILed. |
Refer to this link for build results (access rights to CI server needed): Build result: FAILURE[...truncated 14 lines...] > git config remote.origin.url https://github.com/owncloud/core.git # timeout=10 > git config --add remote.origin.fetch +refs/heads/:refs/remotes/origin/ # timeout=10 > git config remote.origin.url https://github.com/owncloud/core.git # timeout=10Fetching upstream changes from https://github.com/owncloud/core.gitusing GIT_SSH to set credentials using .gitcredentials to set credentials > git config --local credential.helper store --file=/tmp/git9138639046596617379.credentials # timeout=10 > git -c core.askpass=true fetch --tags --progress https://github.com/owncloud/core.git +refs/pull/:refs/remotes/origin/pr/ > git config --local --remove-section credential # timeout=10 > git rev-parse refs/remotes/origin/pr/14376/merge^{commit} # timeout=10 > git rev-parse refs/remotes/origin/origin/pr/14376/merge^{commit} # timeout=10Checking out Revision 3d48f0c7e895693acae1066622d54502251b6705 (refs/remotes/origin/pr/14376/merge) > git config core.sparsecheckout # timeout=10 > git checkout -f 3d48f0c7e895693acae1066622d54502251b6705 > git rev-list cc341328089c8aed7e6ad6a07a69336a30e36924 # timeout=10First time build. Skipping changelog. > git remote # timeout=10 > git submodule init # timeout=10 > git submodule sync # timeout=10 > git config --get remote.origin.url # timeout=10 > git submodule update --init --recursiveTriggering pull-request-analyser-ng-simple » SLAVEpull-request-analyser-ng-simple » SLAVE completed with result FAILURESetting status of 278e08b9e0b09a690c96306d6d2436ebde68e3ad to FAILURE with url https://ci.owncloud.org/job/pull-request-analyser-ng-simple/9968/ and message: Merged build finished.Test FAILed. |
The inspection completed: 29 new issues, 60 updated code elements |
@@ -640,6 +640,7 @@ public static function init() { | |||
self::registerShareHooks(); | |||
self::registerLogRotate(); | |||
self::registerLocalAddressBook(); | |||
self::registerEncryptionWrapper(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really needed to hooked into the core that much? Shouldn't it be possible to hook this in from an app? cc @icewind1991
I don't really like to introduce again more complexity to the base.php and then it's again static code :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should work just fine when done from an app
I dont want to kill the mood but why arent we focusing on client side encryption? This would be:
The server would manage the public keys, so sharing will work by simply syncing the pubkeys in the client. For that we could create a small app that functions as a keyserver so you can also host your pubkeys for email on it. Encrypted folders would become readonly in the webinterface, so you cant accidentally upload confidential stuff. |
|
@icewind1991 yep, thats why we should move this to the sync client and just lock encrypted directories in the browser |
reading files has the same security issues |
Why? The file is encrypted and by default we could also encrypt the filename. |
Yes, we cant access the file from either the WI or WebDAV which is not something we want to do. |
You can access the file from webdav by using the path which was generated by the sync client. Webdav clients will see only encrypted files which is perfectly fine, things will still continue to work. Anyways, implementation details. You want to encrypt stuff because it is not safe on the server. Using serverside encryption does not help you in any way. Using it for external storage is a use case which affects maybe 1% of all the people that want to use encryption. For that use case this solution is overkill. If someone wants to use encrypted external storage, let the admin set a global password and pipe it through AES when writing it to the storage: simple implementation, less problems and bugs, no need to fiddle around with sharing, reencrypting, pubkeys, etc. As for the webinterface: not accessible, not a problem because you chose security. Theres always the possibility to write a small browser plugin (like megaupload handles it) that handles the decryption when downloading for you. |
It may also be a good idea to just push simple AES encryption support into the external storage app so it is clear where it is actually useful and start working on a design document about clientside encryption :) |
@Raydiation please put your ideas here in the relevant ticket #106. Best would be to have a design/concept and a list of tasks/steps/checkboxes breakdown so that interested people might be able to work on it. |
Looks like this guy is already on it #106 (comment) |
I temporily close this PR - any further work has to be done on #14472 |
@schiesbn @DeepDiver1975 Can this branch be deleted? |
This is a really early stage of encryption 2.0. I created the pull request to let people have a early look and to discuss some stuff but most of it will still change, so no need to review this yet.
The whole idea is to make encryption more modular and define the current encryption app into two parts:
A short explanation of what you can see at this pull request:
At the moment this is more or less a skeleton which will be filled with real code. Some will be copied from the current encryption app located in apps/files_encryption and some parts will be written from scratch.
I will focus on the part in core while @th3fallen will work on the first encryption module which will behave exactly like the current encryption app.
TODO: