I would like to store an encrypted password in a Java file. I saw at a solution using javax.crypto, but the problem with that was that the key was being ge
Symmetric Key Cryptography : Symmetric key uses the same key for encryption and decryption. The main challenge with this type of cryptography is the exchange of the secret key between the two parties sender and receiver.
Example : The following example uses symmetric key for encryption and decryption algorithm available as part of the Sun's JCE(Java Cryptography Extension). Sun JCE is has two layers, the crypto API layer and the provider layer.
DES (Data Encryption Standard) was a popular symmetric key algorithm. Presently DES is outdated and considered insecure. Triple DES and a stronger variant of DES. It is a symmetric-key block cipher. There are other algorithms like Blowfish, Twofish and AES(Advanced Encryption Standard). AES is the latest encryption standard over the DES.
Steps :
KeyGenerator
and an algorithm to generate a secret key. We are using DESede
. UTF-8 encoding
. Cipher
with ENCRYPT_MODE
, use the secret key and encrypt the bytes. Cipher
with DECRYPT_MODE
, use the same secret key and decrypt the bytes. All the above given steps and concept are same, we just replace algorithms.
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class EncryptionDecryptionAES {
static Cipher cipher;
public static void main(String[] args) throws Exception {
/*
create key
If we need to generate a new key use a KeyGenerator
If we have existing plaintext key use a SecretKeyFactory
*/
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128); // block size is 128bits
SecretKey secretKey = keyGenerator.generateKey();
/*
Cipher Info
Algorithm : for the encryption of electronic data
mode of operation : to avoid repeated blocks encrypt to the same values.
padding: ensuring messages are the proper length necessary for certain ciphers
mode/padding are not used with stream cyphers.
*/
cipher = Cipher.getInstance("AES"); //SunJCE provider AES algorithm, mode(optional) and padding schema(optional)
String plainText = "AES Symmetric Encryption Decryption";
System.out.println("Plain Text Before Encryption: " + plainText);
String encryptedText = encrypt(plainText, secretKey);
System.out.println("Encrypted Text After Encryption: " + encryptedText);
String decryptedText = decrypt(encryptedText, secretKey);
System.out.println("Decrypted Text After Decryption: " + decryptedText);
}
public static String encrypt(String plainText, SecretKey secretKey)
throws Exception {
byte[] plainTextByte = plainText.getBytes();
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedByte = cipher.doFinal(plainTextByte);
Base64.Encoder encoder = Base64.getEncoder();
String encryptedText = encoder.encodeToString(encryptedByte);
return encryptedText;
}
public static String decrypt(String encryptedText, SecretKey secretKey)
throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
byte[] encryptedTextByte = decoder.decode(encryptedText);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedByte = cipher.doFinal(encryptedTextByte);
String decryptedText = new String(decryptedByte);
return decryptedText;
}
}
Output:
Plain Text Before Encryption: AES Symmetric Encryption Decryption
Encrypted Text After Encryption: sY6vkQrWRg0fvRzbqSAYxepeBIXg4AySj7Xh3x4vDv8TBTkNiTfca7wW/dxiMMJl
Decrypted Text After Decryption: AES Symmetric Encryption Decryption
Source
Example: Cipher with two modes, they are encrypt and decrypt. we have to start every time after setting mode to encrypt or decrypt a text.
You may want to use the jasypt library (Java Simplified Encryption), which is quite easy to use. ( Also, it's recommended to check against the encrypted password rather than decrypting the encrypted password )
To use jasypt, if you're using maven, you can include jasypt into your pom.xml file as follows:
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.3</version>
<scope>compile</scope>
</dependency>
And then to encrypt the password, you can use StrongPasswordEncryptor
public static String encryptPassword(String inputPassword) {
StrongPasswordEncryptor encryptor = new StrongPasswordEncryptor();
return encryptor.encryptPassword(inputPassword);
}
Note: the encrypted password is different every time you call encryptPassword but the checkPassword method can still check that the unencrypted password still matches each of the encrypted passwords.
And to check the unencrypted password against the encrypted password, you can use the checkPassword method:
public static boolean checkPassword(String inputPassword, String encryptedStoredPassword) {
StrongPasswordEncryptor encryptor = new StrongPasswordEncryptor();
return encryptor.checkPassword(inputPassword, encryptedStoredPassword);
}
The page below provides detailed information on the complexities involved in creating safe encrypted passwords.
http://www.jasypt.org/howtoencryptuserpasswords.html
If you use a static key, encrypt and decrypt always give the same result;
public static final String CRYPTOR_KEY = "your static key here";
byte[] keyByte = Base64.getDecoder().decode(CRYPTOR_KEY);
key = new SecretKeySpec(keyByte, "AES");
Here is a solution using the javax.crypto library and the apache commons codec library for encoding and decoding in Base64 that I was looking for:
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Base64;
public class TrippleDes {
private static final String UNICODE_FORMAT = "UTF8";
public static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
private KeySpec ks;
private SecretKeyFactory skf;
private Cipher cipher;
byte[] arrayBytes;
private String myEncryptionKey;
private String myEncryptionScheme;
SecretKey key;
public TrippleDes() throws Exception {
myEncryptionKey = "ThisIsSpartaThisIsSparta";
myEncryptionScheme = DESEDE_ENCRYPTION_SCHEME;
arrayBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
ks = new DESedeKeySpec(arrayBytes);
skf = SecretKeyFactory.getInstance(myEncryptionScheme);
cipher = Cipher.getInstance(myEncryptionScheme);
key = skf.generateSecret(ks);
}
public String encrypt(String unencryptedString) {
String encryptedString = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainText = unencryptedString.getBytes(UNICODE_FORMAT);
byte[] encryptedText = cipher.doFinal(plainText);
encryptedString = new String(Base64.encodeBase64(encryptedText));
} catch (Exception e) {
e.printStackTrace();
}
return encryptedString;
}
public String decrypt(String encryptedString) {
String decryptedText=null;
try {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptedText = Base64.decodeBase64(encryptedString);
byte[] plainText = cipher.doFinal(encryptedText);
decryptedText= new String(plainText);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedText;
}
public static void main(String args []) throws Exception
{
TrippleDes td= new TrippleDes();
String target="imparator";
String encrypted=td.encrypt(target);
String decrypted=td.decrypt(encrypted);
System.out.println("String To Encrypt: "+ target);
System.out.println("Encrypted String:" + encrypted);
System.out.println("Decrypted String:" + decrypted);
}
}
Running the above program results with the following output:
String To Encrypt: imparator
Encrypted String:FdBNaYWfjpWN9eYghMpbRA==
Decrypted String:imparator
public class GenerateEncryptedPassword {
public static void main(String[] args){
Scanner sc= new Scanner(System.in);
System.out.println("Please enter the password that needs to be encrypted :");
String input = sc.next();
try {
String encryptedPassword= AESencrp.encrypt(input);
System.out.println("Encrypted password generated is :"+encryptedPassword);
} catch (Exception ex) {
Logger.getLogger(GenerateEncryptedPassword.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Here is a sample I made a couple of months ago The class encrypt and decrypt data
import java.security.*;
import java.security.spec.*;
import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class TestEncryptDecrypt {
private final String ALGO = "DES";
private final String MODE = "ECB";
private final String PADDING = "PKCS5Padding";
private static int mode = 0;
public static void main(String args[]) {
TestEncryptDecrypt me = new TestEncryptDecrypt();
if(args.length == 0) mode = 2;
else mode = Integer.parseInt(args[0]);
switch (mode) {
case 0:
me.encrypt();
break;
case 1:
me.decrypt();
break;
default:
me.encrypt();
me.decrypt();
}
}
public void encrypt() {
try {
System.out.println("Start encryption ...");
/* Get Input Data */
String input = getInputData();
System.out.println("Input data : "+input);
/* Create Secret Key */
KeyGenerator keyGen = KeyGenerator.getInstance(ALGO);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.init(56,random);
Key sharedKey = keyGen.generateKey();
/* Create the Cipher and init it with the secret key */
Cipher c = Cipher.getInstance(ALGO+"/"+MODE+"/"+PADDING);
//System.out.println("\n" + c.getProvider().getInfo());
c.init(Cipher.ENCRYPT_MODE,sharedKey);
byte[] ciphertext = c.doFinal(input.getBytes());
System.out.println("Input Encrypted : "+new String(ciphertext,"UTF8"));
/* Save key to a file */
save(sharedKey.getEncoded(),"shared.key");
/* Save encrypted data to a file */
save(ciphertext,"encrypted.txt");
} catch (Exception e) {
e.printStackTrace();
}
}
public void decrypt() {
try {
System.out.println("Start decryption ...");
/* Get encoded shared key from file*/
byte[] encoded = load("shared.key");
SecretKeyFactory kf = SecretKeyFactory.getInstance(ALGO);
KeySpec ks = new DESKeySpec(encoded);
SecretKey ky = kf.generateSecret(ks);
/* Get encoded data */
byte[] ciphertext = load("encrypted.txt");
System.out.println("Encoded data = " + new String(ciphertext,"UTF8"));
/* Create a Cipher object and initialize it with the secret key */
Cipher c = Cipher.getInstance(ALGO+"/"+MODE+"/"+PADDING);
c.init(Cipher.DECRYPT_MODE,ky);
/* Update and decrypt */
byte[] plainText = c.doFinal(ciphertext);
System.out.println("Plain Text : "+new String(plainText,"UTF8"));
} catch (Exception e) {
e.printStackTrace();
}
}
private String getInputData() {
String id = "owner.id=...";
String name = "owner.name=...";
String contact = "owner.contact=...";
String tel = "owner.tel=...";
final String rc = System.getProperty("line.separator");
StringBuffer buf = new StringBuffer();
buf.append(id);
buf.append(rc);
buf.append(name);
buf.append(rc);
buf.append(contact);
buf.append(rc);
buf.append(tel);
return buf.toString();
}
private void save(byte[] buf, String file) throws IOException {
FileOutputStream fos = new FileOutputStream(file);
fos.write(buf);
fos.close();
}
private byte[] load(String file) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(file);
byte[] buf = new byte[fis.available()];
fis.read(buf);
fis.close();
return buf;
}
}