private void decrypt(InputStream in, OutputStream out, byte[] decryptionKey, byte[] iv) throws CryptoException { crypt(in, out, decryptionKey, iv, javax.crypto.Cipher.DECRYPT_MODE); }
public ByteSource decrypt(byte[] ciphertext, byte[] key) throws CryptoException { byte[] encrypted = ciphertext; //No IV, check if we need to read the IV from the stream: byte[] iv = null; if (isGenerateInitializationVectors(false)) { try { //We are generating IVs, so the ciphertext argument array is not actually 100% cipher text. Instead, it //is: // - the first N bytes is the initialization vector, where N equals the value of the // 'initializationVectorSize' attribute. // - the remaining bytes in the method argument (arg.length - N) is the real cipher text. //So we need to chunk the method argument into its constituent parts to find the IV and then use //the IV to decrypt the real ciphertext: int ivSize = getInitializationVectorSize(); int ivByteSize = ivSize / BITS_PER_BYTE; //now we know how large the iv is, so extract the iv bytes: iv = new byte[ivByteSize]; System.arraycopy(ciphertext, 0, iv, 0, ivByteSize); //remaining data is the actual encrypted ciphertext. Isolate it: int encryptedSize = ciphertext.length - ivByteSize; encrypted = new byte[encryptedSize]; System.arraycopy(ciphertext, ivByteSize, encrypted, 0, encryptedSize); } catch (Exception e) { String msg = "Unable to correctly extract the Initialization Vector or ciphertext."; throw new CryptoException(msg, e); } } return decrypt(encrypted, key, iv); }
public ByteSource encrypt(byte[] plaintext, byte[] key) { byte[] ivBytes = null; boolean generate = isGenerateInitializationVectors(false); if (generate) { ivBytes = generateInitializationVector(false); if (ivBytes == null || ivBytes.length == 0) { throw new IllegalStateException("Initialization vector generation is enabled - generated vector" + "cannot be null or empty."); } } return encrypt(plaintext, key, ivBytes, generate); }
protected SecureRandom ensureSecureRandom() { SecureRandom random = getSecureRandom(); if (random == null) { random = getDefaultSecureRandom(); } return random; }
public void decrypt(InputStream in, OutputStream out, byte[] key) throws CryptoException { decrypt(in, out, key, isGenerateInitializationVectors(true)); }
private javax.crypto.Cipher initNewCipher(int jcaCipherMode, byte[] key, byte[] iv, boolean streaming) throws CryptoException { javax.crypto.Cipher cipher = newCipherInstance(streaming); java.security.Key jdkKey = new SecretKeySpec(key, getAlgorithmName()); IvParameterSpec ivSpec = null; if (iv != null && iv.length > 0) { ivSpec = new IvParameterSpec(iv); } init(cipher, jcaCipherMode, jdkKey, ivSpec, getSecureRandom()); return cipher; } }
protected byte[] generateInitializationVector(boolean streaming) { int size = getInitializationVectorSize(); if (size <= 0) { String msg = "initializationVectorSize property must be greater than zero. This number is " + "typically set in the " + CipherService.class.getSimpleName() + " subclass constructor. " + "Also check your configuration to ensure that if you are setting a value, it is positive."; throw new IllegalStateException(msg); } if (size % BITS_PER_BYTE != 0) { String msg = "initializationVectorSize property must be a multiple of 8 to represent as a byte array."; throw new IllegalStateException(msg); } int sizeInBytes = size / BITS_PER_BYTE; byte[] ivBytes = new byte[sizeInBytes]; SecureRandom random = ensureSecureRandom(); random.nextBytes(ivBytes); return ivBytes; }
private void decrypt(InputStream in, OutputStream out, byte[] key, boolean ivPrepended) throws CryptoException { byte[] iv = null; //No Initialization Vector provided as a method argument - check if we need to read the IV from the stream: if (ivPrepended) { //we are generating IVs, so we need to read the previously-generated IV from the stream before //we decrypt the rest of the stream (we need the IV to decrypt): int ivSize = getInitializationVectorSize(); int ivByteSize = ivSize / BITS_PER_BYTE; iv = new byte[ivByteSize]; int read; try { read = in.read(iv); } catch (IOException e) { String msg = "Unable to correctly read the Initialization Vector from the input stream."; throw new CryptoException(msg, e); } if (read != ivByteSize) { throw new CryptoException("Unable to read initialization vector bytes from the InputStream. " + "This is required when initialization vectors are autogenerated during an encryption " + "operation."); } } decrypt(in, out, key, iv); }
private void crypt(InputStream in, OutputStream out, byte[] keyBytes, byte[] iv, int cryptMode) throws CryptoException { if (in == null) { throw new NullPointerException("InputStream argument cannot be null."); } if (out == null) { throw new NullPointerException("OutputStream argument cannot be null."); } javax.crypto.Cipher cipher = initNewCipher(cryptMode, keyBytes, iv, true); CipherInputStream cis = new CipherInputStream(in, cipher); int bufSize = getStreamingBufferSize(); byte[] buffer = new byte[bufSize]; int bytesRead; try { while ((bytesRead = cis.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } catch (IOException e) { throw new CryptoException(e); } }
/** * Returns a new {@link javax.crypto.Cipher Cipher} instance to use for encryption/decryption operations. The * Cipher's {@code transformationString} for the {@code Cipher}.{@link javax.crypto.Cipher#getInstance getInstance} * call is obtaind via the {@link #getTransformationString(boolean) getTransformationString} method. * * @param streaming {@code true} if the cipher instance will be used as a stream cipher, {@code false} if it will be * used as a block cipher. * @return a new JDK {@code Cipher} instance. * @throws CryptoException if a new Cipher instance cannot be constructed based on the * {@link #getTransformationString(boolean) getTransformationString} value. */ private javax.crypto.Cipher newCipherInstance(boolean streaming) throws CryptoException { String transformationString = getTransformationString(streaming); try { return javax.crypto.Cipher.getInstance(transformationString); } catch (Exception e) { String msg = "Unable to acquire a Java JCA Cipher instance using " + javax.crypto.Cipher.class.getName() + ".getInstance( \"" + transformationString + "\" ). " + getAlgorithmName() + " under this configuration is required for the " + getClass().getName() + " instance to function."; throw new CryptoException(msg, e); } }
/** * Functions as follows: * <ol> * <li>Creates a {@link #newCipherInstance(boolean) new JDK cipher instance}</li> * <li>Converts the specified key bytes into an {@link #getAlgorithmName() algorithm}-compatible JDK * {@link Key key} instance</li> * <li>{@link #init(javax.crypto.Cipher, int, java.security.Key, AlgorithmParameterSpec, SecureRandom) Initializes} * the JDK cipher instance with the JDK key</li> * <li>Calls the {@link #crypt(javax.crypto.Cipher, byte[]) crypt(cipher,bytes)} method to either encrypt or * decrypt the data based on the specified Cipher behavior mode * ({@link javax.crypto.Cipher#ENCRYPT_MODE Cipher.ENCRYPT_MODE} or * {@link javax.crypto.Cipher#DECRYPT_MODE Cipher.DECRYPT_MODE})</li> * </ol> * * @param bytes the bytes to crypt * @param key the key to use to perform the encryption or decryption. * @param iv the initialization vector to use for the crypt operation (optional, may be {@code null}). * @param mode the JDK Cipher behavior mode (Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE). * @return the resulting crypted byte array * @throws IllegalArgumentException if {@code bytes} are null or empty. * @throws CryptoException if Cipher initialization or the crypt operation fails */ private byte[] crypt(byte[] bytes, byte[] key, byte[] iv, int mode) throws IllegalArgumentException, CryptoException { if (key == null || key.length == 0) { throw new IllegalArgumentException("key argument cannot be null or empty."); } javax.crypto.Cipher cipher = initNewCipher(mode, key, iv, false); return crypt(cipher, bytes); }
/** * Returns the transformation string to use with the {@link javax.crypto.Cipher#getInstance} invocation when * creating a new {@code Cipher} instance. This default implementation always returns * {@link #getAlgorithmName() getAlgorithmName()}. Block cipher implementations will want to override this method * to support appending cipher operation modes and padding schemes. * * @param streaming if the transformation string is going to be used for a Cipher for stream-based encryption or not. * @return the transformation string to use with the {@link javax.crypto.Cipher#getInstance} invocation when * creating a new {@code Cipher} instance. */ protected String getTransformationString(boolean streaming) { return getAlgorithmName(); }
private javax.crypto.Cipher initNewCipher(int jcaCipherMode, byte[] key, byte[] iv, boolean streaming) throws CryptoException { javax.crypto.Cipher cipher = newCipherInstance(streaming); java.security.Key jdkKey = new SecretKeySpec(key, getAlgorithmName()); IvParameterSpec ivSpec = null; if (iv != null && iv.length > 0) { ivSpec = new IvParameterSpec(iv); } init(cipher, jcaCipherMode, jdkKey, ivSpec, getSecureRandom()); return cipher; } }
protected SecureRandom ensureSecureRandom() { SecureRandom random = getSecureRandom(); if (random == null) { random = getDefaultSecureRandom(); } return random; }
public void decrypt(InputStream in, OutputStream out, byte[] key) throws CryptoException { decrypt(in, out, key, isGenerateInitializationVectors(true)); }
protected byte[] generateInitializationVector(boolean streaming) { int size = getInitializationVectorSize(); if (size <= 0) { String msg = "initializationVectorSize property must be greater than zero. This number is " + "typically set in the " + CipherService.class.getSimpleName() + " subclass constructor. " + "Also check your configuration to ensure that if you are setting a value, it is positive."; throw new IllegalStateException(msg); } if (size % BITS_PER_BYTE != 0) { String msg = "initializationVectorSize property must be a multiple of 8 to represent as a byte array."; throw new IllegalStateException(msg); } int sizeInBytes = size / BITS_PER_BYTE; byte[] ivBytes = new byte[sizeInBytes]; SecureRandom random = ensureSecureRandom(); random.nextBytes(ivBytes); return ivBytes; }
private void decrypt(InputStream in, OutputStream out, byte[] key, boolean ivPrepended) throws CryptoException { byte[] iv = null; //No Initialization Vector provided as a method argument - check if we need to read the IV from the stream: if (ivPrepended) { //we are generating IVs, so we need to read the previously-generated IV from the stream before //we decrypt the rest of the stream (we need the IV to decrypt): int ivSize = getInitializationVectorSize(); int ivByteSize = ivSize / BITS_PER_BYTE; iv = new byte[ivByteSize]; int read; try { read = in.read(iv); } catch (IOException e) { String msg = "Unable to correctly read the Initialization Vector from the input stream."; throw new CryptoException(msg, e); } if (read != ivByteSize) { throw new CryptoException("Unable to read initialization vector bytes from the InputStream. " + "This is required when initialization vectors are autogenerated during an encryption " + "operation."); } } decrypt(in, out, key, iv); }
private void crypt(InputStream in, OutputStream out, byte[] keyBytes, byte[] iv, int cryptMode) throws CryptoException { if (in == null) { throw new NullPointerException("InputStream argument cannot be null."); } if (out == null) { throw new NullPointerException("OutputStream argument cannot be null."); } javax.crypto.Cipher cipher = initNewCipher(cryptMode, keyBytes, iv, true); CipherInputStream cis = new CipherInputStream(in, cipher); int bufSize = getStreamingBufferSize(); byte[] buffer = new byte[bufSize]; int bytesRead; try { while ((bytesRead = cis.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } catch (IOException e) { throw new CryptoException(e); } }
/** * Returns a new {@link javax.crypto.Cipher Cipher} instance to use for encryption/decryption operations. The * Cipher's {@code transformationString} for the {@code Cipher}.{@link javax.crypto.Cipher#getInstance getInstance} * call is obtaind via the {@link #getTransformationString(boolean) getTransformationString} method. * * @param streaming {@code true} if the cipher instance will be used as a stream cipher, {@code false} if it will be * used as a block cipher. * @return a new JDK {@code Cipher} instance. * @throws CryptoException if a new Cipher instance cannot be constructed based on the * {@link #getTransformationString(boolean) getTransformationString} value. */ private javax.crypto.Cipher newCipherInstance(boolean streaming) throws CryptoException { String transformationString = getTransformationString(streaming); try { return javax.crypto.Cipher.getInstance(transformationString); } catch (Exception e) { String msg = "Unable to acquire a Java JCA Cipher instance using " + javax.crypto.Cipher.class.getName() + ".getInstance( \"" + transformationString + "\" ). " + getAlgorithmName() + " under this configuration is required for the " + getClass().getName() + " instance to function."; throw new CryptoException(msg, e); } }
/** * Functions as follows: * <ol> * <li>Creates a {@link #newCipherInstance(boolean) new JDK cipher instance}</li> * <li>Converts the specified key bytes into an {@link #getAlgorithmName() algorithm}-compatible JDK * {@link Key key} instance</li> * <li>{@link #init(javax.crypto.Cipher, int, java.security.Key, AlgorithmParameterSpec, SecureRandom) Initializes} * the JDK cipher instance with the JDK key</li> * <li>Calls the {@link #crypt(javax.crypto.Cipher, byte[]) crypt(cipher,bytes)} method to either encrypt or * decrypt the data based on the specified Cipher behavior mode * ({@link javax.crypto.Cipher#ENCRYPT_MODE Cipher.ENCRYPT_MODE} or * {@link javax.crypto.Cipher#DECRYPT_MODE Cipher.DECRYPT_MODE})</li> * </ol> * * @param bytes the bytes to crypt * @param key the key to use to perform the encryption or decryption. * @param iv the initialization vector to use for the crypt operation (optional, may be {@code null}). * @param mode the JDK Cipher behavior mode (Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE). * @return the resulting crypted byte array * @throws IllegalArgumentException if {@code bytes} are null or empty. * @throws CryptoException if Cipher initialization or the crypt operation fails */ private byte[] crypt(byte[] bytes, byte[] key, byte[] iv, int mode) throws IllegalArgumentException, CryptoException { if (key == null || key.length == 0) { throw new IllegalArgumentException("key argument cannot be null or empty."); } javax.crypto.Cipher cipher = initNewCipher(mode, key, iv, false); return crypt(cipher, bytes); }