import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableEntryException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
/**
*
* @author wangbo
*/
public class ReadKeyStore {
public static void main(String[] args) throws KeyStoreException, FileNotFoundException, IOException,
NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, UnrecoverableEntryException,
javax.security.cert.CertificateException {
// load keystore
FileInputStream keystoreIn = new FileInputStream(Util.PATH_KEYSTORE);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(keystoreIn, Util.KEYSTORE_STOREPASS.toCharArray());
keystoreIn.close();
// get entry from keystore
KeyStore.ProtectionParameter protectionParameter = new KeyStore.PasswordProtection(
Util.KEYSTORE_KEYPASS.toCharArray());
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) keystore.getEntry(
Util.KEYSTORE_ALIAS_RSAKEY, protectionParameter);
// get certificate
Certificate cert = keyEntry.getCertificate();
// get public key (we'll not use public key this time.)
PublicKey pubKey = cert.getPublicKey();
// get private key (we'll not use private key this time.)
PrivateKey priKey = keyEntry.getPrivateKey();
// store certificate into a file
FileOutputStream certOut = new FileOutputStream(Util.PATH_CERTIFICATE);
certOut.write(cert.getEncoded());
certOut.close();
}
}
Encryption
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.security.cert.CertificateException;
import javax.security.cert.X509Certificate;
/**
*
* @author wangbo
*/
public class RSAEncrypt {
public static void main(String[] args) throws IOException, ClassNotFoundException,
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, CertificateException {
// get certificate
FileInputStream certIn = new FileInputStream(Util.PATH_CERTIFICATE);
byte[] certBytes = new byte[certIn.available()];
certIn.read(certBytes);
certIn.close();
X509Certificate cert = X509Certificate.getInstance(certBytes);
// get public key from certificate
PublicKey pubKey = cert.getPublicKey();
// generate a secret key and wrap it with public key
KeyGenerator genKey = KeyGenerator.getInstance("AES");
genKey.init(new SecureRandom());
SecretKey secretKey = genKey.generateKey();
Cipher rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.WRAP_MODE, pubKey);
byte[] wrappedSecretKeyBytes = rsaCipher.wrap(secretKey);
// write secret key into a file
FileOutputStream secretKeyOut = new FileOutputStream(Util.PATH_SECRETKEY);
secretKeyOut.write(wrappedSecretKeyBytes);
secretKeyOut.close();
// encrypt data with secret key
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, secretKey);
BufferedInputStream dataIn = new BufferedInputStream(new FileInputStream(Util.PATH_DATA));
BufferedOutputStream encryptedDataOut = new BufferedOutputStream(new FileOutputStream(
Util.PATH_DATA_ENCRYPTED));
byte[] inBytes = new byte[aesCipher.getBlockSize()];
byte[] outBytes;
int len;
while ((len = dataIn.read(inBytes)) >= 0) {
outBytes = aesCipher.update(inBytes, 0, len);
encryptedDataOut.write(outBytes);
}
outBytes = aesCipher.doFinal();
encryptedDataOut.write(outBytes);
dataIn.close();
encryptedDataOut.close();
}
}
Decryption
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
/**
* @author WANG BO
*/
public class RSADecrypt {
public static void main (String[] args) throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException, UnrecoverableEntryException {
// get private key
BufferedInputStream keystoreIn = new BufferedInputStream (new FileInputStream (
Util.PATH_KEYSTORE));
KeyStore keystore = KeyStore.getInstance (KeyStore.getDefaultType ());
keystore.load (keystoreIn, Util.KEYSTORE_STOREPASS.toCharArray ());
keystoreIn.close ();
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry)keystore.getEntry (
Util.KEYSTORE_ALIAS_RSAKEY,
new KeyStore.PasswordProtection (Util.KEYSTORE_KEYPASS.toCharArray ()));
PrivateKey priKey = keyEntry.getPrivateKey ();
// get encrypted key and unwrap it with private key
Cipher rsaCipher = Cipher.getInstance ("RSA");
rsaCipher.init (Cipher.UNWRAP_MODE, priKey);
FileInputStream unwrappedSecretKeyIn = new FileInputStream (Util.PATH_SECRETKEY);
byte[] unwrappedSecretKeyBytes = new byte[unwrappedSecretKeyIn.available ()];
unwrappedSecretKeyIn.read (unwrappedSecretKeyBytes);
unwrappedSecretKeyIn.close ();
Key secretkey = rsaCipher.unwrap (unwrappedSecretKeyBytes, "AES", Cipher.SECRET_KEY);
// get encrypted data and decrypt it with secret key
BufferedInputStream encryptedDataIn = new BufferedInputStream (new FileInputStream (
Util.PATH_DATA_ENCRYPTED));
BufferedOutputStream decryptedDataOut = new BufferedOutputStream (new FileOutputStream (
Util.PATH_DATA_DECRYPTED));
Cipher aes = Cipher.getInstance ("AES");
aes.init (Cipher.DECRYPT_MODE, secretkey);
byte[] inBytes = new byte[aes.getBlockSize ()];
byte[] outBytes;
int len;
while ((len = encryptedDataIn.read (inBytes)) >= 0) {
outBytes = aes.update (inBytes, 0, len);
decryptedDataOut.write (outBytes);
}
outBytes = aes.doFinal ();
decryptedDataOut.write (outBytes);
encryptedDataIn.close ();
decryptedDataOut.close ();
}
}
Why don't encrypt the message directly with RSA algorithm?
- RSA can encrypt data of limited size, the length is not possible to be over the length of RSA key. With the commonly used "v1.5 padding" and a 2048-bit RSA key, the maximum size of data which can be encrypted with RSA is 245 bytes. No more.
- Encrypt big chunk data is very expensive
- There is not any problem if the data you want to encrypt is very short.