All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jasypt.encryption.pbe.PooledPBEByteEncryptor Maven / Gradle / Ivy

There is a newer version: 6.1.4
Show newest version
/*
 * =============================================================================
 * 
 *   Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org)
 * 
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * 
 * =============================================================================
 */
package org.jasypt.encryption.pbe;

import java.security.Provider;

import org.jasypt.commons.CommonUtils;
import org.jasypt.encryption.pbe.config.PBEConfig;
import org.jasypt.exceptions.AlreadyInitializedException;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.iv.IvGenerator;
import org.jasypt.salt.SaltGenerator;



/**
 * 

* Pooled implementation of {@link PBEByteEncryptor} that in fact contains * an array of {@link StandardPBEByteEncryptor} objects which are used * to attend encrypt and decrypt requests in round-robin. This should * result in higher performance in multiprocessor systems. *

*

* Configuration of this class is equivalent to that of * {@link StandardPBEByteEncryptor}. *

*

* This class is thread-safe. *

* * * @since 1.7 * * @author Daniel Fernández * */ public final class PooledPBEByteEncryptor implements PBEByteCleanablePasswordEncryptor { private final StandardPBEByteEncryptor firstEncryptor; private PBEConfig config = null; private int poolSize = 0; private boolean poolSizeSet = false; private StandardPBEByteEncryptor[] pool; private int roundRobin = 0; /* * Flag which indicates whether the encryptor has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /** * Creates a new instance of PooledStandardPBEByteEncryptor. */ public PooledPBEByteEncryptor() { super(); this.firstEncryptor = new StandardPBEByteEncryptor(); } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(PBEConfig config) { this.firstEncryptor.setConfig(config); this.config = config; } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public synchronized void setAlgorithm(String algorithm) { this.firstEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public synchronized void setPassword(String password) { this.firstEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public synchronized void setPasswordCharArray(char[] password) { this.firstEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public synchronized void setKeyObtentionIterations( int keyObtentionIterations) { this.firstEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public synchronized void setSaltGenerator(SaltGenerator saltGenerator) { this.firstEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public synchronized void setIvGenerator(final IvGenerator ivGenerator) { this.firstEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public synchronized void setProviderName(String providerName) { this.firstEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param provider the provider to be asked for the chosen algorithm */ public synchronized void setProvider(Provider provider) { this.firstEncryptor.setProvider(provider); } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter is required. *

* * @param poolSize size of the pool */ public synchronized void setPoolSize(final int poolSize) { CommonUtils.validateIsTrue(poolSize > 0, "Pool size be > 0"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.poolSize = poolSize; this.poolSizeSet = true; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null) { final Integer configPoolSize = this.config.getPoolSize(); this.poolSize = ((this.poolSizeSet) || (configPoolSize == null))? this.poolSize : configPoolSize.intValue(); } if (this.poolSize <= 0) { throw new IllegalArgumentException("Pool size must be set and > 0"); } this.pool = this.firstEncryptor.cloneAndInitializeEncryptor(this.poolSize); this.initialized = true; } } /** *

* Encrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the byte array message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public byte[] encrypt(final byte[] message) throws EncryptionOperationNotPossibleException { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].encrypt(message); } /** *

* Decrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the byte array message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public byte[] decrypt(final byte[] encryptedMessage) throws EncryptionOperationNotPossibleException { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].decrypt(encryptedMessage); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy