13

Is there a file system providing a directory where everybody can write, but only the directory owner can read the files? In theory it could be done by encrypting using the public key while writing, but I see that it's much more complicated than symmetric disk encryption. The purpose is to allow everybody to have their own directory where everybody else can put files into, i.e., a sort of secure messaging system, just at the file system level.

Nobody (not even root) but the owner should be allowed to read the files, so access rights don't help. Let's assume the system is secured against keyloggers, etc.

AviD
  • 72,138
  • 22
  • 136
  • 218
maaartinus
  • 684
  • 5
  • 12
  • 2
    I'm tempted to say PGP/GPG email. What operating system do you want this for? – Gilles 'SO- stop being evil' Aug 13 '11 at 12:28
  • You don't say why you need these security goals to be enforced by the *filesystem*. It can be done using filesystem features, but there are also other ways to do this at the application level. I assume those are fine too, but if not, you'll need to explain your requirements better. – D.W. Aug 14 '11 at 01:55
  • 10
    You say "not even root" should be able to spy on the messages. This is impossible to achieve. Root has god-like powers to spy on everything that happens on the system, every key that every user types, every byte of memory in every process, as well as to tamper with all programs (e.g., to embed a backdoor in them), etc. This is a fact of life you cannot avoid. You said "Let's assume the system is secured against keyloggers", but that is impossible: it is like saying "Let's assume that water isn't wet" or "Let's assume that pigs can fly". – D.W. Aug 14 '11 at 02:03
  • I see there's no good solution, at least nothing both secure and more usable than PGP email. This question rose from another discussion and I wasn't the very first poster, so I can't give all the details. Thanks to everybody answering. – maaartinus Aug 15 '11 at 16:42
  • 1
    The S3 filesystem supports this. Make an account. Only hand out write policies to those allowed to write. There is no concept of root. – Tom Andersen Nov 10 '11 at 13:57
  • Are you sure? I've never found a write-only or append-only mode in Amazon's S3. I even asked a question about that once : http://security.stackexchange.com/questions/9190/do-any-cloud-storage-system-offer-an-append-only-mode-for-buckets-directories – Jeff Burdges Dec 06 '11 at 21:43
  • I realize I'm a bit late to this conversation but I believe I've worked around most of the file system trust issues by using GnuPG public key cryptography, see answer below or [hak5 forum thread](https://forums.hak5.org/index.php?/topic/39421-gnupg-tools-for-unattended-encryption/) while not a file system itself when combined with `sshfs` it can provide limits to what remote root accounts can access. Also https://keybase.io might be of interest for less restrictions on encrypted file sharing. – S0AndS0 Nov 13 '16 at 17:10
  • There is also kbfs. It is a "cloud" filesystem that allows to put files in other users folders only they can read and much more. It's based on GPG and open source. https://keybase.io/docs/kbfs – Josef Jan 16 '17 at 10:48
  • @JeffBurdges there's always a root. If not explicitly via a root account, then at very least due to the fact that someone, somewhere has hardware access. With S3, you may not be able to have root access, but Amazon sure can. – user371366 May 14 '17 at 20:31

9 Answers9

18

Short concise answer

To the best of my knowledge, such a scheme is not available in a general purpose filesystem in a general purpose operating system using full block level RSA-only non-hybrid crypto. This is because operations like RSA in software are generally slower than their symmetric counterparts and require a lot of implementation extras, which are considered unnecessary when userland applications more than suffice for this purpose. The linux kernel and other kernels are concerned with supporting a wide range of general purpose applications in user space, so any non-necessary to your average general purpose user feature doesn't generally get included. However, this is not to say you cannot do it. People have implemented web servers in kernel space. You could do this if you wanted to.

Just to cover all my bases; obviously the kernel optionally supports a lot of hardware including some which may provide hardware assisted cryptography. In this case, your life is made considerably easier.

A hybrid scheme which PGP/TLS etc implement has a weakness in that the symmetric key is by nature read-write on the encrypted data. If you can intercept this, you can read the data. This is hard to do, no doubt, but possible. In a filesystem, your life is made easier because the read/write system calls will contain that unencrypted data in their buffer, which you can intercept, if you are root.

Long winded answer

I believe you're asking why on earth given that public key cryptography allows you to technically implement this form of access control (write in, no read out) why on earth it hasn't been done. Yes, I am trying to answer why you don't do block-by-block RSA. So, in two sections:

On why RSA hasn't been included in the kernel

You might be surprised to know there isn't an implementation of RSA in your linux kernel (or probably in the Windows kernel - I'd bet that it is in userspace).

