2

In an application I want to store sensitive data (which can be arbitrarily large) so that it can later be used for researching. The point is that I don't want the data to lie around unprotected, so I want to encrypt it before saving it.

On another computer (in a more trustworthy environment) I want to decrypt that data later. The decryption should be possible with readily available tools, for example OpenSSL. Now my question is: How do I do all that?

I already know the abstract steps:

  1. Once and for all generate a public/private key pair.
  2. Encrypt a byte[] in Java using the public key, store it somewhere.
  3. Copy the encrypted data to a "safer" computer.
  4. Decrypt the saved data using a simple OpenSSL command line.

What I'm missing now are the details:

  • What kind of key pair do I need?
  • What encryption scheme should I use? (it's probably something like "rsa-encrypt a symmetric key, then encrypt the data with that key")
  • How does the simple OpenSSL command line look like?

[Update 2011-02-13]

After a little research I found a page that describes exactly what I want to do: http://blog.altudov.com/2010/09/27/using-openssl-for-asymmetric-encryption-of-backups/. Basically the answer to my step 4 is this command line:

openssl smime -decrypt \
  -in data.smime -binary -inform DER \
  -inkey key.pem \
  -out data

Now my question is: How can I generate a file from Java whose format is compatible to OpenSSL so I can decompress it using this command line? I want to do this hundrets of times per second, so invoking an external process seems too slow. That's why I want to do it directly in Java.

Roland Illig
  • 40,703
  • 10
  • 88
  • 121

2 Answers2

1

I finally found exactly what I was looking for. I had just been confused by all the terms like S/MIME, ASN.1, DER, and so on. But finally, and seemingly by coincident, I reached the CMS (whatever that means) package from bouncycastle, which does everything I want. So here is my code:

package de.roland_illig.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.apache.commons.io.IOUtils;
import org.bouncycastle.cms.CMSEnvelopedDataStreamGenerator;
import org.bouncycastle.cms.CMSEnvelopedGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class CryptDemo {

  private static final File DIR = new File("c:/program files/cygwin/home/roland/crypto/");

  private static X509Certificate certificate() throws IOException, GeneralSecurityException {
    InputStream is = new FileInputStream(new File(DIR, "key.pub.der"));
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
    is.close();
    return cert;
  }

  private static void encrypt() throws IOException, GeneralSecurityException, CMSException {
    CMSEnvelopedDataStreamGenerator gen = new CMSEnvelopedDataStreamGenerator();
    gen.addKeyTransRecipient(certificate());

    InputStream is = new FileInputStream(new File(DIR, "secret"));
    OutputStream out = new FileOutputStream(new File(DIR, "secret.encrypted"));
    OutputStream encryptingOut = gen.open(out, CMSEnvelopedGenerator.AES128_CBC, "BC");

    IOUtils.copy(is, encryptingOut);

    is.close();
    encryptingOut.close();
    out.close();
  }

  public static void main(String[] args) throws Exception {
    Security.addProvider(new BouncyCastleProvider());

    encrypt();
  }
}
Roland Illig
  • 40,703
  • 10
  • 88
  • 121
  • I do not seriously get it why you insist on mixing PKI into your solution still although you have obviously no reason for it and it does not produce any extra value in point-to-point solutions like yours... That imho unfortunately demonstrates that you did not understand the previously discussed concepts entirely... :( But anyways, I'm glad you're happy with your solution. – erloewe Feb 14 '11 at 15:43
  • The encrypted data contains information that should not be easily decryptable. So if I use symmetric encryption I would have to leave the key somewhere on the server. If that key is revealed (by some attack on the server) there is no point in encrypting the data in the first place. Therefore I wanted to use asymmetric encryption. The reason for mentioning OpenSSL was just that I want to be able to decrypt the data with readily available tools, and OpenSSL seems to be widespread enough. – Roland Illig Feb 14 '11 at 22:34
  • Now I understand your point. I should not use PKI when a simple public/private key pair suffices. So can you tell me how I can achieve my goal in a simpler way? – Roland Illig Feb 15 '11 at 15:26
0

You should understand that SSL is about encrypting network traffic. Public key systems with certificates and so on are good for validating trust between parties. If you need to protect something that you will be using yourself later you should probably go without mixing the previous concepts into your solution. It makes your life easier.

Take for instance this question and the accepted answer it has as a pointer. What you probably should do is to use a hash function to generate a key from password. Then you would encrypt your data using AES. Later at a safe location you would use the same password to generate the actual key and decrypt the data.

Community
  • 1
  • 1
erloewe
  • 1,319
  • 9
  • 20
  • I think I already understand all of the concepts. I just want to have an encrypted format that can be easily understood by tools that are already installed on most machines, instead of growing my own file format for encrypted data snippets. – Roland Illig Feb 13 '11 at 21:36
  • @Roland In that case something like http://bsdsupport.org/2007/01/q-how-do-i-use-openssl-to-encrypt-files/ will do :) – erloewe Feb 13 '11 at 21:49
  • Thanks for the link. I just wrote a comment there that `rsautl` cannot encrypt large files, so this is not the solution. Anyway, I updated the question with what I got so far. – Roland Illig Feb 13 '11 at 22:02