title: How to use Bouncy Castle lightweight API with AES and PBE
body: <p>I have a block of ciphertext that was created using the JCE algorithim "PBEWithSHA256And256BitAES-CBC-BC". The provider is BouncyCastle. What I'd like to do it decrypt this ciphertext using the BouncyCastle lightweight API. I don't want to use JCE because that requires installing the Unlimited Strength Jurisdiction Policy Files.</p>
  
  <p>Documentation seems to be thin on the ground when it comes to using BC with PBE and AES.</p>
  
  <p>Here's what I have so far. The decryption code runs without exception but returns rubbish.</p>
  
  <p>The encryption code,</p>
  
  <pre><code>String password = "qwerty";
  String plainText = "hello world";
  
  byte[] salt = generateSalt();
  byte[] cipherText = encrypt(plainText, password.toCharArray(), salt);
  
  private static byte[] generateSalt() throws NoSuchAlgorithmException {
      byte salt[] = new byte[8];
      SecureRandom saltGen = SecureRandom.getInstance("SHA1PRNG");
      saltGen.nextBytes(salt);
      return salt;
  }
  
  private static byte[] encrypt(String plainText, char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
      Security.addProvider(new BouncyCastleProvider());
  
      PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
  
      PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
      SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
      SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
  
      Cipher encryptionCipher = Cipher.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
      encryptionCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
  
      return encryptionCipher.doFinal(plainText.getBytes());
  }
  </code></pre>
  
  <p>The decryption code,</p>
  
  <pre><code>byte[] decryptedText = decrypt(cipherText, password.getBytes(), salt);
  
  private static byte[] decrypt(byte[] cipherText, byte[] password, byte[] salt) throws DataLengthException, IllegalStateException, InvalidCipherTextException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
      BlockCipher engine = new AESEngine();
      CBCBlockCipher cipher = new CBCBlockCipher(engine);
  
      PKCS5S1ParametersGenerator keyGenerator = new PKCS5S1ParametersGenerator(new SHA256Digest());
      keyGenerator.init(password, salt, 20);
  
      CipherParameters keyParams = keyGenerator.generateDerivedParameters(256);
      cipher.init(false, keyParams);
  
      byte[] decryptedBytes = new byte[cipherText.length];
      int numBytesCopied = cipher.processBlock(cipherText, 0, decryptedBytes, 0);
  
      return decryptedBytes;
  }
  </code></pre>