package com.sromku.simple.storage.security;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* Security utils for encryption, xor and more
*
* @author Roman Kushnarenko - sromku (sromku@gmail.com)
*/
public class SecurityUtil {
/**
* Encrypt or Descrypt the content. <br>
*
* @param content
* The content to encrypt or descrypt.
* @param encryptionMode
* Use: {@link Cipher#ENCRYPT_MODE} or
* {@link Cipher#DECRYPT_MODE}
* @param secretKey
* Set the secret key for encryption of file content.
* <b>Important: The length must be 16 long</b>. <i>Uses SHA-256
* to generate a hash from your key and trim the result to 128
* bit (16 bytes)</i>
* @param ivx
* This is not have to be secret. It used just for better
* randomizing the cipher. You have to use the same IV parameter
* within the same encrypted and written files. Means, if you
* want to have the same content after descryption then the same
* IV must be used. <i>About this parameter from wiki:
* https://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
* #Initialization_vector_.28IV.29</i> <b>Important: The length
* must be 16 long</b>
* @return
*/
public static byte[] encrypt(byte[] content, int encryptionMode, final byte[] secretKey, final byte[] ivx) {
if (secretKey.length != 16 || ivx.length != 16) {
throw new RuntimeException("Set the encryption parameters correctly. The must be 16 length long each");
}
try {
final SecretKey secretkey = new SecretKeySpec(secretKey, CipherAlgorithmType.AES.getAlgorithmName());
final IvParameterSpec IV = new IvParameterSpec(ivx);
final String transformation = CipherTransformationType.AES_CBC_PKCS5Padding;
final Cipher decipher = Cipher.getInstance(transformation);
decipher.init(encryptionMode, secretkey, IV);
final byte[] plainText = decipher.doFinal(content);
return plainText;
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Failed to encrypt/descrypt - Unknown Algorithm", e);
}
catch (NoSuchPaddingException e) {
throw new RuntimeException("Failed to encrypt/descrypt- Unknown Padding", e);
}
catch (InvalidKeyException e) {
throw new RuntimeException("Failed to encrypt/descrypt - Invalid Key", e);
}
catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException("Failed to encrypt/descrypt - Invalid Algorithm Parameter", e);
}
catch (IllegalBlockSizeException e) {
throw new RuntimeException("Failed to encrypt/descrypt", e);
}
catch (BadPaddingException e) {
throw new RuntimeException("Failed to encrypt/descrypt", e);
}
}
/**
* Do xor operation on the string with the key
*
* @param str
* The string to xor on
* @param key
* The key by which the xor will work
* @return The string after xor
*/
public String xor(String msg, String key) {
try {
final String UTF_8 = "UTF-8";
byte[] msgArray;
msgArray = msg.getBytes(UTF_8);
byte[] keyArray = key.getBytes(UTF_8);
byte[] out = new byte[msgArray.length];
for (int i = 0; i < msgArray.length; i++) {
out[i] = (byte) (msgArray[i] ^ keyArray[i % keyArray.length]);
}
return new String(out, UTF_8);
}
catch (UnsupportedEncodingException e) {
}
return null;
}
}