package org.bouncycastle.crypto.modes;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithIV;

Implements the Segmented Integer Counter (SIC) mode on top of a simple block cipher. This mode is also known as CTR mode.
/** * Implements the Segmented Integer Counter (SIC) mode on top of a simple * block cipher. This mode is also known as CTR mode. */
public class SICBlockCipher implements BlockCipher { private final BlockCipher cipher; private final int blockSize; private byte[] IV; private byte[] counter; private byte[] counterOut;
Basic constructor.
Params:
  • c – the block cipher to be used.
/** * Basic constructor. * * @param c the block cipher to be used. */
public SICBlockCipher(BlockCipher c) { this.cipher = c; this.blockSize = cipher.getBlockSize(); this.IV = new byte[blockSize]; this.counter = new byte[blockSize]; this.counterOut = new byte[blockSize]; }
return the underlying block cipher that we are wrapping.
Returns:the underlying block cipher that we are wrapping.
/** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */
public BlockCipher getUnderlyingCipher() { return cipher; } public void init( boolean forEncryption, //ignored by this CTR mode CipherParameters params) throws IllegalArgumentException { if (params instanceof ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)params; byte[] iv = ivParam.getIV(); System.arraycopy(iv, 0, IV, 0, IV.length); reset(); cipher.init(true, ivParam.getParameters()); } else { throw new IllegalArgumentException("SIC mode requires ParametersWithIV"); } } public String getAlgorithmName() { return cipher.getAlgorithmName() + "/SIC"; } public int getBlockSize() { return cipher.getBlockSize(); } public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { cipher.processBlock(counter, 0, counterOut, 0); // // XOR the counterOut with the plaintext producing the cipher text // for (int i = 0; i < counterOut.length; i++) { out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]); } int carry = 1; for (int i = counter.length - 1; i >= 0; i--) { int x = (counter[i] & 0xff) + carry; if (x > 0xff) { carry = 1; } else { carry = 0; } counter[i] = (byte)x; } return counter.length; } public void reset() { System.arraycopy(IV, 0, counter, 0, counter.length); cipher.reset(); } }