What is the most suitable way to encrypt and decrypt sensitive data on a public cloud server disk without storing the decryption key on the server in plaintext?


In our SaaS web/mobile app, following user login a user may upload PDF files containing sensitive customer data to a public cloud server physically hosted by a 3rd party provider (e.g. Amazon/Rackspace). I would like to protect the data on disk by encrypting it before writing it to disk, and unencrypting it when it's read from disk.

A common solution is to use Symmetric encryption e.g. AES and to store the decryption key on the server's filesystem. I want to avoid storing the plaintext decryption key alongside the data in order to protect access to the data on disk wherever it ends up within the 3rd party's infrastructure - e.g. potentially across multiple physical servers and disks (server disks, unencrypted on daily image backup disk arrays) etc.

Conditions: A user should be able to download PDFs which they previously uploaded. An Admin user should be able to view PDFs uploaded by any user.

I'm considering using a user's login password to protect the decryption key(s).


During each user registration an RSA Public/Private keypair would be generated by and stored on the server's disk. The Private key would be stored AES encrypted with user's password (actually the PBKDF2 derived key based on the user's password).


  • Plaintext PDF is uploaded to server (over SSL)
  • Server generates a random string (R) for AES encryption.
  • RSA encrypt R using the user's Public key. RSA encrypt R using the Admin user's Public key. # Allows admin user to decrypt anything AES encrypt PDF with R and
  • Store these three encrypted parts to the filesystem.


  • Decrypt user's Private key using their login password (via PBKDF2)
  • RSA Decrypt R using user's Private key.
  • AES Decrypt PDF using R and return it to the user

In this way if somebody has full access to the full filesystem data they cannot decrypt the PDF files unless they also know a password.

Q: Is this a secure solution? Do you see flaws in this? Are there suitable alternatives which I should consider?

  • 5
    I'd consider looking at Amazon Key Management Service or something similar before I rolled my own. Commented Dec 8, 2014 at 18:21
  • You should specify: Is it more acceptable for the pdf to be unrecoverable (lost key) or potentially exposed? What is the expected lifetime of a pdf (days, weeks, years)?
    – this.josh
    Commented Apr 14, 2017 at 5:18

3 Answers 3


You are certainly on the right track but it is possible that you're making it just a bit more complicated than you need to. You have correctly identified that a symmetric encryption system creates the significant issue of the decryption key being present on the system.

If you choose to generate public/private keys for each piece of data, you may be making your life unnecessarily difficult in addition to "handling" the private keys in a non-optimal location. If you are married to the data being encrypted with the user's public key, the following can be modified to store two copies of the encrypted symmetric key. In this case it would be best to allow the user to generate a keeper and provide you with the public key rather than generating the keypair for the user. (In other words, you really don't want to handle the private key)

  1. In a trusted location, generate a public/private keypair for the server/application
  2. Copy the public key (only) into the application path between the user and the database
  3. Whenever sensitive data arrives, generate a random secret key and use this key to encrypt the sensitive data using a symmetric algorithm (such as AES)
  4. Encrypt the random secret key with the application public key

There are a number of things that are ideal about this approach:

  • Backend systems and users with a business need and the proper rights can use the private key in a separate system to retrieve the sensitive data
  • Since only the private key can be used to decrypt the random secret keys there is no useful attack surface aside from raw brute force for an attacker who compromises the application
  • The effectiveness of a brute force attack is dramatically reduced since a successful attack against any of the random secret keys provides access only to that single piece of data; all of the other keys are different. This makes a brute force attack very unattractive against the symmetric keys.
  • Currently a brute force against a, say, 4096 bit public/private keypair is considered intractable

So, again, you've got the right idea, but you may want to simplify your approach just a bit!

  • RSA encrypting the symmetric key is indeed what I'm describing - I agree with you. I'd generate an RSA key per user + AES key per PDF. Assuming that is a sane approach, the issue is around private key protection. The problem is that the decrypted data needs to be displayed in the web/mobile app, i.e. offline decryption on a trusted server will not do. That's how I came to conclude that the private keys must be stored on the server but can be encrypted using the user's pass. Using e.g. PKCS#8 format they could be encrypted with AES-256. So this would be a safe solution then, would you agree?
    – taz
    Commented Dec 9, 2014 at 23:09
  • It sounds like you are in an unenviable situation. If you are generating and storing the keys locally on the server it's a risky proposition because all of the secrets are in one place. I'm assuming that you are not storing the password or are storing a multiple-round hash of the password? That will make it much more acceptable. :) Commented Dec 10, 2014 at 2:42