Firstly, let's look at what is in the kernel: here's the crypto folder from Linus's main tree. Not an asymmetric algorithm in sight. Remember, we're still discussing filesystems here.

Next step, how do we implement RSA. At a register level, a x64 (as in, AMD64/EM64T compatible) processor can hold exactly 64 bits per register. This is why you have types like uint32_t and uint64_t in stdint.h and why integer overflow occurs.

If you're not quite following why this is at all relevant, well, an RSA key requires that you produce a modulus of a certain bit length; 2048 is recommended I believe although factoring 1024 is going to be hard enough (search Thomas Pornin's posts for a discussion on factoring both here and on crypto). So let's say 2048 bits. You might have noticed that in a single register, there's no way we can actually store that number. So we're a little stuffed for loading it into a register and manipulating it then, aren't we?

Ok so how then do we process integers of such a size as we require for RSA. Chain lots of 64-bit blocks together is basically the answer. x86 processors support operations such as adc which is short for add with carry. What happens when you add two registers who have the most significant bit set together and will therefore overflow is that the carry flag is set and the next adc you run will have an additional 1 added to the least significant bit.

This very fact allows us to start approaching arbitrary precision arithmetic. Now, all we need is 32 64-bit blocks of memory to store one side of our multiplication and the result and a further x lots of 64-bit for the other number. That gets us to actually generating our modulus.

Let's speed this theory up a bit or we'll be here all night. Addition is basically O(N) whichever way you look at it in a bignum library. Things like multiplication and exponentiation can be reduced to O(N) if one of the operators is only a single limb (64-bit chunk; limb is the bignum term for it); however, for two arbitrary numbers operations such as multiplication and division are always worse. Monumental effort has gone into speeding that up. The best summary that I know of of algorithms and their runtimes is available here: Modern Computer Arithmetic. However, I'd say it's actually highly theoretical, algorithm-listy and that Seminumerical Algorithms by Don Knuth contains a more accessible introduction.

Now, bignum operations are fast. Not just fast, like stupidly fast. Amazingly fast. Loop-unrolled hand optimised per platform assembly fast. GNU MP is widely regarded as the fastest general purpose bignum library on the planet and is used by Mathematica, Maple, Pari/GP and everyone else who does arbitrary precision arithmetic. It turns out neither GPG or OpenSSL use this in favour of their own bignum implementations, but that's their choice.

In contrast, AES, once you expand the SBox and the key expansion, is really two things: a hash table you never add to (the SBox)(and is therefore always O(1)) and a lookup table for the key expansion (also O(1)) and some xor-ing.

So, I think it's fair to say relative to AES, RSA is pretty slow, right? It's more computationally expensive per operation.

Edit I've just woken up with another reason in my mind as to why you don't do this. See this link for this:

Linux kernel code and data are not swappable and are never moved to swap.

So now you're forcing physical memory to always contain your bignum, RSA implementation and keys, leaving you less room for userland applications, forcing more swapping.

These are huge problems for the kernel. The kernel's job is to be as efficient as it can be. Very simple. This actually adds several other restrictions to kernel development, like having a fixed stack size and the fact that most of libc is considered excessive for kernel space. You also shouldn't use floating point operations in the kernel either. Let's be clear on what I'm saying: it is entirely technically possible to implement RSA in the kernel, but on a practical level, nobody does it because it is better off in userland, for which all these efficiency saving sacrifices are ultimately made.

RSA is also poorly suited to a block layer storage - before anyone starts, it is not obvious necessarily that this is a bad idea. Let's actually read the discussion I linked to last time. Directly quoting Thomas's answer there:

