package org.apache.pdfbox.pdmodel.encryption; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.spec.IvParameterSpec; import org.apache.pdfbox.exceptions.CryptographyException; public abstract class BaseAesImplementation extends BaseEncryptionImplementation { public static final int IV_LENGTH = 16; @Override protected String algorithmFor(final Key key) { return "AES/CBC/PKCS5Padding"; } @Override public InputStream decrypt(final Key key, final InputStream encrypted) throws CryptographyException, IOException { final byte[] iv = new byte[IV_LENGTH]; final int read = encrypted.read(iv); if (read != IV_LENGTH) { throw new IOException("unable to read initialization vector expected: " + IV_LENGTH + ", got: " + read); } final AlgorithmParameterSpec parameter = new IvParameterSpec(iv); return decrypt(key, parameter, encrypted); } @Override public InputStream encrypt(final Key key, final InputStream clear) throws CryptographyException, IOException { final SecureRandom secureRandom; try { secureRandom = SecureRandom.getInstance("SHA1PRNG"); } catch (final NoSuchAlgorithmException e) { throw new CryptographyException(e); } final byte[] iv = new byte[IV_LENGTH]; secureRandom.nextBytes(iv); final AlgorithmParameterSpec parameter = new IvParameterSpec(iv); final InputStream encrypted = encrypt(key, parameter, clear); return new SequenceInputStream(new ByteArrayInputStream(iv), encrypted); } }