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

org.refcodes.forwardsecrecy.AbstractDecryptionService Maven / Gradle / Ivy

The newest version!
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// =============================================================================
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// together with the GPL linking exception applied; as being applied by the GNU
// Classpath ("http://www.gnu.org/software/classpath/license.html")
// =============================================================================
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// =============================================================================
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.forwardsecrecy;

import java.util.ArrayList;
import java.util.List;

import org.refcodes.forwardsecrecy.SignatureVerificationException.SignatureVerificationRuntimeException;

/**
 * Abstract base implementation for non abstract {@link DecryptionService}
 * implementations.
 */
public abstract class AbstractDecryptionService implements DecryptionService {

	// /////////////////////////////////////////////////////////////////////////
	// CONSTANTS:
	// /////////////////////////////////////////////////////////////////////////

	protected static long EXPIRE_TIME_NEVER = -1;
	protected static long EXPIRE_TIME_IMMEDIATELY = 0;

	// /////////////////////////////////////////////////////////////////////////
	// VARIABLES:
	// /////////////////////////////////////////////////////////////////////////

	private final DecryptionServer _decryptionServer;
	private final String _namespace;
	private long _cipherVersionsExpireTimeMillis;
	private long _cipherVersionsLastLoadedTime = EXPIRE_TIME_IMMEDIATELY;
	private List _cipherVersions;