Nobody in their right frame of mind does such RSA-with-CBC encryption. Among the reasons are:

  • the construction has not received sufficient scrutiny to be deemed secure;
  • the size overhead implies that the encrypted message will be about 9.4% longer than the plaintext message;
  • RSA encryption is not very fast (a modern CPU would still succeed in encrypting, say, 2 MBytes worth of data per second that way).

This last reason is the most often quoted, but, in my opinion, the least compelling of the three.

I have dealt mainly with the last issue because that's the most obvious drawback, but assuming that's not a problem and you're happy with being relatively slow on a block level, then you've also got the fact that there's a large overhead per byte you want to store. Not a massively efficient use of your storage device.

I caveat all of this with if you want to do it, it is technically possible. There is nothing stopping you doing this at all. I'm only trying to actually explain why it hasn't been done.

So, that's RSA-per-block out of the way. As everyone else has got around to yelling, the alternative is to use RSA for the small amount of really valuable data - an AES or other symmetric key. This works. This is how TLS works. This is how PGP/GPG/OpenPGP and just about every other cryptographic protocol on the internet works. The idea is that you use slow RSA to encrypt the key, transmit it to the recipient (the only person who can decrypt it) and then you both have the symmetric key and can do high volume data transfer with a significantly reduced overhead, assuming correct usage of all the algorithms.

On why crypto and keys on the same OS is ok, but not perfectly safe

So, now let's talk about operating systems. Your computer is like a house with housemates in it and a live in landlord. The landlord is the kernel, the housemates are programs. Now, to achieve your system, Bob is you and wants to make sure this happens. So, he buys two safes and instructs Alice and Carroll to manufacture padlocks and also buy a safe each. He, meanwhile, invents a combination for one of his safes, sets it and puts the safe in the hallway. Now, to protect that combination, he writes it down and asks each of Alice, Carroll (and himself) to put a copy of that combination in their own safe and lock each of their own safe with their own padlock. So, to open the safe in the hallway, Alice must first open her own safe, to which only she has the key, then read the combination, lock her safe and go and open the safe in the hallway.

Eve is an evil housemate and is very angry nobody has told her what's in the safe. She can't enter anyone else's room, but she can persuade the landlord to do it, because he can go anywhere. She only needs to:

  1. Observe the making of one of those padlocks.
  2. Observe the code being written down for the safe in the hallway.
  3. Observe said code being used, or whatever is in the safe.

Simple as that. The best bit from my original answer was this:

The battle for your OS is theoretically lost as soon as someone can get to root, or Administrator, simple as that

Now, by contrast, a network service works like this. Bob wants to post a message to George. So, he gets George to send him a padlock in the post. George lives with a landlord they both trust totally. So Bob sets the combination for the safe in the hallway and writes it down, puts it in his safe, puts Goerge's padlock on it and gives both to the postman. He doesn't trust the postman one bit, but he's not going to invite the postman in any time soon, just up to the door. Unless something he does on the doorstep gives him away, or unless there's a problem with the safe or the padlock, or unless the postman can persuade him to reveal anything, his message should get to George safely.

That is what I was trying to get to. Even if you use GPG, or a userland-based filesystem such as FUSE (totally possible) you must still trust the system you're making those keys and doing that encryption on. Otherwise, the best you can hope for is fairly hard to intercept. You can use public key cryptography and symmetric cryptography together but they're not achieving what you think they are - even disk encryption as access control is worthless vs someone with physical access to your system; the only reason to use it is because it makes forensic analysis of your hard disk 6 months after you've chucked it away a lot harder.

Cryptography only works so long as the key and the data are separate. It's that simple. Which is why TLS across the internet works (because an attacker doesn't have the key) but crypto locally, where the key is going, at some point, to touch the system, doesn't. So, by all means implement an encrypted filesystem and protect the keys used to encrypt it with asymmetric keys. This is the most secure you can get with such a scheme, but:

  • Your requirement for write in all, read out one user will be enforced by the OS in terms of access control. There exists no current cryptography capable of doing this unless you do everything block-by-block RSA, which is slow and intensive relative to the hybrid implementation.
  • Nothing you can possibly do will ever be totally, 100% immune to root/Administrator/the guy who walks by your desk every day.
  • Although this answer is from 2011, I'd like to point out that there _is_ an implementation of RSA in the Linux kernel now, in the form of a kernelspace X.509 parser. A lot of crypto is done in the Linux kernel nowadays... – forest Apr 06 '19 at 09:02
