6

My Delphi 2010 application (currently in development) encrypt users' files and upload them to EC2 and then to S3. Users can download their files using a secure website (kinda like dropbox but in a different context, market, use, etc...)

I use RSA Encryption. I give my users the ability to choose whether they want to use their own private keys (generated locally) or use the shared key (located on the cloud)

When working on file download, I ended up with 4 possibilities that I must handle properly:

  1. If a user uses his/her own private encryption key:

    a. Downloading from Delphi / Client: file is decrypted on user's machine after download

    b. Downloading from website / PHP: impossible (directly), unless I give the user the possibility to download a small utility that allows him/her to locally supply his/her private key and decrypt the file after download.

Pros/Cons: Secure, but not straightforward / too restrictive, and impossible to do on mobiles(?)

  1. User choose to use my shared private encryption key (located on the cloud)

    a. Downloading from Delphi / Client: file is first decrypted via PHP on EC2 (then served to the user), in which case the download process could become very slow if many users are downloading files (unlikely) or if the files being decrypted are too large.

    b. Downloading from website / PHP: same as (a)

Pros/Cons: Straightforward/ just works, but may results in a huge CPU usage, unacceptable delay when downloading (esp. if the file size in question is huge).

My two-part question is:

1) Is there a better strategy to handle such scenario? and

2) What would you do (in term of encryption strategy / handling downloads) if you wanted to offer your users the ability to choose between private and shared encryption keys?

PS. I'm using Delphi 2010 (client) with PHP 5.3 running on the EC2 instance is running the latest standard Amazon Linux 2012 build

EDIT Traffic is always encrypted, so HTTPS only!

EDIT 2 I'm using GPG for encryption / decryption

TheDude
  • 3,045
  • 4
  • 46
  • 95
  • 2
    If you're storing private keys in the cloud, doesn't that somewhat defeats the purpose of encrypting files also stored in the cloud? – Tech163 Sep 02 '12 at 13:44
  • Why don't you just upload the files directly to S3? – John Wheal Sep 02 '12 at 13:46
  • @Tech163: only the **shared** private key is stored on the cloud. If a user wants to use its own key, then it's generated and kept on his/her machine – TheDude Sep 02 '12 at 13:48
  • you can also go for apps that do the download/upload/decryption/encryption process, if you're storing the file encrypted and then serve it via HTTPS unencrypted, you've already wasted a ton of CPU for nothing, session stealing is not that difficult... also, consider dropping PHP in favor of an apache module built with freepascal. just my 2 cents. –  Sep 02 '12 at 13:51
  • From what I understand, users can choose between using their own private key or using your shared key. I don't think using a shared key (that is stored on the cloud) to encrypt the file would provide any additional security for those who choose to go with the shared key. – Tech163 Sep 02 '12 at 13:51
  • If you can use the html5 filewriter api you could do the decryption in the browser. – Frederick Cheung Sep 02 '12 at 13:51
  • @JohnWheal: I need to encrypt the file on EC2 before it's sent to S3. I can't do that if a user opt to use the cloud private key. – TheDude Sep 02 '12 at 13:52
  • @FrederickCheung: Interesting, is there a fallback solution for old browsers? – TheDude Sep 02 '12 at 13:55
  • @DorinDuminica: Only HTTPS is used, sorry for not mentioning this in my post! – TheDude Sep 02 '12 at 13:56
  • What about S3's built in server side encryption instead? – Tech163 Sep 02 '12 at 13:59
  • @Tech163: I believe it does (I mean in case someone get into our amazon account) – TheDude Sep 02 '12 at 14:00
  • 1
    If someone gets into your amazon account, they will also have access to your shared private key – Tech163 Sep 02 '12 at 14:00
  • @Gdhami I would have been very surprised if HTTPS was not used, however, HTTPS is useful to hide information from script "kiddies", please look at http://en.wikipedia.org/wiki/Session_hijacking and http://phpsec.org/projects/guide/4.html –  Sep 02 '12 at 14:01
  • @Tech163: You're right, having the files encrypted on S3 is more of a "psychological reason" rather than better security practice. – TheDude Sep 02 '12 at 14:02
  • @Tech163: S3 encryption is **really** interesting, but I also **really** wanna stay away from it, I don't want to put all my eggs in one basket (plus it doesn't really help for these who opt to use their own private keys) – TheDude Sep 02 '12 at 14:04
  • @DorinDuminica: Thanks for the links! I'm using HTTPS **everywhere** so I should be safe regarding this particular point. – TheDude Sep 02 '12 at 14:06
  • What do you mean by "I use RSA Encryption". RSA encryption should only be used for key exchange, and not for encrypting the actual data. RSA can't even work on more than 100ish bytes at a time, and constructing your own ECB like mode to work around that is an extremely bad idea. – CodesInChaos Sep 02 '12 at 14:13
  • @CodesInChaos: My mistake, I use GPG for encryption – TheDude Sep 02 '12 at 14:17

