16

I'm writing a client app in Java that sends encrypted data back to the server. All clients have my RSA public key. Is there a standard way to encrypt a given file with it to send it back to the server?

From websites such as this one, I gather that usually, a symmetric key is generated to encrypt the actual file, and this key is then encrypted with the RSA public key and sent along the file. Is there a standard way in Java or a standard file format (without additional libs) to package the encrypted symmetric key and the symmetrically encrypted file?

Of course, I could design my own file format, but I'd rather stick to standards if possible.

AviD
  • 73,317
  • 24
  • 140
  • 221
  • 1
    BouncyCastle maybe? Its the only library I know of that does encryption – TheLQ Jan 04 '11 at 15:11
  • 1
    How would I do it with BouncyCastle? – Jean-Philippe Pellet Jan 04 '11 at 15:51
  • 3
    What is your underlying goal and threat model? E.g. do you also want to authenticate where the data came from, or are you vulnerable to a MITM attack? Have you considered SSL and then encrypting the file on the server side if desired? – nealmcb Jan 04 '11 at 15:53
  • 1
    +1 to @nealmcb, it shouldn't be assumed that file encryption is necessarily the way to go. – AviD Jan 04 '11 at 18:58
  • The client app saves user activity logs whose content should be published to a server unaltered, even if the user has read/write access to the saved files. Moreover, the user should not be able to inspect the contents (the files are exercise, progress, and error reports from a quiz application). – Jean-Philippe Pellet Jan 04 '11 at 19:51
  • @JPP, ah see - all this file encryption stuff won't help you now. – AviD Jan 09 '11 at 00:17
  • @Avid, I don't understand how encryption doesn't help me — it seems to do what I want. Save the files encrypted with my RSA public key (client cannot decrypt back) and send them to my server when time comes. If the client alters the file, it is then immediately invalid because I can't decrypt it any more, which is exactly what I want. Where's the catch? – Jean-Philippe Pellet Jan 12 '11 at 11:32

4 Answers4

9

One common, standard encryption format is Cryptographic Message Syntax (CMS, evolved from PKCS#7), and e.g. BouncyCastle supports it. It allows for signatures also, and is the basis, e.g., for S/MIME mail message security. It may be overkill, but is widely supported.

Example code is provided by Bouncy Castle. For CMS, see org.bouncycastle.cms.test, probably the Enveloped Data examples.

Another option is the XML Encryption format, standardized by W3C. For Java examples, see e.g. Exploring XML Encryption, Part 1 or do it with XSS4J: Implementing XML Encryption in Java

nealmcb
  • 20,783
  • 6
  • 72
  • 117
3

The simplest and most surefire way of file encryption is to shell out and invoke gpg or pgp to encrypt it. I know it sounds inelegant, but in my experience reviewing a lot of crypto code, this is the simplest way to ensure that your solution is secure, without having to know a lot about cryptography. If you want to do it yourself, you will need to learn more about how cryptography works, and the risk of a security problem increases.

Make sure there is authenticity protection for the encrypted data (e.g., encrypt and then sign/MAC): you will need both confidentiality and authenticity protection. A very common error is to encrypt but fail to sign; this error can introduce subtle security problems. (If you are not a cryptographer, I realize this may not make any sense to you. I realize this is by no means obvious, but I am a cryptographer. If you are familiar with IND-CCA2 and INT-CTXT, you will understand why I am recommending this. If you're not familiar with those concepts, you can read about them if you want, or you can take my word on it. Hey, crypto is tricky stuff; what can I say.) For instance, the website you link to makes this mistake; I should not rely upon that website for advice about secure encryption. The strawman approach you mention in your question also suffers from this flaw, and it looks like some of the proposed answers here also have a similar shortcoming.

An alternative approach, which is a very good one if the client and server are connected in real time, is to open a TLS-encrypted channel between the client and the server and send the data over that channel. Make sure that the client verifies the public key / cert of the server. If you want to authenticate clients, give clients a client cert and make sure that the server requires the client to provide a client cert and validates that cert.

D.W.
  • 99,525
  • 33
  • 275
  • 596
  • 4
  • Adds requirement that the gpg/pgp tool is installed on the client box. 2. You now have a new problem: you need to ensure the integrity of a tool you're calling via exec().
  • –  Jan 07 '11 at 09:47
  • 1
    @Graham, yes, this requires gpg/pgp. No, this is not a new problem: you already have to ensure the integrity of your code, so use the exact same mechanism for gpg/pgp. In practice integrity is not hard. Note: I didn't say my solution has no drawbacks, I said it was the simplest way to get good security. If you have a simpler way to do it securely, feel free to post it. But be warned in advance that there are many tricky details. – D.W. Jan 08 '11 at 00:39
  • 1
    @D.W. but you have a race condition. if(pgpExecutable.isValid()) { exec(pgpExecutable.path(), ...) –  Jan 08 '11 at 10:31
  • 1
    @Graham, you are simply wrong. That is not the solution I was proposing, nor does my solution have a race condition or any other such problem. Sounds like you're a bit confused about the threat model and how software is deployed to end machines. – D.W. Jan 09 '11 at 01:05
  • It does: it has the one I demonstrated in my comment. –  Jan 09 '11 at 16:46
  • 1
    @Graham, again, you are wrong. As I already stated, you are attacking a strawman. I am not proposing what you think I am proposing. – D.W. Jan 12 '11 at 02:41
  • 1
    @D.W. in that case please make your answer more specific. It sure looks like you are, and I'm sure most readers will find "specific example of a problem"/"you're wrong and I can't be bothered to explain why" boring after a couple of rounds ;) –  Jan 12 '11 at 11:02
  • @Graham , Yes, I agree that if the pgp tool that the Java program uses is compromised, then we have a problem. However (and I think @D.W. will agree with me), this is not a "new problem", compared to doing a functionally equivalent encryption "internally" in Java to avoid dependencies. Any cracker that can corrupt the pgp tool can just as easily corrupt the functionally equivalent code in the Java application. – David Cary Feb 28 '11 at 07:02
  • 1
    @David Cary, yes, I agree. (To elaborate on my earlier statement: "you already have to ensure the integrity of your [Java] code, so use the exact same mechanism for [ensuring the integrity of] gpg/pgp".) Oh well, that's one of the downsides of the Stack Exchange format on topics like cryptography; upvotes aren't always correlated to the best technical advice. – D.W. Feb 28 '11 at 09:17