Symmetric Encryption
Symmetric encryption uses the same key for both encryption and decryption. In Java, use an instance of javax.crypto.Cipher. Example:
import java.security.*;
import javax.crypto.*;
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, key);
byte[] ciphertext = aes.doFinal("my cleartext".getBytes());
aes.init(Cipher.DECRYPT_MODE, key);
String cleartext = new String(aes.doFinal(ciphertext));
The key for the cipher should be an instance of javax.crypto.spec.SecretKeySpec. AES in particular requires its key to be created with exactly 128 bits (16 bytes).
A simple way to get the required number of bytes is to take a variable length passphrase and hash it with a java.security.MessageDigest such as SHA1. For example:
import java.security.*;
import javax.crypto.spec.*;
String passphrase = "correct horse battery staple";
MessageDigest digest = MessageDigest.getInstance("SHA");
digest.update(passphrase.getBytes());
SecretKeySpec key = new SecretKeySpec(digest.digest(), 0, 16, "AES");
A better way to create a key is with a SecretKeyFactory using a salt:
byte[] salt = "choose a better salt".getBytes();
int iterations = 10000;
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey tmp = factory.generateSecret(new PBEKeySpec(passphrase.toCharArray(), salt, iterations, 128));
SecretKeySpec key = new SecretKeySpec(tmp.getEncoded(), "AES");
PBKDF2 is an algorithm specially designed for generating keys from passwords that is considered more secure than a simple SHA1 hash. The salt ensures your encryption won't match another encryption using the same key and cleartext and helps prevent dictionary attacks. The iterations value is an adjustable parameter. Higher values use more computing power, making brute force attacks more difficult.
Asymmetric Encryption
Asymmetric encryption, also called public key encryption, uses a key pair. One part of the key is used to encrypt and the other to decrypt. This allows you to make the encryption key public, allowing anyone to generate messages only you, the holder of the private decryption key, can read. Alternatively, you can encrypt with the private key, useful for digital signatures.
As with symmetric encryption, use an instance of javax.crypto.Cipher:
import java.security.*;
Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsa.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] ciphertext = rsa.doFinal("my cleartext".getBytes());
rsa.init(Cipher.DECRYPT_MODE, privateKey);
String cleartext = new String(rsa.doFinal(ciphertext));
In this case the keys will be instances of java.security.PublicKey and java.security.PrivateKey. To generate a new pair:
import java.security.*;
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Public and private keys can also be transformed into byte arrays for storage and transmission:
import java.security.*;
import java.security.spec.*;
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] publicKeyBytes = publicKey.getEncoded();
KeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey keyFromBytes = keyFactory.generatePublic(keySpec);
No comments:
Post a Comment