1 Answers1

2

If you're forced to offer server side encryption/decryption, use system()/exec() with openssl or something. I would hate to see PHP used to encryptd/encrypt anything large, simply because it's not really designed to do so. In that case, it would be important to delete unencrypted version of files after some time.

As with what you're trying to do, it's really difficult to have something secure on the server side. If you're encrypting/decrypting small stuff, you can probably do it in javascript in your browser - perhaps see https://www.google.com/search?q=javascript+aes&sugexp=chrome,mod=16&sourceid=chrome&ie=UTF-8

What I would do:

1) Upload to EC2. Generate a random password, encrypt that with your public key, and store that. You don't want to use asymmetrical encryption for large stuff. Encrypt with openssl via command line with the previously generated random password. Upload to S3 the encrypted file. Delete (perhaps shred) the unencrypted file.

2) For downloading, fetch from S3. Have your user upload private key. Use private key to decrypt encrypted version of the previous random password. Now use that password to decrypt the file using openssl. Make the name a hash of something random so it can pass right through nginx/apache without PHP. Have cron clean that up every x minutes.

Tech163
  • 4,176
  • 8
  • 33
  • 36
  • Yes, I'm using exec() from PHP decrypt files, ie. `exec('gpg -o ' . $encr_file_name . ' --decrypt ' . $decrypted_file_name);` BTW, I'm using GPG! – TheDude Sep 02 '12 at 14:11
  • Is there any particular reason you must use GPG? On another note, I think it would be the same concept for openssl and GPG – Tech163 Sep 02 '12 at 14:13
  • I always encrypt files *before* upload (when using client app, that is). Is there a reason *not* to use GPG? – TheDude Sep 02 '12 at 14:15
  • 1
    GPG would work nicely too I imagine. I'm just saying that you shouldn't encrypt directly with public key, but rather use public key to store an encrypted version of a random password, and use the private key to decrypt that encrypted version of a random password - see http://stackoverflow.com/questions/3491481/encrypting-large-files-using-a-public-key. It's for better performance. – Tech163 Sep 02 '12 at 14:19
  • 1
    @Gdhami I'd go with something less mainstream, like blowfish –  Sep 02 '12 at 14:20
  • I've done something similar with OpenSSL (see http://stackoverflow.com/questions/10442217/openssl-encryption-zero-length-password-error) and I know the concept works well. Blowfish, AES, etc, take your pick. – Tech163 Sep 02 '12 at 14:22
  • 1
    @DorinDuminica Why would you want to use *blowfish*? If you *really* want a non standard cipher, at least use something more modern, such as an AES candidate, or Salsa20. – CodesInChaos Sep 02 '12 at 14:22
  • Tech163: The problem with such approach is that any hacker can inspect / spy on the client / delphi application and get the password *before* it's encrypted, that's why I actually switched to GPG in the first place. Otherwise it would be brilliant indeed! – TheDude Sep 02 '12 at 14:24
  • 1
    Get the password before it's encrypted? How? Get from memory? It's a randomly generated password that will be different each time, different for each file. – Tech163 Sep 02 '12 at 14:24
  • I think if they have access to your computer's memory and is able to get the password there, they probably also have access to the unencrypted file. – Tech163 Sep 02 '12 at 14:27
  • The user-specific private key yes, but not if the user uses the cloud/shared private key...anyway, this sounds *really* stupid but I've *never* considered combining both approaches (dynamic password + GPG encryption) as you suggested, this sounds like a way better method, I'm going to try it and see how things go! – TheDude Sep 02 '12 at 14:29
  • 1
    @CodesInChaos because http://en.wikipedia.org/wiki/Blowfish_(cipher)#Cryptanalysis_of_Blowfish and because I like to use something less widespread in usage –  Sep 02 '12 at 14:33
  • 2
    @DorinDuminica I still see no advantage of blowfish over a modern stream cipher, and at least one clear disadvantage: 64 bit blocks. Even its author recommends using newer ciphers. If you want to avoid AES, you can go with any of the other AES finalists, such as blowfish's successor TwoFish. – CodesInChaos Sep 02 '12 at 15:20