4

How would I go about this? I have code encrypting a file using AES/CBC/PKCS5Padding in Java and as I understand form this picture: enter image description here

Partial decryption should be possible having part of ciphertext used by preceding block and the key. I have not found any examples of this, though. Any help?

The decrypting code is as fallows:

    //skip the IV (ivSize is 16 here) - IV was pretended to the stream during encryption
    data.skip(ivSize);
    //skip n blocks
    int n = 2;
    System.out.println("skipped: " + data.skip(n*16));

    byte[] iv = new byte[ivSize];
    //use next 16 bytes as IV
    data.read(iv);

    // Hashing key.
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(encryptionKey.getBytes(StandardCharsets.UTF_8));
    byte[] keyBytes = new byte[16];
    System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);

    Cipher cipher;
    try {
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
    } catch (GeneralSecurityException e) {
        throw new IOException(e);
    }

    CipherInputStream cis = new CipherInputStream(data, cipher);
    try {
        ByteStreams.copy(ByteStreams.limit(cis, limit), output);
    } catch (IOException exception) {
        // starting with java 8 the JVM wraps an IOException around a GeneralSecurityException
        // it should be safe to swallow a GeneralSecurityException
        if (!(exception.getCause() instanceof GeneralSecurityException)) {
            throw exception;
        }
        log.warning(exception.getMessage());
    } finally {
        cis.close();
    }
ed22
  • 1,127
  • 2
  • 14
  • 30
  • according the diagram you could use the previous ciphertext as IV of the block you intend to decipher – gusto2 Feb 16 '18 at 16:44
  • yes, I tried but got javax.crypto.BadPaddingException - skipped couple 16 byte blocks and used the following block as IV – ed22 Feb 16 '18 at 16:51
  • It decrypts but I get the above exception in the end. – ed22 Feb 16 '18 at 17:35
  • 1
    Questions seeking debugging help ("**why isn't this code working?**") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it **in the question itself**. Questions without **a clear problem statement** are not useful to other readers. See: [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). – President James K. Polk Feb 16 '18 at 20:00
  • 1
    As stated in the answer, Padding must **only be used for the last block of the entire encrypted message**, for all other blocks use no padding. `Cipher` must be instantiated with the correct padding option depending if it is the last block of the entire encrypted data or not – zaph Feb 17 '18 at 03:40
  • 1
    I have found working solutions https://gist.github.com/itarato/abef95871756970a9dad and http://www.itcsolutions.eu/wp-content/uploads/2011/08/BouncyCastleProvider_AES_CBC.java.txt that can be used to implement this. – ed22 Feb 21 '18 at 23:19
  • Grabbing something from GitHub is not understanding the problem/solution and just a short term fix. – zaph Feb 22 '18 at 21:04
  • @zaph Is it possible to decrypt a small part of a block? If a block has 16 bytes and I want to decrypt only the bytes between 4 and 10, i.e starting at 4º byte and ending at 10º byte. I'm doing padding start and padding end to the block to keep block size multiple but I get a weird output and not the decrypted part of plaintext itself. – Renan Coelho Jun 26 '22 at 22:17

1 Answers1

5

Yes it is possible.

You need to choose the "part" on a block boundary, a length that is a block size multiple and use the previous block as the IV. For AES the block size is 16-bytes.

If the "part" includes the last block specify the correct padding, otherwise specify no padding NoPadding: AES/CBC/NoPadding in this instance. This will eliminate a padding error. Only there last block is has/is padding.

Cipher must be instantiated with the correct padding option depending if it is the last block of the entire encrypted data or not.

See: PKCS#7 padding (sometimes called PKCS#5 in error) which is the most common padding.

zaph
  • 111,848
  • 21
  • 189
  • 228
  • Yes, in Java they decided to stay with "PKCS#5" even though PKCS#7 is used anyway... – ed22 Feb 17 '18 at 03:04
  • 1
    Clarifying: It was just the Java developers being lazy with naming, it is really PKCS#7, by definition PKCS#5 only supports 8-byte block sizes. From the answer link: "*PKCS#5 padding is identical to PKCS#7 padding, except that it has only been defined for block ciphers that use a 64-bit (8-byte) block size. In practice the two can be used interchangeably.*" – zaph Feb 17 '18 at 03:14