public key cryptograpy with Java and OpenSSL
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:
- Once and for all generate a public/private key pair.
- Encrypt a
byte[开发者_StackOverflow中文版]
in Java using the public key, store it somewhere. - Copy the encrypted data to a "safer" computer.
- 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.
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();
}
}
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.
精彩评论