Assemblies
==========

Figure 7: Assembly class diagram

Operation
=========

An enumeration type for specifying the mode of operation of a Transformer instance, when wired into an Assembly.

This class cannot be instantiated; but its (only) two possible values can be used for constructing Transformer elements:

  * PRE_PROCESSING: to mean that the input data is first processed by the current Transformer before being passed to the rest of the chain; and

  * POST_PROCESSING: to mean that the input data is first passed to the rest of the chain, and the resulting bytes are then processed by the current Transformer.

Transformer
===========

A Transformer is an abstract representation of a two-way transformation that can be chained together with other instances of this type. Examples of such transformations in this library are:

  * CascadeTransformer that adapts an instance of a Cascade,

  * PaddingTransformer that adapts an instance of gnu.crypto.pad.IPad, and finally

  * DeflateTransformer that adapts a ZLib-based deflater/inflater algorithm implementation.

The special type LoopbackTransformer is also available and is implicitly (and silently) added to each instance of an Assembly.

A Transformer is characterized by the followings:

  * It can be chained to other instances, to form an Assembly.

  * When configured in an Assembly, it can be set to apply its internal transformation on the input data stream before (pre-processing) or after (post-processing) passing the input data to the next element in the chain. Note that the same type Transformer can be used in either pre-processing, or post-processing modes.

  * A special transformer --LoopbackTransformer-- is used to close the chain.

  * A useful type of Transformer --one we're interested in-- has internal buffers. The distinction between a casual push (update) operation, and the last one, allows to correctly flush any intermediate bytes that may exist in those buffers.

To allow wiring Transformer instances together, a minimal output size in bytes is necessary. The trivial case of a value of 1 for such attribute practically means that no output buffering, from the previous element, is needed --which is independent of buffering the input if the Transformer implementation itself is block-based.

This class exposes one class attribute and three Factory methods. They are:

 -- Variable: String DIRECTION
     The name of a property in the attributes map that is passed to the init method, representing the transformation's desired wiring direction. The mapped value should be a valid Direction value. If this attribute is omitted, Direction.FORWARD is used.

 -- Function: Transformer getCascadeTransformer (Cascade CASCADE)
     Returns the designated CASCADE instance wrapped in an Adapter for use as a Transformer.

 -- Function: Transformer getPaddingTransformer (IPad PADDING)
     Returns the designated PADDING instance wrapped in an Adapter for use as a Transformer.

 -- Function: Transformer getDeflateTransformer ()
     Returns a Transformer that underlies an implementation of the ZLib algorithm, able to deflate (compress) and inflate (decompress) data.

Concrete class instances of this abstract class, also expose the following instance methods:

 -- Function: void setMode (final Operation MODE)
     Sets the operational mode of this Transformer to the designated MODE value. Throws IllegalStateException if this instance has already been assigned an operational mode.

 -- Function: boolean isPreProcessing ()
     Returns true if this Transformer has been wired in pre-processing mode; returns false otherwise. Throws an IllegalStateException if this instance has not yet been assigned an operational mode.

 -- Function: boolean isPostProcessing ()
     Returns true if this Transformer has been wired in post-processing mode; returns false otherwise. Throws an IllegalStateException if this instance has not yet been assigned an operational mode.

 -- Function: void init (java.util.Map ATTRIBUTES) throws TransformerException
     Initializes the Transformer for operation with specific characteristics, indicated by the designated ATTRIBUTES. The latter being a set of name-value pairs that describes the desired future behavior of this instance. Throws an IllegalStateException if the instance is already initialized.

 -- Function: int currentBlockSize ()
     Returns the block-size of this Transformer. A value of 1 indicates that this instance is block-agnostic.

 -- Function: void reset ()
     Resets the Transformer for re-initialization and use with other characteristics. This method always succeeds.

 -- Function: byte[] update (byte B) throws TransformerException
     Convenience method that calls the method with same name and three arguments, using a byte array of length 1 whose contents are the designated byte B. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] update (byte[] IN) throws TransformerException
     Convenience method that calls the same method with three arguments. All bytes in IN, starting from index position 0 are considered. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws a TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] update (byte[] IN, int OFFSET, int LENGTH) throws TransformerException
     Returns the result of processing a designated LENGTH bytes from a given IN byte array, starting at position OFFSET. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate () throws TransformerException
     Convenience method that calls the same method with three arguments. A zero-long byte array is used. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate (byte B) throws TransformerException
     Convenience method that calls the method with same name and three arguments, using a byte array of length 1 whose contents are the designated byte B. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate (byte[] IN) throws TransformerException
     Convenience method that calls the same method with three arguments. All bytes in IN, starting from index position 0 are considered. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate (byte[] IN, int OFFSET, int LENGTH) throws TransformerException
     Returns the result of processing a designated LENGTH bytes from the given IN byte array, starting at index position OFFSET and signals, at the same time, that this is the last push operation on this Transformer. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

Assembly
========

An Assembly is a construction consisting of a chain of Transformer elements; each wired in pre- or post- operational mode. This chain is (always) terminated by one LoopbackTransformer element.