6

A write-only file system is doable, even cryptographically, but it has little extra functionality over what you can already do with, say, GnuPG.

It would take some effort at defining precisely what you want. There are many behavioral options:

  • Should it be possible for anybody to see the files metadata (name, length, date of last modification...) ?
  • If files can be deposited, who can erase and/or replace them ? Anybody, only the directory owner, or both the owner and the file sender ?
  • Should it be possible to append data to an encrypted file ?
  • What about subdirectories ?

Having the system as a kernel-powered filesystem makes sense only if you want to be able to write the files through the normal API for files (open(), write()...), which in turn constraints the answers to the questions above. Supporting the "normal API" is for the benefit of applications which are unaware of your specific auto-encrypting filesystem. On the other hand, if you accept that users who wish to deposit a file in such a directory may have to invoke a specific command, then there is little reason to implement the feature in the kernel. A purely userspace solution would work equally well, and probably better since userland programming has less constraints than kernel programming. An existing userland solution already exists, and is called "e-mail", with GnuPG.

Also, if root is your enemy then you are doomed. Root is almighty on a Unix system; he can change the kernel as he sees fit, and thus activate a key logger, or just obtain a copy of every byte which is written to a file. On the other hand, if root is not an enemy, then normal non-crypto security features (e.g. file access rights) of the system ought to be enough to enforce data confidentiality; see the other responses for that.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • The metadata are unimportant, there's no secret there. Deletions & al. should be handled by permission. Append and subdirectories are not required. I could imagine using a dedicated computer for this where the root can login only under control, no idea how it could exactly be achieved. The encryption (unlike access rights) would protect the data even in case of theft. However, I see that my question as given has no practical solution. – maaartinus Aug 15 '11 at 16:31
4

By definition, the root user will be able to circumvent and local encryption while its running[1]. So you're targeting an adversary with full control over the machine that wants to decrypt all the data 2 hours or 2 weeks after it was stored. And users should have write-only access.

I suggest to use access control and a cronjob with periodic file-based encryption. Symmetric encryption with a random key and key-encryption with asymmetric key. Simple GPG-encryption should automatically use this hybrid approach for you. You should use different partitions/folders to separate the files you encrypted from those in the staging area.

File-based encryption may not be as secure as block-layer encryption due to leakage of filename and metadata. But it also rescues you from the problem that users might overwrite their own or other peoples files. From your scenario I suppose you wouldn't like that to happen.

[1] I know that root is not root, but obviously the poster does not want to rely on access control here.

pepe
  • 3,536
  • 14
  • 14
  • 1
    Quote from question: "Nobody (not even root) but the owner should be allowed to read the files [...]" – pepe Aug 14 '11 at 07:57
  • you are right and I was wrong. My apologies. I was confused. I've deleted my erroneous comment. If you want to edit your answer I will upvote it. – D.W. Aug 14 '11 at 17:16
  • 1
    If the encryption is done by the writer, even the root user couldn't circumvent the encryption. He wouldn't have the reader's private key and he would only receive encrypted data from the writer. – David Schwartz Aug 16 '11 at 04:30
4

With cryptography. If you don't want to rely upon filesystem permissions, you can solve this problem straightforwardedly with public-key encryption.

Details. Here's how. Radia, the recipient of all these messages, can use GPG to create a public-key keypair. Radia should then communicate her public key to everyone: for instance, she might store the public key in some read-only file that everyone can read. Radia should store her private key safely in a file that only she can read.

To send a message, Alice can import Radia's public key into her GPG keyfile, then encrypt her message to Radia's public key using GPG, and send the encrypted file to Radia. It doesn't really matter how the encrypted file gets to Radia; it could be transmitted by cleartext email, stored in a world-writeable directory, or any other insecure medium.

