content: package config.security;
  
  import excp.PasswordConfigException;
  import lombok.SneakyThrows;
  import lombok.extern.slf4j.Slf4j;
  
  import javax.crypto.*;
  import javax.crypto.spec.PBEKeySpec;
  import javax.crypto.spec.PBEParameterSpec;
  import javax.inject.Inject;
  import javax.inject.Singleton;
  import java.io.IOException;
  import java.io.UnsupportedEncodingException;
  import java.net.InetAddress;
  import java.nio.charset.StandardCharsets;
  import java.security.InvalidAlgorithmParameterException;
  import java.security.InvalidKeyException;
  import java.security.NoSuchAlgorithmException;
  import java.security.spec.AlgorithmParameterSpec;
  import java.security.spec.InvalidKeySpecException;
  import java.security.spec.KeySpec;
  import java.util.Base64;
  import java.util.Map;
  
  /** Encryption and Decryption of String data;
   *  PBE(Password Based Encryption and Decryption)
   *
   *  @link https://stackoverflow.com/a/30591380
   *  @author Vikram
   **/
  @Slf4j
  @Singleton
  public class PassConfig {
      private Cipher ecipher;
      private Cipher dcipher;
      private String algoritm = "PBEWithMD5AndDES";
      // 8-byte Salt
      private byte[] salt = {
              (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
              (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
      };
      // Iteration count
      private int iterationCount = 19;
  
      @Inject
      public PassConfig() { }
  
      @SneakyThrows
      public String encrypt(String plainText){
          if (plainText == null)
              throw new PasswordConfigException("Text for encryption could not be null.. " +
                  "Check password field of connProfile entity in configuration!");
  
          return encrypt(getComputerName(), plainText);
      }
  
      @SneakyThrows
      public String decrypt(String encryptedText){
          if (encryptedText == null)
              throw new PasswordConfigException("Text for decryption could not be null.. " +
                      "Check password field of connProfile entity in configuration!");
  
          return decrypt(getComputerName(), encryptedText);
      }
  
      /**
       * @param secretKey Key used to encrypt data
       * @param plainText Text input to be encrypted
       * @return Returns encrypted text
       * @throws java.security.NoSuchAlgorithmException
       * @throws java.security.spec.InvalidKeySpecException
       * @throws javax.crypto.NoSuchPaddingException
       * @throws java.security.InvalidKeyException
       * @throws java.security.InvalidAlgorithmParameterException
       * @throws java.io.UnsupportedEncodingException
       * @throws javax.crypto.IllegalBlockSizeException
       * @throws javax.crypto.BadPaddingException
       */
      private String encrypt(String secretKey, String plainText)
              throws NoSuchAlgorithmException,
              InvalidKeySpecException,
              NoSuchPaddingException,
              InvalidKeyException,
              InvalidAlgorithmParameterException,
              UnsupportedEncodingException,
              IllegalBlockSizeException,
              BadPaddingException {
          //Key generation for enc and desc
          KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount);
          SecretKey key = SecretKeyFactory.getInstance(algoritm).generateSecret(keySpec);
          // Prepare the parameter to the ciphers
          AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
  
          //Enc process
          ecipher = Cipher.getInstance(key.getAlgorithm());
          ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
          byte[] in = plainText.getBytes(StandardCharsets.UTF_8);
          byte[] out = ecipher.doFinal(in);
          String encStr = new String(Base64.getEncoder().encode(out));
          return encStr;
      }
  
      /**
       * @param secretKey     Key used to decrypt data
       * @param encryptedText encrypted text input to decrypt
       * @return Returns plain text after decryption
       * @throws java.security.NoSuchAlgorithmException
       * @throws java.security.spec.InvalidKeySpecException
       * @throws javax.crypto.NoSuchPaddingException
       * @throws java.security.InvalidKeyException
       * @throws java.security.InvalidAlgorithmParameterException
       * @throws java.io.UnsupportedEncodingException
       * @throws javax.crypto.IllegalBlockSizeException
       * @throws javax.crypto.BadPaddingException
       */
      private String decrypt(String secretKey, String encryptedText)
              throws NoSuchAlgorithmException,
              InvalidKeySpecException,
              NoSuchPaddingException,
              InvalidKeyException,
              InvalidAlgorithmParameterException,
              UnsupportedEncodingException,
              IllegalBlockSizeException,
              BadPaddingException,
              IOException {
          //Key generation for enc and desc
          KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount);
          SecretKey key = SecretKeyFactory.getInstance(algoritm).generateSecret(keySpec);
          // Prepare the parameter to the ciphers
          AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
          //Decryption process; same key will be used for decr
          dcipher = Cipher.getInstance(key.getAlgorithm());
          dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
          byte[] enc = Base64.getDecoder().decode(encryptedText);
          byte[] utf8 = dcipher.doFinal(enc);
          String plainStr = new String(utf8, StandardCharsets.UTF_8);
          return plainStr;
      }
  
      @SneakyThrows
      private String getComputerName()
      {
          Map<String, String> env = System.getenv();
          if (env.containsKey("COMPUTERNAME"))
              return env.get("COMPUTERNAME");
          else if (env.containsKey("HOSTNAME"))
              return env.get("HOSTNAME");
          else
              return InetAddress.getLocalHost().toString();
      }
  }
  