title: AES-256(CBC) : encryption in Java/Decryption in JavaScript(CryptoJS)
body: <p>I am doing encryption in Java and decrypting it with JavaScript using AES-256/CBC, but actually this is the scenario: 
  while encryption of <strong>.pdf</strong>, <strong>.jpg</strong>, in other words, other than text files Java produces the encrypted file with roughly the same bytes but in case of JavaScript(<a href="https://code.google.com/archive/p/crypto-js/" rel="nofollow noreferrer" title="CryptoJS documentation">CryptoJS</a>) it outputs ~1.5 times of the original file size, which is why I think for the decryption with <a href="https://code.google.com/archive/p/crypto-js/" rel="nofollow noreferrer" title="CryptoJS documentation">CryptoJS</a> it does not expect the small encrypted file size from Java. I have given the code from both sides i.e, encryption at Java side, decryption at JavaScript side. </p>
  
  <p><strong>Problem</strong>: </p>
  
  <p>I have a requirement of encrypting any file with Java and decrypting the same file with JavaScript. Kindly refer to the code as given below and this <a href="https://github.com/mpetersen/aes-example" rel="nofollow noreferrer">example</a>.</p>
  
  <p><strong>Java: Encryption</strong></p>
  
  <ol>
  <li><p>key generation:</p>
  
  <pre><code> Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
   SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
   KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), iterationCount, keySize);
   SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
  </code></pre></li>
  <li><p>Encryption:</p>
  
  <p>params:</p>
  
  <pre><code>private static final String IV = "F27D5C9927726BCEFE7510B1BDD3D137";
  private static final String SALT = "3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55";
  private static final int KEY_SIZE = 128;
  private static final int ITERATION_COUNT = 10000;
  private static final String PASSWORD = "SET_YOUR_PASSWORD_HERE";
  </code></pre>
  
  <p>code:</p>
  
  <pre><code>public String encrypt(String salt, String iv, String passphrase, String plaintext) {
      try {
          SecretKey key = generateKey(salt, passphrase);
          byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, iv, plaintext.getBytes("UTF-8"));
          return base64(encrypted);
      } catch (Exception e) {
          throw fail(e);
      }
  }
  private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) {
      try {
          cipher.init(encryptMode, key, new IvParameterSpec(hex(iv)));
          return cipher.doFinal(bytes);
      } catch (InvalidKeyException |
          InvalidAlgorithmParameterException |
          IllegalBlockSizeException |
          BadPaddingException e) {
          throw fail(e);
      }
  }
  public static String base64(byte[] bytes) {
      return Base64.getEncoder().encodeToString(bytes);
  }
  public static byte[] base64(String str) {
      return Base64.getDecoder().decode(str);
  }
  protected static byte[] hex(String str) {
      try {
          return decodeHex(str.toCharArray());
      } catch (Exception e) {
          e.printStackTrace();
      }
  
      return new byte[0];
  }
  public static byte[] decodeHex(char[] data) throws Exception {
      int len = data.length;
      if ((len &amp; 1) != 0) {
          throw new Exception("Odd number of characters.");
      } else {
          byte[] out = new byte[len &gt;&gt; 1];
          int i = 0;
  
          for (int j = 0; j &lt; len; ++i) {
              int f = toDigit(data[j], j) &lt;&lt; 4;
              ++j;
              f |= toDigit(data[j], j);
              ++j;
              out[i] = (byte)(f &amp; 255);
          }
  
          return out;
      }
  }
  protected static int toDigit(char ch, int index) throws Exception {
      int digit = Character.digit(ch, 16);
      if (digit == -1) {
          throw new Exception("Illegal hexadecimal character " + ch + " at index " + index);
      } else {
          return digit;
      }
  }
  public static byte[] hexStringToByteArray(String s) {
      int len = s.length();
  
      byte[] data = new byte[len / 2];
      for (int i = 0; i &lt; len; i += 2) {
          data[i / 2] = (byte)((Character.digit(s.charAt(i), 16) &lt;&lt; 4) +
              Character.digit(s.charAt(i + 1), 16));
      }
      return data;
  }
  private IllegalStateException fail(Exception e) {
      return new IllegalStateException(e);
  }
  </code></pre></li>
  <li><p>Decryption</p>
  
  <p>params:
  (same as in above java code)</p>
  
  <p>code:</p>
  
  <pre><code>var cipherParams = CryptoJS.lib.CipherParams.create({
    ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
  });
  
  var decrypted = CryptoJS.AES.decrypt(
     cipherParams,
     key,
     { iv: CryptoJS.enc.Hex.parse(iv) });
  
  var plaintext = decrypted.toString(CryptoJS.enc.Utf8);
  </code></pre></li>
  </ol>