	// /////////////////////////////////////////////////////////////////////////
	// CONSTRUCTORS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Constructs the service with the required services and configuration. The
	 * cipher versions expire time is set to 0 (expire immediately). See
	 * {@link #setCipherVersionsExpireTimeMillis(long)}.
	 * 
	 * @param aNamespace The name space to which service belongs
	 * @param aDecryptionServer The server to which the service is being
	 *        "connected"
	 * @param aCipherVersionsExpireTimeMillis The time in milliseconds after
	 *        which them loaded cipher versions expire and are reloaded. A value
	 *        of 0 indicates that them cipher versions expire immediately
	 *        (default). A value of -1 indicate that them cipher versions expire
	 *        never.
	 */
	public AbstractDecryptionService( String aNamespace, DecryptionServer aDecryptionServer, long aCipherVersionsExpireTimeMillis ) {
		_namespace = aNamespace;
		_decryptionServer = aDecryptionServer;
	}

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List getCipherVersions() {
		if ( _cipherVersionsExpireTimeMillis == EXPIRE_TIME_NEVER && _cipherVersions != null ) {
			return _cipherVersions;
		}
		final long theCurrentTimeMs = System.currentTimeMillis();
		// Determine whether to reload the cipher versions:
		if ( isLoadEncryptedCipherVersions( theCurrentTimeMs ) ) {
			synchronized ( this ) {
				// In case of thread race conditions:
				if ( isLoadEncryptedCipherVersions( theCurrentTimeMs ) ) {

					final List theEncryptedCipherVersions;
					try {
						final String theMessage = createMessage();
						final String theSignature = toSignature( theMessage );

						// @formatter:off
						// ------------------------------------------
						// Remove log in productive environment:
						// ------------------------------------------
						// System.out.println( "Message = " + theMessage );
						// System.out.println( "Signature = " + theSignature );
						// ------------------------------------------
						// @formatter:on

						theEncryptedCipherVersions = _decryptionServer.getCipherVersions( _namespace, theMessage, theSignature );
					}
					catch ( SignatureVerificationException e ) {
						throw new SignatureVerificationRuntimeException( "Cannot verify the signature!", e );
					}

					final List theCipherVersions = new ArrayList<>();

					// @formatter:off
					// -------------------------------------------------
					// Remove these log messages when done implementing!
					// -------------------------------------------------
					// LOGGER.info( "=== ENCRYPTED cipher versions FROM LIST ===" );
					// for ( CipherVersion eCipherVersion : theEncryptedCipherVersions ) {
					//	LOGGER.log( Level.FINE,  eCipherVersion.getUniversalId() + " --> " + TextUtility.toFixedLength( eCipherVersion.getCipher(), 10, '.', TextUtility.Direction.FROM_RIGHT_TO_LEFT ) + " (with length <" + eCipherVersion.getCipher().length() + ">) ..." );
					// }
					// -------------------------------------------------
					// @formatter:on

					for ( CipherVersion eCipherVersion : theEncryptedCipherVersions ) {
						theCipherVersions.add( toDecryptedCipherVersion( eCipherVersion ) );
					}

					// Update cipher versions:
					_cipherVersions = theCipherVersions;
					_cipherVersionsLastLoadedTime = System.currentTimeMillis();
				}
			}
		}
		return _cipherVersions;
	}

	/**
	 * Returns the the expire time (in milliseconds) after which once loaded
	 * cipher versions expire. A value of 0 indicates that them cipher versions
	 * are always reloaded upon accessing the cipher versions (default). A value
	 * of -1 indicates that the cipher versions are just loaded once and then
	 * never reloaded (them never expire).
	 * 
	 * @return The time in milliseconds after which them loaded cipher versions
	 *         expire and are reloaded. A value of 0 indicates that them cipher
	 *         versions expire immediately (default). A value of -1 indicate
	 *         that them cipher versions expire never.
	 */
	public long getCipherVersionsExpireTimeMillis() {
		return _cipherVersionsExpireTimeMillis;
	}

	/**
	 * Injection method for setting the the expire time (in milliseconds) after
	 * which once loaded cipher versions expire. A value of 0 indicates that
	 * them cipher versions are always reloaded upon accessing the cipher
	 * versions (default). A value of -1 indicates that the cipher versions are
	 * just loaded once and then never reloaded (them never expire).
	 * 
	 * @param aCipherVersionsExpireTimeMillis The time in milliseconds after
	 *        which them loaded cipher versions expire and are reloaded. A value
	 *        of 0 indicates that them cipher versions expire immediately
	 *        (default). A value of -1 indicate that them cipher versions expire
	 *        never.
	 */
	public void setCipherVersionsExpireTimeMillis( long aCipherVersionsExpireTimeMillis ) {
		_cipherVersionsExpireTimeMillis = aCipherVersionsExpireTimeMillis;
	}

	/**
	 * Builder method for the {@link #setCipherVersionsExpireTimeMillis(long)}
	 * method.
	 * 
	 * @param aCipherVersionsExpireTimeMillis The time in milliseconds after
	 *        which them loaded cipher versions expire and are reloaded
	 *        (default). A value of 0 indicates that them cipher versions expire
	 *        immediately. A value of -1 indicate that them cipher versions
	 *        expire never.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	public DecryptionService withCipherVersionsExpireTimeMillis( long aCipherVersionsExpireTimeMillis ) {
		setCipherVersionsExpireTimeMillis( aCipherVersionsExpireTimeMillis );
		return this;
	}

	// /////////////////////////////////////////////////////////////////////////
	// HELPER:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Determine whether to load the encrypted cipher versions from the
	 * decryption server.
	 * 
	 * @param aCurrentTimeMillis The current time to use when determining
	 *        whether to load or not.
	 * 
	 * @return True in case the cipher versions are to be loaded, else false.
	 */
	private boolean isLoadEncryptedCipherVersions( long aCurrentTimeMillis ) {
		// @formatter:off
		return (_cipherVersionsExpireTimeMillis == EXPIRE_TIME_IMMEDIATELY) || _cipherVersions == null || (_cipherVersionsExpireTimeMillis > 0 && aCurrentTimeMillis - _cipherVersionsExpireTimeMillis > _cipherVersionsLastLoadedTime);
		// @formatter:on
	}

	// /////////////////////////////////////////////////////////////////////////
	// HOOK METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Creates a signature for the given aMessage.
	 * 
	 * @param aMessage The aMessage for which a signature is to be generated
	 * 
	 * @return The signature for the aMessage
	 */
	protected abstract String toSignature( String aMessage );

	/**
	 * Creates a aMessage for which a signature is to be created in order to
	 * authenticate for the retrieval of the cipher versions. A decryption
	 * server should deny any requests to get cipher versions in case the same
	 * aMessage is used twice.
	 * 
	 * @return The aMessage
	 */
	protected abstract String createMessage();

	/**
	 * Hook factory method to be implemented by subclasses. The provided cipher
	 * is to be decrypted (e.g. with the private key of an asymmetric encryption
	 * approach) so that an decryption server only receives encrypted data.
	 * 
	 * @param  The type of the {@link CipherVersion} to be used.
	 * @param aEncyrptedCipherVersion The {@link CipherVersion} to be decrypted.
	 * 
	 * @return The decrypted {@link CipherVersion}.
	 */
	protected abstract  CV toDecryptedCipherVersion( CV aEncyrptedCipherVersion );
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy