gnu.crypto.assembly.package.html Maven / Gradle / Ivy
Provides a high-level API for combining and using GNU Crypto cipher, mode,
and padding primitives.
Package overview
This package describes two patterns implemneted by the GNU Crypto
library that allow users to combine the basic cipher (and other) primitives
into higher level components in order to offer more flexible functionalities.
These two patterns are: Cascade and Assembly.
The Cascade is a means of assembling block cipher Modes of
Operations into an ordered sequence of stages. A stage
is a representation of a Mode (of Operations) wired in a designated
direction: FORWARD or REVERSED. A Mode staged in the FORWARD
direction would encrypt input blocks, producing ciphertext, while the
same Mode, wired in the REVERSED direction would do the opposite; i.e.
decrypt an input text producing a plaintext.
In the simplest case, all stages in a Cascade have k-bit
keys, and the stage inputs and outputs are all n-bit quantities.
The stage ciphers may differ (general cascade of ciphers), or all be
identical (cascade of identical ciphers).
An Assembly is a construction of an ordered set of Transformer
objects. Each Transformer is wired to operate in PRE_PROCESSING or
POST_PROCESSING mode --the Transformer's operation. In
PRE_PROCESSING, the input is first processed by the Transformer
before being passed to the rest of the chain, while in POST_PROCESSING
state, the Transformer first passes the input to the rest of the
chain and only processes the output of the returned data.
Cascade pattern
The following diagram shows the important classes participating in the
Cascade pattern:
Here is an example of how a Cascade is used to construct a
DES-EDE symetric-key block cipher from three independent
DES cipher instances:
HashMap map = new HashMap();
HashMap map1 = new HashMap();
HashMap map2 = new HashMap();
HashMap map3 = new HashMap();
Cascade new3DES = new Cascade();
Object des1 = new3DES.append(
Stage.getInstance(
ModeFactory.getInstance(Registry.ECB_MODE, new DES(), 8),
Direction.FORWARD));
Object des2 = new3DES.append(
Stage.getInstance(
ModeFactory.getInstance(Registry.ECB_MODE, new DES(), 8),
Direction.REVERSED));
Object des3 = new3DES.append(
Stage.getInstance(
ModeFactory.getInstance(Registry.ECB_MODE, new DES(), 8),
Direction.FORWARD));
map.put(des1, map1);
map.put(des2, map2);
map.put(des3, map3);
map1.put(IBlockCipher.KEY_MATERIAL, key1material);
map2.put(IBlockCipher.KEY_MATERIAL, key2material);
map3.put(IBlockCipher.KEY_MATERIAL, key3material);
// encryption
map.put(Cascade.DIRECTION, Direction.FORWARD);
byte[] pt = ...; // some plaintext to encrypt
byte[] ct = new byte[pt.length]; // where ciphertext is returned
try
{
new3DES.init(map);
new3DES.update(pt, 0, ct, 0);
}
catch (InvalidKeyException x)
{
x.printStackTrace(System.err);
}
Assembly pattern
The following diagram shows the important classes participating in the
Assembly pattern:
Here is an example of how to compress and encrypt a stream of
plaintext:
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);
}