To receive the message, Radia can use GPG to decrypt it (using Radia's private key).

Only Radia will be able to decrypt the message. Bob doesn't know Radia's public key, so even if Bob intercepts the encrypted file, Bob can't read the message that Alice was trying to send.

Discussion. This is all a totally straightforward application of public-key cryptography. Rather than implementing public-key crypto yourself, I recommend that you use some existing, time-tested, heavily-vetted file encryption software. GPG comes highly recommended for this purpose. You could also use PGP's commercial product, if you prefer to pay money for it. S/MIME-encrypted email would also be a perfectly reasonable implementation. This solution doesn't require any special support from the filesystem; instead, the security is implemented at the application layer.

Caveat. Root will be able to read all files and read all messages. You said you don't want this. However, what you want is unachievable. On any existing operating system, if root is malicious, root can spy on everything that every user does. (You said "Let's assume the system is secure against keyloggers", but there is no way to do that, if root is the one trying to do keylogging.) Therefore, this achieves your goals to the extent that they are achievable.

D.W.
  • 98,420
  • 30
  • 267
  • 572
3

Without cryptography. You can do this on a Unix filesystem, simply by using standard Unix file permissions, with no need for any cryptography of any kind.

Details. Here's how. First, the recipient (let's call her Radia) should set things up like this:

radia $ mkdir /securefolder
radia $ chmod a+w,og-r,a+x,o+t /securefolder
radia $ ls -ld /securefolder
drwx-wx-wt. 2 radia radia 4096 Aug 13 18:34 /securefolder

Now Alice can write a file there, that only Radia (and herself) can read:

alice $ umask 077
alice $ echo 'hello, Radia!' > /securefolder/hi_there

At this point Radia will be able to read the file Alice created:

radia $ ls -l /securefolder
total 4
-rw-------. 1 alice alice 13 Aug 13 18:38 hi_there
# cat /securefolder/hi_there 
hello, Radia!

But Bob cannot read the file that Alice created, or delete her file, or even list all files within that directory:

