package org.jabref.shared.security;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* {@link Password} contains methods which are useful to encrypt and decrypt passwords using symetric algorithms.
*/
public class Password {
private final byte[] phrase;
private final Cipher cipher;
private final SecretKeySpec secretKey;
private final IvParameterSpec ivSpec;
/**
* @param phrase Phrase which should be encrypted or decrypted
* @param key Key which is used to improve symmetric encryption
*/
public Password(char[] phrase, String key) throws NoSuchAlgorithmException, NoSuchPaddingException {
this.phrase = new String(phrase).getBytes();
this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
this.secretKey = new SecretKeySpec(get128BitHash(key.getBytes()), "AES");
this.ivSpec = new IvParameterSpec("ThisIsA128BitKey".getBytes());
}
/**
* Encrypts the set phrase/password with a symmetric encryption algorithm.
*
* @return Encrypted phrase/password
*/
public String encrypt() throws GeneralSecurityException, UnsupportedEncodingException {
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
return new String(Base64.getEncoder().encode(cipher.doFinal(phrase)), "UTF-8");
}
/**
* Decrypts the set phrase/password which was encrypted via {@link Password#encrypt()}.
*
* @return Decrypted phrase/password
*/
public String decrypt() throws GeneralSecurityException, UnsupportedEncodingException {
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
return new String(cipher.doFinal(Base64.getDecoder().decode(phrase)), "UTF-8");
}
/**
* Returns a 128 bit hash using SHA-256.
*/
private byte[] get128BitHash(byte[] byteArrayToHash) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(byteArrayToHash);
return Arrays.copyOf(messageDigest.digest(), 16); // return 128 bit
}
}