package ru.jimbot.util;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class CryptoUtil {
/**
* Алгоритм шифрования. Возможны варианты:
* DES: Digital Encryption Standard
* DESede: Triple DES Encryption
* Blowfish: The block cipher designed by Bruce Schneier
* и другие
*/
private static final String ALGORITHM_KEY = "Blowfish";
/**
* Режим работы алгоритма. Режимов много, например:
* DES/CBC/PKCS5Padding
* DES/PCBC/PKCS5Padding
* DESede/ECB/PKCS5Padding
* DESede/ECB/PKCS5Padding
* Blowfish/CBC/PKCS5Padding
* и много других
*/
private static final String ALGORITHM = "Blowfish/PCBC/PKCS5Padding";
/**
* Параметр инициализации алгоритма шифрования. Значения байтов могут
* быть разными, но одинаковыми для шифрации и дешифрации одних и тех
* же данных
*/
private static final byte[] SALT = new byte[]{
(byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
(byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99};
/**
* 64 bit secret key from raw bytes
*/
private static final SecretKey key64 = new SecretKeySpec(
new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, ALGORITHM_KEY);
/**
* 192 bit secret key from raw bytes
*/
private static final SecretKey key192 = new SecretKeySpec(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17 }, ALGORITHM_KEY);
/**
* Кодирование заданного текста алгоритмом ALGORITHM с использованием
* сгенерированного ключа
*
* @param cleartext текст для шифрования
* @param key ключ, используемый при шифровании
* @return байтовый массив
* @see CryptoUtil#generateKey
*/
public static byte[] encode(String cleartext, Key key) {
try {
return crypt(cleartext.getBytes("UTF-8"), key, Cipher.ENCRYPT_MODE);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
/**
* Кодирование заданного текста алгоритмом ALGORITHM с использованием
* сгенерированного ключа
*
* @param data данные для шифрования
* @param key ключ, используемый при шифровании
* @return байтовый массив
* @see CryptoUtil#generateKey
*/
public static byte[] encode(byte[] data, Key key) {
return crypt(data, key, Cipher.ENCRYPT_MODE);
}
/**
* Метод для дешифрования текста.
*
* @param ciphertext зашифрованный текст в виде байтового массива
* @param key ключ, использованный при шифровании текста
* @return дешифрованный текст
* @see CryptoUtil#generateKey
*/
public static String decode(byte[] ciphertext, Key key) {
try {
return new String(crypt(ciphertext, key, Cipher.DECRYPT_MODE), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
/**
* Метод генерации ключа, используемого в алгоритме шифрования
*
* @return ключ для шифрования
*/
private static SecretKey generateKey() {
try {
return KeyGenerator.getInstance(ALGORITHM_KEY).generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* Метод шифрования/дешифрования текста в зависимости от параметра mode
*
* @param input входной байтовый массив для шифрования
* @param key секретный ключ, используемый при шифровании
* @param mode режим работы алгоритма (шифрование/дешифрование)
* @return зашифрованный или дешифрованный текст в виде байтового массива
*/
private static byte[] crypt(byte[] input, Key key, int mode) {
IvParameterSpec iv = new IvParameterSpec(SALT);
Cipher c;
try {
c = Cipher.getInstance(ALGORITHM);
c.init(mode, key, iv);
return c.doFinal(input);
} catch (Exception e) {
// вообще-то может возникать несколько типов исключений и их нужно
// обрабатывать соотв. образом. Но в примере это не важно
e.printStackTrace();
}
return null;
}
}