bob $ cat /securefolder/hi_there
cat: /securefolder/hi_there: Permission denied
bob $ rm /securefolder/hi_there
rm: cannot remove `/securefolder/hi_there': Operation not permitted
bob $ ls -l /securefolder
ls: cannot open directory /securefolder: Permission denied

(Trivia: given a guess at a filename, Bob can test whether a file by that name exists, but he cannot learn its contents. This is likely to be harmless in practice, as long as you avoid encoding any sensitive information in the filenames.)

Caveat. Root will be able to read all files and read all messages. You said you don't want this. However, what you want is unachievable. On any existing operating system, if root is malicious, root can spy on everything that every user does. (You said "Let's assume the system is secure against keyloggers", but there is no way to do that, if root is the one trying to do keylogging.) Therefore, this achieves your goals to the extent that they are achievable.

D.W.
  • 98,420
  • 30
  • 267
  • 572
2

Someone implemented just the thing (which is kind-of opposite to what I need...)

http://www.arthy.org/wocfs/

WOCFS is a write only crypto-locked FUSE based filesystem. You can write into the FUSE mount, but the files so written there can't be read from without a separate tool. Someone with sufficient privileges can delete or move the files, but without the tool, they can't read/edit them.

It's usable, but it's not going to be a barn-burner for speed since it's using RSA public key encryption to encode with. Might be able to get it re-worked to use libsodium and speed it up dramatically.

0

This is similar another question: https://serverfault.com/questions/89126

Where a sysadmin wanted one way encryption of specific server logs. As stated there, read that project warnings, but unlike stated there, here's a quick start for your usage scenario described.

  • Login to user account that will be encrypting files.

  • Import public key of your file "owner" and use their associated email in the next command for the Var_gpg_id variable.

Set some custom variables for readability of this how-to

Var_gpg_id='email@host.domain'
Var_script_ower="${USER}"
Var_script_group="${USER}"
Var_gpg_file_ower="${USER}"
Var_gpg_file_group="${USER}"
Var_output_file="${HOME}/.secrets/gpg_messages.gpg"
Var_output_dir="${HOME}/.secrets/gpg_messages.gpg"
Var_named_pipe_location="${HOME}/Share/encryption_wormhole.pipe"
Var_script_copy_location="${HOME}/.secrets/wormhole_${USER}_pipe_listener.sh"

Clone script and print help

git clone https://github.com/S0AndS0/Perinoid_Pipes
cd Perinoid_Pipes
Perinoid_Pipes.sh -h

Run script with --help to check settings

Perinoid_Pipes --copy-save-yn='yes'\
 --copy-save-name="${Var_script_copy_location}"\
 --copy-save-ownership="${Var_script_ower}:${Var_script_group}"\
 --copy-save-permissions='100'\
 --debug-level='6'\
 --listener-quit-string='sOmErAnDoM_sTrInG_wItHoUt_SpAcEs_tHaT_iS_nOt_NoRmAlY_rEaD'\
 --log-level='0'\
 --named-pipe-name="${Var_named_pipe_location}"\
 --named-pipe-ownership="${Var_gpg_file_ower}:${Var_gpg_file_group}"'\
 --named-pipe-permissions='420'\
 --output-bulk-dir="${Var_output_file}"\
 --output-parse-name="${Var_output_file}"\
 --output-parse-recipient="${Var_gpg_id}"\
 --output-rotate-actions='compress-encrypt,remove-old'\
 --output-rotate-check-requency='2500000'\
 --output-rotate-max-bites='8388608'\
 --output-rotate-recipient="${Var_gpg_id}"\
 --output-rotate-yn='no'\
 --output-save-yn='yes'\
 --disown-yn='yes' --help

Adjust the above to suit needs for the user, remove --help when ready to write script copy, and then add something similar to bellow to their .bashrc file.

cat >> ${HOME}/.bashrc <<EOF
if [ -e "${Var_script_copy_location}" ]; then
    if ! [ -p "${Var_named_pipe_location}" ]; then
        echo "# Starting ${Var_script_copy_location}"
        ${Var_script_copy_location} || echo "## Failed!"
    else
        echo "# Detected [${Var_script_copy_location}] already running"
        echo "# ${USER} may write to [${Var_named_pipe_location}] for auto encryption."
    if
else
        echo "## Could not start ${Var_script_copy_location}"
fi
EOF

The end result is that when logging in under this user the bash start up file will be read and thus the status of the named pipe file will be checked, if it doesn't exist then the script copy will be run to remake it. When known file or directory paths are written to the named pipe (echo "${HOME}/Downloads" > ${Var_named_pipe_location}) the script copy should deposit compressed & encrypted results into the directory specified by ${Var_output_dir} variable. And messages or random data written to the named pipe will be appended to the file specified by ${Var_output_file} variable.

Note to allow anyone to write to the named pipe you may want to set the --named-pipe-permissions='420'\ option to 422 but try it with the more restrictive permissions first shown because allowing anyone to pull system entropy like this can be dangerous.

S0AndS0
  • 377
  • 1
  • 3
  • 12
0

The only way to avoid root being able to read the contents of the files if they really wanted to would be to encrypt them locally on your own system, upload the encrypted versions to the system you have envisioned and let anyone who has to read them download them and decrypt them locally. That way no keys are ever present on the system to which this third party root has access so the problem of reading the files becomes one of cracking whichever encryption algorithm you choose. Assuming the algorithm is secure and that the keys are long/complex enough this means being a brute force attack which would take too long to be feasible.

Mr. C
  • 131
  • 1
0

I don't think there are such file systems. The only one I know of is Microsoft EFS (implemented in NTFS), it uses asymmetrical crypto, so you may be able to configure it the way you want, I never tried such configuration so YMMV.

Easiest and most compatible way would be to go with e-mail, either OpenPGP or S/MIME. Most e-mail clients encrypt the sent message using the receivers public key and the local copy using the senders key, this way both of them have a copy only they can read (as long as their private keys are secret, of course).

Hubert Kario
  • 3,708
  • 3
  • 27
  • 34
  • 1st paragraph: Yes, such filesystems exist; see my answer. 2nd paragraph: I agree. This is good advice. – D.W. Aug 14 '11 at 01:45