Once constructed, and correctly initialized, the bulk of the methods available on the Assembly are delegated to the head of the Transformer chain of the Assembly.

 -- Variable: String DIRECTION
     The name of a property in the attributes map that is passed to the init method, representing the assembly's desired wiring direction. The mapped value should be a valid Direction value. If this attribute is omitted, Direction.FORWARD is used.

 -- Function: boolean addPreTransformer (Transformer T)
     Adds the designated Transformer T, to the head of the current chain, and signals that it should operate in pre-processing mode; i.e. it should apply its internal transformation algorithm on the input data stream, before it passes that stream to the next element in the chain. Throws an IllegalArgumentException if the designated Transformer has a non-null tail; i.e. it is already an element of a chain.

 -- Function: boolean addPostTransformer (Transformer T)
     Adds the designated Transformer T, to the head of the current chain, and signals that it should operate in post-processing mode; i.e. it should apply its internal transformation algorithm on the input data stream, after it passes that stream to the next element in the chain. Throws an IllegalArgumentException if the designated Transformer has a non-null tail; i.e. it is already an element of a chain.

 -- Function: void init (java.util.Map ATTRIBUTES) throws TransformerException
     Initializes the Assembly for operation with specific characteristics, indicated by the designated ATTRIBUTES. The latter being a set of name-value pairs that describes the desired future behavior of this instance. Throws an IllegalStateException if the instance is already initialized.

 -- Function: void reset ()
     Resets the Assembly for re-initialization and use with other characteristics. This method always succeeds.

 -- Function: byte[] update (byte B) throws TransformerException
     Convenience method that calls the method with same name and three arguments, using a byte array of length 1 whose contents are the designated byte B. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] update (byte[] IN) throws TransformerException
     Convenience method that calls the same method with three arguments. All bytes in IN, starting from index position 0 are considered. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws a TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] update (byte[] IN, int OFFSET, int LENGTH) throws TransformerException
     Returns the result of processing a designated LENGTH bytes from a given IN byte array, starting at position OFFSET. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate () throws TransformerException
     Convenience method that calls the same method with three arguments. A zero-long byte array is used. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate (byte B) throws TransformerException
     Convenience method that calls the method with same name and three arguments, using a byte array of length 1 whose contents are the designated byte B. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate (byte[] IN) throws TransformerException
     Convenience method that calls the same method with three arguments. All bytes in IN, starting from index position 0 are considered. Returns the result of transformation. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

 -- Function: byte[] lastUpdate (byte[] IN, int OFFSET, int LENGTH) throws TransformerException
     Returns the result of processing a designated LENGTH bytes from the given IN byte array, starting at index position OFFSET and signals, at the same time, that this is the last push operation on this Transformer. Throws an IllegalStateException if the instance is not yet initialized. Throws an TransformerException if a transformation-related exception occurs during the operation.

Example
=======

The following example shows an Assembly that compresses its input data, before encrypting it with a Blowfish algorithm, in OFB mode, with PKCS7 padding.

     import gnu.crypto.Registry;
     import gnu.crypto.util.Util;
     import gnu.crypto.assembly.Assembly;
     import gnu.crypto.assembly.Cascade;
     import gnu.crypto.assembly.Direction;
     import gnu.crypto.assembly.Stage;
     import gnu.crypto.assembly.Transformer;
     import gnu.crypto.assembly.TransformerException;
     import gnu.crypto.cipher.Blowfish;
     import gnu.crypto.cipher.IBlockCipher;
     import gnu.crypto.mode.IMode;
     import gnu.crypto.mode.ModeFactory;
     import gnu.crypto.pad.IPad;
     import gnu.crypto.pad.PadFactory;

     HashMap attributes = new HashMap();
     HashMap modeAttributes = new HashMap();

     Cascade ofbBlowfish = new Cascade();
     Object modeNdx = ofbBlowfish.append(
         Stage.getInstance(
             ModeFactory.getInstance(Registry.OFB_MODE, new Blowfish(), 8),
             Direction.FORWARD));

     attributes.put(modeNdx, modeAttributes);
     IPad pkcs7 = PadFactory.getInstance(Registry.PKCS7_PAD);

     Assembly asm = new Assembly();
     asm.addPreTransformer(Transformer.getCascadeTransformer(ofbBlowfish));
     asm.addPreTransformer(Transformer.getPaddingTransformer(pkcs7));
     asm.addPreTransformer(Transformer.getDeflateTransformer());

     // plaintext and key material
     byte[] km = new byte[] { 0,  1,  2,  3,  4,  5,  6,  7,  8};
     byte[] iv = new byte[] {-1, -2, -3, -4, -5, -6, -7, -8, -9};
     byte[] pt = new byte[] { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,  11};
     byte[] tpt = new byte[11 * pt.length];

     // forward transformation
     modeAttributes.put(IBlockCipher.KEY_MATERIAL, km);
     modeAttributes.put(IMode.IV, iv);
     attributes.put(Assembly.DIRECTION, Direction.FORWARD);
     try
       {
         asm.init(attributes);
       }
     catch (TransformerException x)
       {
         x.printStackTrace(System.err);
       }

     byte[] ct = null;
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     try
       {
         for (int i = 0; i < 10; i++)
           { // transform in parts of 12-byte a time
             System.arraycopy(pt, 0, tpt, i * pt.length, pt.length);
             ct = asm.update(pt);
             baos.write(ct, 0, ct.length);
           }
       }
     catch (TransformerException x)
       {
         x.printStackTrace(System.err);
       }

     try
       {
         System.arraycopy(pt, 0, tpt, 10 * pt.length, pt.length);
         ct = asm.lastUpdate(pt);
       }
     catch (TransformerException x)
       {
         x.printStackTrace(System.err);
       }

     baos.write(ct, 0, ct.length);
     ct = baos.toByteArray();

     // reversed transformation
     attributes.put(Assembly.DIRECTION, Direction.REVERSED);
     try
       {
         asm.init(attributes);
       }
     catch (TransformerException x)
       {
         x.printStackTrace(System.err);
       }

     byte[] ot = null;
     try
       {
         ot = asm.lastUpdate(ct); // transform the lot in one go
       }
     catch (TransformerException x)
       {
         x.printStackTrace(System.err);
       }