package org.intellimate.izou.security; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.jcajce.provider.digest.SHA3; import org.bouncycastle.util.encoders.Hex; import javax.crypto.*; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; /** * SecurityFunction implements basic cryptographic functions like hash functions or encryption and decryption * functions. */ public final class SecurityFunctions { private final Logger logger = LogManager.getLogger(this.getClass()); /** * Applies SHA-3 hash function on the {@code input} string * * @param input the string to apply to SHA-3 hash on * @return the hashed input string */ public String sha3(String input) { String hash = ""; try { SHA3.DigestSHA3 md = new SHA3.DigestSHA3(256); md.update(input.getBytes("UTF-8")); hash = Hex.toHexString(md.digest()); } catch (UnsupportedEncodingException e) { logger.error("Error while hashing with SHA-3", e); } return hash; } /** * Applies an AES encryption on the string {@code plainText} with they given key * <p> * Keys have to be generated using the {@link #generateKey()} function * </p> * @param plainText the string to encrypt * @param key the key to use during the encryption * @return a byte array containing the encrypted data */ public byte[] encryptAES(String plainText, SecretKey key) { byte[] byteCipherText = new byte[0]; try { Cipher cipher = Cipher.getInstance("AES", "BC"); cipher.init(Cipher.ENCRYPT_MODE, key); byteCipherText = cipher.doFinal(plainText.getBytes("UTF-8")); } catch (BadPaddingException | NoSuchAlgorithmException | IllegalBlockSizeException | NoSuchPaddingException | InvalidKeyException | UnsupportedEncodingException | NoSuchProviderException e) { logger.error("Unable to apply AES encryption", e); } return byteCipherText; } /** * Applies an AES decryption on the byte array {@code cipherBytes} with they given key. The key has to be the same * key used during encryption, else null is returned * * @param cipherBytes the byte array to decrypt * @param key the key to use during the decryption * @return the decrypted string if everything was successful, else null */ public String decryptAES(byte[] cipherBytes, SecretKey key) { String plainText = null; Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); try { Cipher cipher = Cipher.getInstance("AES", "BC"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] bytePlainText = cipher.doFinal(cipherBytes); plainText = new String(bytePlainText, "UTF-8"); } catch (IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException | BadPaddingException | NoSuchPaddingException | UnsupportedEncodingException | NoSuchProviderException e) { logger.error("Unable to apply AES decryption", e); } return plainText; } /** * Generates a key for the AES encryption * * @return a new key for the AES encryption */ public SecretKey generateKey() { SecretKey key = null; try { KeyGenerator generator = KeyGenerator.getInstance("AES"); generator.init(128); key = generator.generateKey(); } catch (NoSuchAlgorithmException e) { logger.error("Unable to generate AES key", e); } return key; } }