First off @taz good on you for thinking outside the box on keeping your customer's data more secure, however I've some concerns and possible suggestions of furthering securing data storage...

To your question of security of purposed system, I see the potential of a covert server compromise leading to your clients data becoming comprised the next time they login and I see the potential of the admin account being a single point of failure/compromise. While the proposed system would be more secure than what I've seen implemented by other server admins, I'll cover some other options ya may want to look into for inspiration on making security even tighter.

web/app enabled options

  1. Consider openpgpjs for client decryption within browser

  2. Consider openpgp- php for server side encryption

  3. Consider pulling source code from ProtonMail or KeyBase for how those teams have implemented encrypting/decrypting between server and client.

Alternative possible solution is sshfs + GnuPG encryption... it's a bit of setup for clients and server but it'll keep clients' & admins' private keys on their related file system and completely off the servers file system.

setup sshfs on cloud server to chroot clients

  1. Install sshfs to server

    apt-get install sshfs
  2. Make a new group for clients to be recognized by

    group add sshfsmount
  3. Add users to new group and users to server

    for _user in ${Var_users_list//,/ }; do
        ## Add user
        adduser ${_user}
        ## Lock user account from logins and append to chroot group
        passwd -l ${_user}
        usermod -s /bin/false  -a -G ${Var_chroot_group} ${_user}
        ## Make directory for user to be chrooted to with restricting permissions
        mkdir -p ${Var_chroot_group}/${_user}
        chown root:root ${Var_chroot_group}
        chown ${Var_chroot_group}:${_user} ${Var_chroot_group}/${_user}
        chmod 760 ${Var_chroot_group}/${_user}
  4. Modify server ssh configuration

    nano /etc/ssh/sshd_config
    ## snip, change subsystem settings
    Subsystem      sftp     internal-sftp
    ## snip, append the following to chroot the group
    Match Group sshfsmount
        ChrootDirectory /sshfsmount/%u
        ForceCommand internal-sftp
        AllowTcpForwarding no
        PermitTunnel no
        X11Forwarding no
  5. Check settings and reload server ssh configuration

    sshd -T
    if [ "$?" = "0" ]; then
        /etc/init.d/ssh reload

Note Subsystem sftp internal-sftp may cause ssh logins to fail so attempt to login via a normal ssh account after restarting the server before logging out of current ssh terminal that made the above changes.

  1. Add clients' public ssh keys to authorized

    for _user in ${Var_users_list//,/ }; do
        find "${Var_key_dir}" -xtype f | while read _key; do
            if grep -qE "${_user}" <<<"${_key}"; then
                mkdir -p /home/${_user}/.ssh
                cat "${_key}" >> /home/${_user}/.ssh/authorized_keys

Setup for bob client sshfs

  1. Install sshfs

    apt-get install sshfs
  2. Modify ssh client settings to make use of keys

    nano /etc/ssh/ssh_config
    ## append the following config block
    host cloud_server
        User bob
        HostName host.domain
        IdentityFile /some/dir/private_ssh_key
        IdentitiesOnly yes

Note host.domain should point to the cloud server's domain name or IP address

  1. Make directory and mount cloud server to clients local file system

    mkdir -p /mnt/glow_cloud
    sshfs cloud_server:/ /mnt/glow_cloud

Note to unmount use the following

    fusermount -u /mnt/glow_cloud
  1. Use GnuPG public key encryption for user bob to encrypt a file with output saved to cloud server

    cat some_local_file.txt | gpg -a -e -r bob@glow_cloud.domain -r admin@glow_cloud.domain -o /mnt/glow_cloud/enc_file.gpg

Note for text files the user bob may use a vim plugin/script to edit the above encrypted file on the remote server.

Note for non-text files you may wish to checkout the latest build of Paranoid_Pipes for further inspiration and utilize similar steps as above to make encrypting/decrypting between server and clients automatic. However, this last suggestion is experimental and results in clients keeping decryption key's passphrase in their local memory... so with above security mainly rests upon your clients' shoulders because the admin can use similar mounting schemes for keeping their own private keys off the server too.


There are some annoying realities about storing anything on a public cloud. The only safe way to decrypt/encrypt anything is on the local client itself, and all the issues of handling private keys locally - phone theft, key theft, etc. Using the public cloud means you have to trust that, on a multi tenant system, the other tenants are not able to scrape in memory, or the hosting provider doesn't siphon off a copy. If you have a really critical piece of data, no public cloud is the answer.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .