org.refcodes.forwardsecrecy.AbstractDecryptionService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refcodes-forwardsecrecy Show documentation
Show all versions of refcodes-forwardsecrecy Show documentation
Artifact for the refcodes forward secrecy framework design.
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 );
}