ISO9797Alg3Macpublic class ISO9797Alg3Mac extends Object implements org.bouncycastle.crypto.MacDES based CBC Block Cipher MAC according to ISO9797, algorithm 3 (ANSI X9.19 Retail MAC)
This could as well be derived from CBCBlockCipherMac, but then the property mac in the base
class must be changed to protected |
Fields Summary |
---|
private byte[] | mac | private byte[] | buf | private int | bufOff | private org.bouncycastle.crypto.BlockCipher | cipher | private org.bouncycastle.crypto.paddings.BlockCipherPadding | padding | private int | macSize | private org.bouncycastle.crypto.params.KeyParameter | lastKey2 | private org.bouncycastle.crypto.params.KeyParameter | lastKey3 |
Constructors Summary |
---|
public ISO9797Alg3Mac(org.bouncycastle.crypto.BlockCipher cipher)create a Retail-MAC based on a CBC block cipher. This will produce an
authentication code of the length of the block size of the cipher.
this(cipher, cipher.getBlockSize() * 8, null);
| public ISO9797Alg3Mac(org.bouncycastle.crypto.BlockCipher cipher, org.bouncycastle.crypto.paddings.BlockCipherPadding padding)create a Retail-MAC based on a CBC block cipher. This will produce an
authentication code of the length of the block size of the cipher.
this(cipher, cipher.getBlockSize() * 8, padding);
| public ISO9797Alg3Mac(org.bouncycastle.crypto.BlockCipher cipher, int macSizeInBits)create a Retail-MAC based on a block cipher with the size of the
MAC been given in bits. This class uses single DES CBC mode as the basis for the
MAC generation.
Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
or 16 bits if being used as a data authenticator (FIPS Publication 113),
and in general should be less than the size of the block cipher as it reduces
the chance of an exhaustive attack (see Handbook of Applied Cryptography).
this(cipher, macSizeInBits, null);
| public ISO9797Alg3Mac(org.bouncycastle.crypto.BlockCipher cipher, int macSizeInBits, org.bouncycastle.crypto.paddings.BlockCipherPadding padding)create a standard MAC based on a block cipher with the size of the
MAC been given in bits. This class uses single DES CBC mode as the basis for the
MAC generation. The final block is decrypted and then encrypted using the
middle and right part of the key.
Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
or 16 bits if being used as a data authenticator (FIPS Publication 113),
and in general should be less than the size of the block cipher as it reduces
the chance of an exhaustive attack (see Handbook of Applied Cryptography).
if ((macSizeInBits % 8) != 0)
{
throw new IllegalArgumentException("MAC size must be multiple of 8");
}
if (!(cipher instanceof DESEngine))
{
throw new IllegalArgumentException("cipher must be instance of DESEngine");
}
this.cipher = new CBCBlockCipher(cipher);
this.padding = padding;
this.macSize = macSizeInBits / 8;
mac = new byte[cipher.getBlockSize()];
buf = new byte[cipher.getBlockSize()];
bufOff = 0;
|
Methods Summary |
---|
public int | doFinal(byte[] out, int outOff)
int blockSize = cipher.getBlockSize();
if (padding == null)
{
//
// pad with zeroes
//
while (bufOff < blockSize)
{
buf[bufOff] = 0;
bufOff++;
}
}
else
{
if (bufOff == blockSize)
{
cipher.processBlock(buf, 0, mac, 0);
bufOff = 0;
}
padding.addPadding(buf, bufOff);
}
cipher.processBlock(buf, 0, mac, 0);
// Added to code from base class
DESEngine deseng = new DESEngine();
deseng.init(false, this.lastKey2);
deseng.processBlock(mac, 0, mac, 0);
deseng.init(true, this.lastKey3);
deseng.processBlock(mac, 0, mac, 0);
// ****
System.arraycopy(mac, 0, out, outOff, macSize);
reset();
return macSize;
| public java.lang.String | getAlgorithmName()
return "ISO9797Alg3";
| public int | getMacSize()
return macSize;
| public void | init(org.bouncycastle.crypto.CipherParameters params)
reset();
if (!(params instanceof KeyParameter))
{
throw new IllegalArgumentException(
"params must be an instance of KeyParameter");
}
// KeyParameter must contain a double or triple length DES key,
// however the underlying cipher is a single DES. The middle and
// right key are used only in the final step.
KeyParameter kp = (KeyParameter)params;
KeyParameter key1;
byte[] keyvalue = kp.getKey();
if (keyvalue.length == 16)
{ // Double length DES key
key1 = new KeyParameter(keyvalue, 0, 8);
this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
this.lastKey3 = key1;
}
else if (keyvalue.length == 24)
{ // Triple length DES key
key1 = new KeyParameter(keyvalue, 0, 8);
this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
this.lastKey3 = new KeyParameter(keyvalue, 16, 8);
}
else
{
throw new IllegalArgumentException(
"Key must be either 112 or 168 bit long");
}
cipher.init(true, key1);
| public void | reset()Reset the mac generator.
/*
* clean the buffer.
*/
for (int i = 0; i < buf.length; i++)
{
buf[i] = 0;
}
bufOff = 0;
/*
* reset the underlying cipher.
*/
cipher.reset();
| public void | update(byte in)
int resultLen = 0;
if (bufOff == buf.length)
{
resultLen = cipher.processBlock(buf, 0, mac, 0);
bufOff = 0;
}
buf[bufOff++] = in;
| public void | update(byte[] in, int inOff, int len)
if (len < 0)
{
throw new IllegalArgumentException("Can't have a negative input length!");
}
int blockSize = cipher.getBlockSize();
int resultLen = 0;
int gapLen = blockSize - bufOff;
if (len > gapLen)
{
System.arraycopy(in, inOff, buf, bufOff, gapLen);
resultLen += cipher.processBlock(buf, 0, mac, 0);
bufOff = 0;
len -= gapLen;
inOff += gapLen;
while (len > blockSize)
{
resultLen += cipher.processBlock(in, inOff, mac, 0);
len -= blockSize;
inOff += blockSize;
}
}
System.arraycopy(in, inOff, buf, bufOff, len);
bufOff += len;
|
|