org.bouncycastle.crypto.modes.KCTRBlockCipher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-ext-debug-jdk18on Show documentation
Show all versions of bcprov-ext-debug-jdk18on Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for Java 1.8 and later with debug enabled.
The newest version!
package org.bouncycastle.crypto.modes;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
/**
* Implementation of DSTU7624 CTR mode
*/
public class KCTRBlockCipher
extends StreamBlockCipher
{
private byte[] iv;
private byte[] ofbV;
private byte[] ofbOutV;
private int byteCount;
private boolean initialised;
private BlockCipher engine;
public KCTRBlockCipher(BlockCipher engine)
{
super(engine);
this.engine = engine;
this.iv = new byte[engine.getBlockSize()];
this.ofbV = new byte[engine.getBlockSize()];
this.ofbOutV = new byte[engine.getBlockSize()];
}
public void init(boolean forEncryption, CipherParameters params)
throws IllegalArgumentException
{
this.initialised = true;
if (params instanceof ParametersWithIV)
{
ParametersWithIV ivParam = (ParametersWithIV)params;
byte[] iv = ivParam.getIV();
int diff = this.iv.length - iv.length;
Arrays.fill(this.iv, (byte)0);
System.arraycopy(iv, 0, this.iv, diff, iv.length);
params = ivParam.getParameters();
}
else
{
throw new IllegalArgumentException("invalid parameter passed");
}
if (params != null)
{
engine.init(true, params);
}
reset();
}
public String getAlgorithmName()
{
return engine.getAlgorithmName() + "/KCTR";
}
public int getBlockSize()
{
return engine.getBlockSize();
}
protected byte calculateByte(byte b)
{
if (byteCount == 0)
{
incrementCounterAt(0);
checkCounter();
engine.processBlock(ofbV, 0, ofbOutV, 0);
return (byte)(ofbOutV[byteCount++] ^ b);
}
byte rv = (byte)(ofbOutV[byteCount++] ^ b);
if (byteCount == ofbV.length)
{
byteCount = 0;
}
return rv;
}
public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
throws DataLengthException, IllegalStateException
{
if (in.length - inOff < getBlockSize())
{
throw new DataLengthException("input buffer too short");
}
if (out.length - outOff < getBlockSize())
{
throw new OutputLengthException("output buffer too short");
}
processBytes(in, inOff, getBlockSize(), out, outOff);
return getBlockSize();
}
public void reset()
{
if (initialised)
{
engine.processBlock(this.iv, 0, ofbV, 0);
}
engine.reset();
byteCount = 0;
}
private void incrementCounterAt(int pos)
{
int i = pos;
while (i < ofbV.length)
{
if (++ofbV[i++] != 0)
{
break;
}
}
}
private void checkCounter()
{
// TODO:
// if the IV is the same as the blocksize we assume the user knows what they are doing
// if (IV.length < ofbV.length)
// {
// for (int i = 0; i != IV.length; i++)
// {
// if (ofbV[i] != IV[i])
// {
// throw new IllegalStateException("Counter in KCTR mode out of range.");
// }
// }
// }
}
}