Encrypt in python and decrypt in Java with AES-CFB
<p>I am aware of a question very similar to this (<a href="http://stackoverflow.com/questions/10440777/how-do-i-encrypt-in-python-and-decrypt-in-java">How do I encrypt in Python and decrypt in Java?</a>) but I have a different problem.</p>

<p>My problem is, I am not able to decrypt in Java correctly. Despite using the correct key and IV, I still get garbage characters after decryption. I don't have any compile/run-time errors or exceptions in Java so I believe I am using the right parameters for decryption.</p>

<p>Python Encryption Code - </p>

<pre><code>from Crypto.Cipher import AES
import base64
key = '0123456789012345'
iv = 'RandomInitVector'
raw = 'samplePlainText'
cipher = AES.new(key,AES.MODE_CFB,iv)
encrypted = base64.b64encode(cipher.encrypt(raw))
</code></pre>

<p>Java Decryption Code - </p>

<pre><code>private static String KEY = "0123456789012345";
public static String decrypt(String encrypted_encoded_string) throws NoSuchAlgorithmException, NoSuchPaddingException,
    InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

      String plain_text = "";
      try{
          byte[] encrypted_decoded_bytes = Base64.getDecoder().decode(encrypted_encoded_string);
          String encrypted_decoded_string = new String(encrypted_decoded_bytes);
          String iv_string = encrypted_decoded_string.substring(0,16); //IV is retrieved correctly.

          IvParameterSpec iv = new IvParameterSpec(iv_string.getBytes());
          SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");

          Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
          cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

          plain_text = new String(cipher.doFinal(encrypted_decoded_bytes));//Returns garbage characters
          return plain_text;

      }  catch (Exception e) {
            System.err.println("Caught Exception: " + e.getMessage());
      }

      return plain_text;
 }
</code></pre>

<p>Is there anything obvious that I am missing?</p>

<p>The <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_.28CFB.29" rel="nofollow">Cipher Feedback (CFB) mode of operation</a> is a family of modes. It is parametrized by the segment size (or register size). PyCrypto has a default <a href="https://github.com/dlitz/pycrypto/blob/v2.6.1/src/block_template.c#L182" rel="nofollow">segment size of 8 bit</a> and Java (actually OpenJDK) has a default segment size the <a href="http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/com/sun/crypto/provider/CipherCore.java#228" rel="nofollow">same as the block size</a> (128 bit for AES).</p>

<p>If you want CFB-128 in pycrypto, you can use <code>AES.new(key, AES.MODE_CFB, iv, segment_size=128)</code>. If you want CFB-8 in Java, you can use <code>Cipher.getInstance("AES/CFB8/NoPadding");</code>.</p>

<hr>

<p>Now that we have that out the way, you have other problems:</p>

<ul>
<li><p>Always specify the character set you're using, because it can change between different JVMs: <code>new String(someBytes, "UTF-8")</code> and <code>someString.getBytes("UTF-8")</code>. When you do, be consistent.</p></li>
<li><p>Never use a String to store binary data (<code>new String(encrypted_decoded_bytes);</code>). You can copy the bytes directly: <code>IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(encrypted_decoded_bytes, 16));</code> and <code>cipher.doFinal(Arrays.copyOfRange(encrypted_decoded_bytes, 16, encrypted_decoded_bytes.length))</code>.</p></li>
<li><p>In Java, you're assuming that the IV is written in front of the ciphertext and then encoded together, but in Python, you're never doing anything with the IV. I guess you posted incomplete code.</p></li>
<li><p>It is crucial for CFB mode to use a <strong>different</strong> IV every time if the key stays the same. If you don't change the IV for every encryption, you will create a multi-time pad which enables an attacker to deduce the plaintext even without knowing the key.</p></li>
</ul>

java python encryption pycrypto cfb-mode